package org.sugr.gearshift.datasource;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.webkit.MimeTypeMap;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.sugr.gearshift.G;
import org.sugr.gearshift.R;
import org.sugr.gearshift.core.Torrent;
import org.sugr.gearshift.core.TransmissionSession;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class TorrentValues {
public ContentValues torrent;
public List<ContentValues> files;
public List<ContentValues> trackers;
public List<ContentValues> peers;
}
class TorrentCursorArgs {
public String selection;
public String[] selectionArgs;
public String orderBy;
}
public class DataSource {
private SQLiteDatabase database;
private SQLiteOpenHelper dbHelper;
private Context context;
/* Transmission stuff */
private static final int NEW_STATUS_RPC_VERSION = 14;
private TransmissionSession session;
public DataSource(Context context) {
setContext(context);
setHelper(new SQLiteHelper(context.getApplicationContext()));
}
public DataSource(Context context, SQLiteOpenHelper helper) {
setContext(context);
setHelper(helper);
}
public void open() {
synchronized (DataSource.class) {
database = dbHelper.getWritableDatabase();
}
}
public void close() {
synchronized (DataSource.class) {
dbHelper.close();
database = null;
}
}
public boolean isOpen() {
return database != null && database.isOpen();
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public void setHelper(SQLiteOpenHelper helper) {
this.dbHelper = helper;
}
public boolean updateSession(String profile, JsonParser parser) throws IOException {
if (!isOpen())
return false;
List<ContentValues> session = jsonToSessionValues(profile, parser);
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
for (ContentValues item : session) {
database.insertWithOnConflict(Constants.T_SESSION, null,
item, SQLiteDatabase.CONFLICT_REPLACE);
}
database.setTransactionSuccessful();
return true;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public TorrentStatus updateTorrents(String profile, JsonParser parser, boolean removeObsolete)
throws IOException {
if (!isOpen())
return null;
int[] idChanges = queryTorrentIdChanges();
int[] status = queryStatusCount();
if (session == null) {
session = getSession(profile);
}
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
List<String> validHashStrings = null;
if (removeObsolete) {
validHashStrings = new ArrayList<>();
}
/* Remove all trackers for the current profile, since they can change relative to a torrent */
removeAllTrackers(profile);
while (parser.nextToken() != JsonToken.END_ARRAY) {
TorrentValues values = jsonToTorrentValues(parser);
String hash = (String) values.torrent.get(Constants.C_HASH_STRING);
if (removeObsolete) {
validHashStrings.add(hash);
}
int updated = database.update(
Constants.T_TORRENT, values.torrent, Constants.C_HASH_STRING + " = ?",
new String[] { hash });
if (updated < 1) {
database.insertWithOnConflict(Constants.T_TORRENT, null,
values.torrent, SQLiteDatabase.CONFLICT_REPLACE);
}
ContentValues profileValues = new ContentValues();
profileValues.put(Constants.C_HASH_STRING, hash);
profileValues.put(Constants.C_PROFILE_ID, profile);
database.insertWithOnConflict(Constants.T_TORRENT_PROFILE, null,
profileValues, SQLiteDatabase.CONFLICT_IGNORE);
if (values.trackers != null) {
for (ContentValues tracker : values.trackers) {
Integer trackerId = (Integer) tracker.get(Constants.C_TRACKER_ID);
tracker.put(Constants.C_HASH_STRING, hash);
updated = database.update(Constants.T_TRACKER, tracker,
Constants.C_HASH_STRING + " = ? AND " + Constants.C_TRACKER_ID + " = ?",
new String[] { hash, trackerId.toString() });
if (updated < 1) {
database.insertWithOnConflict(Constants.T_TRACKER, null,
tracker, SQLiteDatabase.CONFLICT_REPLACE);
}
}
}
if (values.files != null) {
for (ContentValues file : values.files) {
Integer index = (Integer) file.get(Constants.C_FILE_INDEX);
file.put(Constants.C_HASH_STRING, hash);
updated = database.update(Constants.T_FILE, file,
Constants.C_HASH_STRING + " = ? AND " + Constants.C_FILE_INDEX + " = ?",
new String[] { hash, index.toString() });
if (updated < 1) {
database.insertWithOnConflict(Constants.T_FILE, null,
file, SQLiteDatabase.CONFLICT_REPLACE);
}
}
}
if (values.peers != null) {
for (ContentValues peer : values.peers) {
peer.put(Constants.C_HASH_STRING, hash);
database.insertWithOnConflict(Constants.T_PEER, null,
peer, SQLiteDatabase.CONFLICT_REPLACE);
}
}
}
if (removeObsolete) {
removeObsolete(profile, validHashStrings);
}
database.setTransactionSuccessful();
int[] updatedIdChanges = queryTorrentIdChanges();
int[] updatedStatus = queryStatusCount();
boolean added = false, removed = false, statusChanged = false;
boolean incompleteMetadata = !hasCompleteMetadata(profile);
if (idChanges != null && updatedIdChanges != null) {
added = idChanges[0] < updatedIdChanges[0];
removed = idChanges[0] > updatedIdChanges[0] || idChanges[1] < updatedIdChanges[1];
if (added || removed) {
statusChanged = true;
}
}
if (status != null && updatedStatus != null && status.length == updatedStatus.length) {
for (int i = 0; i < status.length && !statusChanged; ++i) {
statusChanged = status[i] != updatedStatus[i];
}
}
return new TorrentStatus(
added,
removed,
statusChanged,
incompleteMetadata
);
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public boolean removeTorrents(String... hashStrings) {
if (!isOpen())
return false;
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
for (String hash : hashStrings) {
removeTorrent(hash);
}
database.setTransactionSuccessful();
return true;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public boolean removeTorrents(String profile, int... ids) {
if (!isOpen())
return false;
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
for (int id : ids) {
removeTorrent(profile, id);
}
database.setTransactionSuccessful();
return true;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public boolean removeTrackers(String hashString, int... ids) {
if (!isOpen())
return false;
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
for (int id : ids) {
removeTracker(hashString, id);
}
database.setTransactionSuccessful();
return true;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
/* Transmission implementation */
public TransmissionSession getSession(String profile) {
if (!isOpen())
return null;
Cursor cursor = null;
try {
cursor = database.query(Constants.T_SESSION, new String[] {
Constants.C_NAME, Constants.C_VALUE_INTEGER,
Constants.C_VALUE_REAL, Constants.C_VALUE_TEXT
}, Constants.C_PROFILE_ID + " = ?", new String[] { profile }, null, null, null);
return cursorToSession(cursor);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public boolean hasExtraInfo(String profile) {
if (!isOpen())
return false;
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT count(" + Constants.T_FILE + ".rowid), count(CASE "
+ Constants.T_FILE + "." + Constants.C_NAME
+ " WHEN '' THEN 1 ELSE NULL END) FROM "
+ Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " JOIN " + Constants.T_FILE
+ " ON " + Constants.T_FILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?",
new String[] { profile }
);
cursor.moveToFirst();
return cursor.getInt(0) != 0 && cursor.getInt(1) == 0;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public boolean hasCompleteMetadata(String profile) {
if (!isOpen())
return false;
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT count(" + Constants.T_TORRENT + ".rowid) FROM "
+ Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_TOTAL_SIZE + " = 0 AND ("
+ Constants.C_STATUS + " = "
+ Torrent.Status.CHECKING
+ " OR "
+ Constants.C_STATUS + " = "
+ Torrent.Status.DOWNLOADING
+ " OR "
+ Constants.C_STATUS + " = "
+ Torrent.Status.SEEDING
+ ") AND " + Constants.C_PROFILE_ID + " = ?",
new String[] { profile }
);
cursor.moveToFirst();
return cursor.getInt(0) == 0;
} finally {
if (cursor != null)
cursor.close();
}
}
public String[] getUnnamedTorrentHashStrings(String profile) {
if (!isOpen())
return null;
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ " AND " + Constants.C_NAME + " = ''",
new String[] { profile }
);
String[] hashStrings = new String[cursor.getCount()];
int index = 0;
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
hashStrings[index++] = cursor.getString(0);
cursor.moveToNext();
}
return hashStrings;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public boolean addTorrent(String profile, int id, String name, String hash, String location) {
if (!isOpen())
return false;
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
ContentValues values = new ContentValues();
values.put(Constants.C_HASH_STRING, hash);
values.put(Constants.C_TORRENT_ID, id);
values.put(Constants.C_NAME, name);
values.put(Constants.C_STATUS, Torrent.Status.STOPPED);
values.put(Constants.C_ADDED_DATE, new Date().getTime() / 1000);
values.put(Constants.C_DOWNLOAD_DIR, location);
long result = database.insert(Constants.T_TORRENT, null, values);
if (result > -1) {
values = new ContentValues();
values.put(Constants.C_HASH_STRING, hash);
values.put(Constants.C_PROFILE_ID, profile);
result = database.insert(Constants.T_TORRENT_PROFILE, null, values);
}
database.setTransactionSuccessful();
return result > -1;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public boolean clearTorrentsForProfile(String profile) {
if (!isOpen())
return false;
synchronized (DataSource.class) {
database.beginTransactionNonExclusive();
try {
String[] args = new String[] { profile };
/* Delete all torrents that are only present for the given profile
DELETE FROM torrent
WHERE hash_string IN (
SELECT hash_string FROM torrent_profile t1 WHERE NOT EXISTS (
SELECT 1 FROM torrent_profile t2
WHERE t1.hash_string = t2.hash_string
AND t1.profile_id != t2.profile_id
) AND t1.profile_id = ?
)
*/
database.delete(Constants.T_TORRENT, Constants.C_HASH_STRING
+ " IN ("
+ " SELECT " + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TORRENT_PROFILE + " t1"
+ " WHERE NOT EXISTS ("
+ " SELECT 1"
+ " FROM " + Constants.T_TORRENT_PROFILE + " t2"
+ " WHERE t1." + Constants.C_HASH_STRING + " = t2." + Constants.C_HASH_STRING
+ " AND t1." + Constants.C_PROFILE_ID + " != t2." + Constants.C_PROFILE_ID
+ ")"
+ " AND t1." + Constants.C_PROFILE_ID + " = ?"
+ ")",
args);
database.delete(Constants.T_TORRENT_PROFILE, Constants.C_PROFILE_ID + " = ?", args);
database.delete(Constants.T_SESSION, Constants.C_PROFILE_ID + " = ?", args);
database.setTransactionSuccessful();
return true;
} finally {
if (database.inTransaction()) {
database.endTransaction();
}
}
}
}
public List<String> getTrackerAnnounceURLs(String profile) {
if (!isOpen())
return null;
List<String> urls = new ArrayList<>();
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT DISTINCT " + Constants.C_ANNOUNCE
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TRACKER
+ " ON " + Constants.T_TRACKER + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ " ORDER BY " + Constants.C_ANNOUNCE + " COLLATE NOCASE",
new String[] { profile }
);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
urls.add(cursor.getString(0));
cursor.moveToNext();
}
return urls;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public List<String> getTrackerAnnounceAuthorities(String profile) {
Set<String> authorities = new HashSet<>();
for (String url : getTrackerAnnounceURLs(profile)) {
try {
URI uri = new URI(url);
authorities.add(uri.getAuthority());
} catch (URISyntaxException ignored) {}
}
List<String> authorityList = new ArrayList<>(authorities);
Collections.sort(authorityList);
return authorityList;
}
public List<String> getDownloadDirectories(String profile) {
if (!isOpen())
return null;
List<String> directories = new ArrayList<>();
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT DISTINCT " + Constants.C_DOWNLOAD_DIR
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ " ORDER BY " + Constants.C_DOWNLOAD_DIR + " COLLATE NOCASE",
new String[] { profile }
);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
directories.add(cursor.getString(0));
cursor.moveToNext();
}
return directories;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public long[] getTrafficSpeed(String profile) {
if (!isOpen())
return null;
long[] speed = new long[2];
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT SUM(" + Constants.C_RATE_DOWNLOAD + "), SUM(" + Constants.C_RATE_UPLOAD + ")"
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?",
new String[] { profile }
);
cursor.moveToFirst();
speed[0] = cursor.getLong(0);
speed[1] = cursor.getLong(1);
return speed;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public Cursor getTorrentCursor(String profile, SharedPreferences prefs) {
if (!isOpen())
return null;
if (session == null) {
session = getSession(profile);
}
TorrentCursorArgs args = getTorrentCursorArgs(prefs);
Cursor cursor = getTorrentCursor(profile, args.selection, args.selectionArgs,
args.orderBy, false);
String search = prefs.getString(G.PREF_LIST_SEARCH, null);
if (!TextUtils.isEmpty(search)) {
MatrixCursor matrix = new MatrixCursor(cursor.getColumnNames());
String prefixString = search.toLowerCase(Locale.getDefault());
Pattern prefixPattern = null;
int hiPrimary = context.getResources().getColor(R.color.filter_highlight_primary);
int hiSecondary = context.getResources().getColor(R.color.filter_highlight_secondary);
if (prefixString.length() > 0) {
String[] split = prefixString.split("");
StringBuilder pattern = new StringBuilder();
for (int i = 0; i < split.length; i++) {
if (split[i].equals("")) {
continue;
}
pattern.append("\\Q").append(split[i]).append("\\E");
if (i < split.length - 1) {
pattern.append(".{0,2}?");
}
}
prefixPattern = Pattern.compile(pattern.toString());
}
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String name = Torrent.getName(cursor);
Matcher m = prefixPattern.matcher(name.toLowerCase(Locale.getDefault()));
if (m.find()) {
SpannableString spannedName = new SpannableString(name);
spannedName.setSpan(
new ForegroundColorSpan(hiPrimary),
m.start(),
m.start() + 1,
Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
if (m.end() - m.start() > 2) {
spannedName.setSpan(
new ForegroundColorSpan(hiSecondary),
m.start() + 1,
m.end() - 1,
Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
}
if (m.end() - m.start() > 1) {
spannedName.setSpan(
new ForegroundColorSpan(hiPrimary),
m.end() - 1,
m.end(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
}
name = Html.toHtml(spannedName);
MatrixCursor.RowBuilder row = matrix.newRow();
int index = 0;
for (String column : cursor.getColumnNames()) {
switch (column) {
case Constants.C_NAME:
row.add(name);
break;
case Constants.C_ID:
case Constants.C_STATUS:
case Constants.C_ERROR:
case Constants.C_SEED_RATIO_MODE:
row.add(cursor.getInt(index));
break;
case Constants.C_HASH_STRING:
case Constants.C_TRAFFIC_TEXT:
case Constants.C_STATUS_TEXT:
case Constants.C_ERROR_STRING:
case Constants.C_MIME_TYPE:
row.add(cursor.getString(index));
break;
case Constants.C_METADATA_PERCENT_COMPLETE:
case Constants.C_PERCENT_DONE:
case Constants.C_UPLOAD_RATIO:
case Constants.C_SEED_RATIO_LIMIT:
row.add(cursor.getFloat(index));
break;
default:
throw new IllegalStateException("Unexpected column: " + column);
}
++index;
}
}
cursor.moveToNext();
}
cursor.close();
return matrix;
}
/* Fill the cursor window */
cursor.getCount();
return cursor;
}
public Cursor getTorrentCursor(String profile, String selection, String[] selectionArgs,
String orderBy, boolean details) {
if (!isOpen())
return null;
String[] columnList = Constants.ColumnGroups.TORRENT_OVERVIEW;
if (details) {
columnList = G.concat(columnList, Constants.ColumnGroups.TORRENT_DETAILS);
}
String columns = Constants.T_TORRENT + ".rowid AS " + Constants.C_ID + ", "
+ Constants.T_TORRENT + "." + Constants.C_HASH_STRING + ", "
+ TextUtils.join(", ", columnList);
String query = "SELECT " + columns
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " AND " + Constants.T_TORRENT_PROFILE + "." + Constants.C_PROFILE_ID + " = ?";
if (selection != null && selection.length() > 0) {
query = query + " WHERE " + selection;
}
if (orderBy != null && orderBy.length() > 0) {
query = query + " ORDER BY " + orderBy;
}
return database.rawQuery(query, G.concat(new String[] { profile }, selectionArgs));
}
public TorrentNameStatus getTorrentNameStatus(String profile, String hash) {
if (!isOpen())
return null;
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT " + Constants.C_NAME + ", " + Constants.C_STATUS
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ " AND " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING + " = ?",
new String[] { profile, hash }
);
if (cursor.getCount() == 0) {
return null;
}
cursor.moveToFirst();
return new TorrentNameStatus(cursor.getString(0), cursor.getInt(1));
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public TorrentDetails getTorrentDetails(String profile, String hash) {
if (!isOpen())
return null;
String[] selectionArgs = new String[] { hash };
Cursor torrent = getTorrentCursor(profile,
Constants.T_TORRENT + "." + Constants.C_HASH_STRING + " = ?",
selectionArgs, null, true);
Cursor trackers = database.query(Constants.T_TRACKER, Constants.ColumnGroups.TRACKER,
Constants.C_HASH_STRING + " = ?", selectionArgs, null, null, null);
Cursor files = database.query(Constants.T_FILE, Constants.ColumnGroups.FILE,
Constants.C_HASH_STRING + " = ?", selectionArgs, null, null, null);
return new TorrentDetails(torrent, trackers, files);
}
protected TransmissionSession cursorToSession(Cursor cursor) {
session = new TransmissionSession();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String name = cursor.getString(0);
switch (name) {
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_ENABLED:
session.setAltSpeedLimitEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.ALT_DOWNLOAD_SPEED_LIMIT:
session.setAltDownloadSpeedLimit(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.ALT_UPLOAD_SPEED_LIMIT:
session.setAltUploadSpeedLimit(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_ENABLED:
session.setAltSpeedLimitTimeEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_BEGIN:
session.setAltSpeedTimeBegin(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_END:
session.setAltSpeedTimeEnd(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_DAY:
session.setAltSpeedTimeDay(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.BLOCKLIST_ENABLED:
session.setBlocklistEnabled(cursor.getInt(1) > 0);
break;
case "blocklist-size":
session.setBlocklistSize(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.BLOCKLIST_URL:
session.setBlocklistURL(cursor.getString(3));
break;
case TransmissionSession.SetterFields.DHT:
session.setDhtEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.ENCRYPTION:
session.setEncryption(cursor.getString(3));
break;
case TransmissionSession.SetterFields.CACHE_SIZE:
session.setCacheSize(cursor.getLong(1));
break;
case "config-dir":
session.setConfigDir(cursor.getString(3));
break;
case TransmissionSession.SetterFields.DOWNLOAD_DIR:
session.setDownloadDir(cursor.getString(3));
break;
case "download-dir-free-space":
session.setDownloadDirFreeSpace(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.DOWNLOAD_QUEUE_SIZE:
session.setDownloadQueueSize(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.DOWNLOAD_QUEUE_ENABLED:
session.setDownloadQueueEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.IDLE_SEEDING_LIMIT:
session.setIdleSeedingLimig(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.IDLE_SEEDING_LIMIT_ENABLED:
session.setIdleSeedingLimitEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.INCOMPLETE_DIR:
session.setIncompleteDir(cursor.getString(3));
break;
case TransmissionSession.SetterFields.INCOMPLETE_DIR_ENABLED:
session.setIncompleteDirEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.LOCAL_DISCOVERY:
session.setLocalDiscoveryEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.UTP:
session.setUtpEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.GLOBAL_PEER_LIMIT:
session.setGlobalPeerLimit(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.TORRENT_PEER_LIMIT:
session.setTorrentPeerLimit(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.PEER_EXCHANGE:
session.setPeerExchangeEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.PEER_PORT:
session.setPeerPort(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.RANDOM_PORT:
session.setPeerPortRandomOnStart(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.PORT_FORWARDING:
session.setPortForwardingEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.RENAME_PARTIAL:
session.setRenamePartialFilesEnabled(cursor.getInt(1) > 0);
break;
case "rpc-version":
session.setRPCVersion(cursor.getInt(1));
break;
case "rpc-version-minimum":
session.setRPCVersionMin(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.DONE_SCRIPT:
session.setDoneScript(cursor.getString(3));
break;
case TransmissionSession.SetterFields.DONE_SCRIPT_ENABLED:
session.setDoneScriptEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.SEED_QUEUE_SIZE:
session.setSeedQueueSize(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.SEED_QUEUE_ENABLED:
session.setSeedQueueEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.SEED_RATIO_LIMIT:
session.setSeedRatioLimit(cursor.getFloat(2));
break;
case TransmissionSession.SetterFields.SEED_RATIO_LIMIT_ENABLED:
session.setSeedRatioLimitEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.DOWNLOAD_SPEED_LIMIT:
session.setDownloadSpeedLimit(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.DOWNLOAD_SPEED_LIMIT_ENABLED:
session.setDownloadSpeedLimitEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.UPLOAD_SPEED_LIMIT:
session.setUploadSpeedLimit(cursor.getLong(1));
break;
case TransmissionSession.SetterFields.UPLOAD_SPEED_LIMIT_ENABLED:
session.setUploadSpeedLimitEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.STALLED_QUEUE_SIZE:
session.setStalledQueueSize(cursor.getInt(1));
break;
case TransmissionSession.SetterFields.STALLED_QUEUE_ENABLED:
session.setStalledQueueEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.START_ADDED:
session.setStartAddedTorrentsEnabled(cursor.getInt(1) > 0);
break;
case TransmissionSession.SetterFields.TRASH_ORIGINAL:
session.setTrashOriginalTorrentFilesEnabled(cursor.getInt(1) > 0);
break;
case "version":
session.setVersion(cursor.getString(3));
break;
}
cursor.moveToNext();
}
return session;
}
protected List<ContentValues> jsonToSessionValues(String profile, JsonParser parser)
throws IOException {
List<ContentValues> values = new ArrayList<>();
while (parser.nextToken() != JsonToken.END_OBJECT) {
String name = parser.getCurrentName();
ContentValues item = new ContentValues();
boolean valid = true;
parser.nextToken();
item.put(Constants.C_PROFILE_ID, profile);
switch (name) {
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.ALT_DOWNLOAD_SPEED_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.ALT_UPLOAD_SPEED_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_BEGIN:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_END:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.ALT_SPEED_LIMIT_TIME_DAY:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.BLOCKLIST_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case "blocklist-size":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.BLOCKLIST_URL:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case TransmissionSession.SetterFields.DHT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.ENCRYPTION:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case TransmissionSession.SetterFields.CACHE_SIZE:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case "config-dir":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case TransmissionSession.SetterFields.DOWNLOAD_DIR:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case "download-dir-free-space":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.DOWNLOAD_QUEUE_SIZE:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.DOWNLOAD_QUEUE_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.IDLE_SEEDING_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.IDLE_SEEDING_LIMIT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.INCOMPLETE_DIR:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case TransmissionSession.SetterFields.INCOMPLETE_DIR_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.LOCAL_DISCOVERY:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.UTP:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.GLOBAL_PEER_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.TORRENT_PEER_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.PEER_EXCHANGE:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.PEER_PORT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.RANDOM_PORT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.PORT_FORWARDING:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.RENAME_PARTIAL:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case "rpc-version":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case "rpc-version-minimum":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.DONE_SCRIPT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
case TransmissionSession.SetterFields.DONE_SCRIPT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.SEED_QUEUE_SIZE:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.SEED_QUEUE_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.SEED_RATIO_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_FLOAT);
item.put(Constants.C_VALUE_REAL, parser.getFloatValue());
break;
case TransmissionSession.SetterFields.SEED_RATIO_LIMIT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.DOWNLOAD_SPEED_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.DOWNLOAD_SPEED_LIMIT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.UPLOAD_SPEED_LIMIT:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_LONG);
item.put(Constants.C_VALUE_INTEGER, parser.getLongValue());
break;
case TransmissionSession.SetterFields.UPLOAD_SPEED_LIMIT_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.STALLED_QUEUE_SIZE:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_INT);
item.put(Constants.C_VALUE_INTEGER, parser.getIntValue());
break;
case TransmissionSession.SetterFields.STALLED_QUEUE_ENABLED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.START_ADDED:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case TransmissionSession.SetterFields.TRASH_ORIGINAL:
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_BOOLEAN);
item.put(Constants.C_VALUE_INTEGER, parser.getBooleanValue());
break;
case "version":
item.put(Constants.C_NAME, name);
item.put(Constants.C_VALUE_AFFINITY, Constants.TYPE_STRING);
item.put(Constants.C_VALUE_TEXT, parser.getText());
break;
default:
valid = false;
parser.skipChildren();
break;
}
if (valid) {
values.add(item);
}
}
return values;
}
protected TorrentValues jsonToTorrentValues(JsonParser parser) throws IOException {
TorrentValues values = new TorrentValues();
ContentValues torrent = new ContentValues();
values.torrent = torrent;
int status = 0, peersConnected = 0, peersGettingFromUs = 0, peersSendingToUs = 0,
seedRatioMode = Torrent.SeedRatioMode.GLOBAL_LIMIT;
long eta = 0, leftUntilDone = 0, sizeWhenDone = 0, uploadedEver = 0,
rateDownload = 0, rateUpload = 0;
float metadataPercentComplete = 0, percentDone = 0, uploadRatio = 0,
recheckProgress = 0, seedLimit = 0;
boolean isStalled = false;
String mimeType = null;
while (parser.nextToken() != JsonToken.END_OBJECT) {
String name = parser.getCurrentName();
parser.nextToken();
switch (name) {
case "id":
torrent.put(Constants.C_TORRENT_ID, parser.getIntValue());
break;
case "hashString":
torrent.put(Constants.C_HASH_STRING, parser.getText());
break;
case "status":
status = parser.getIntValue();
if (session.getRPCVersion() < NEW_STATUS_RPC_VERSION) {
switch (status) {
case Torrent.OldStatus.CHECK_WAITING:
status = Torrent.Status.CHECK_WAITING;
break;
case Torrent.OldStatus.CHECKING:
status = Torrent.Status.CHECKING;
break;
case Torrent.OldStatus.DOWNLOADING:
status = Torrent.Status.DOWNLOADING;
break;
case Torrent.OldStatus.SEEDING:
status = Torrent.Status.SEEDING;
break;
case Torrent.OldStatus.STOPPED:
status = Torrent.Status.STOPPED;
break;
}
}
torrent.put(Constants.C_STATUS, status);
break;
case "name":
torrent.put(Constants.C_NAME, parser.getText());
break;
case "error":
torrent.put(Constants.C_ERROR, parser.getIntValue());
break;
case "errorString":
torrent.put(Constants.C_ERROR_STRING, parser.getText());
break;
case "metadataPercentComplete":
metadataPercentComplete = parser.getFloatValue();
torrent.put(Constants.C_METADATA_PERCENT_COMPLETE, metadataPercentComplete);
break;
case "percentDone":
percentDone = parser.getFloatValue();
torrent.put(Constants.C_PERCENT_DONE, percentDone);
break;
case "eta":
eta = parser.getLongValue();
torrent.put(Constants.C_ETA, eta);
break;
case "isFinished":
torrent.put(Constants.C_IS_FINISHED, parser.getBooleanValue());
break;
case "isStalled":
isStalled = parser.getBooleanValue();
torrent.put(Constants.C_IS_STALLED, isStalled);
break;
case "peersConnected":
peersConnected = parser.getIntValue();
torrent.put(Constants.C_PEERS_CONNECTED, peersConnected);
break;
case "peersGettingFromUs":
peersGettingFromUs = parser.getIntValue();
torrent.put(Constants.C_PEERS_GETTING_FROM_US, peersGettingFromUs);
break;
case "peersSendingToUs":
peersSendingToUs = parser.getIntValue();
torrent.put(Constants.C_PEERS_SENDING_TO_US, peersSendingToUs);
break;
case "leftUntilDone":
leftUntilDone = parser.getLongValue();
torrent.put(Constants.C_LEFT_UNTIL_DONE, leftUntilDone);
break;
case "desiredAvailable":
torrent.put(Constants.C_DESIRED_AVAILABLE, parser.getLongValue());
break;
case "totalSize":
torrent.put(Constants.C_TOTAL_SIZE, parser.getLongValue());
break;
case "sizeWhenDone":
sizeWhenDone = parser.getLongValue();
torrent.put(Constants.C_SIZE_WHEN_DONE, sizeWhenDone);
break;
case "rateDownload":
rateDownload = parser.getLongValue();
torrent.put(Constants.C_RATE_DOWNLOAD, rateDownload);
break;
case "rateUpload":
rateUpload = parser.getLongValue();
torrent.put(Constants.C_RATE_UPLOAD, rateUpload);
break;
case Torrent.SetterFields.QUEUE_POSITION:
torrent.put(Constants.C_QUEUE_POSITION, parser.getIntValue());
break;
case "recheckProgress":
recheckProgress = parser.getFloatValue();
torrent.put(Constants.C_RECHECK_PROGRESS, recheckProgress);
break;
case Torrent.SetterFields.SEED_RATIO_MODE:
seedRatioMode = parser.getIntValue();
torrent.put(Constants.C_SEED_RATIO_MODE, seedRatioMode);
break;
case Torrent.SetterFields.SEED_RATIO_LIMIT:
seedLimit = parser.getFloatValue();
torrent.put(Constants.C_SEED_RATIO_LIMIT, seedLimit);
break;
case "uploadedEver":
uploadedEver = parser.getLongValue();
torrent.put(Constants.C_UPLOADED_EVER, uploadedEver);
break;
case "uploadRatio":
uploadRatio = parser.getFloatValue();
torrent.put(Constants.C_UPLOAD_RATIO, uploadRatio);
break;
case "addedDate":
torrent.put(Constants.C_ADDED_DATE, parser.getLongValue());
break;
case "doneDate":
torrent.put(Constants.C_DONE_DATE, parser.getLongValue());
break;
case "startDate":
torrent.put(Constants.C_START_DATE, parser.getLongValue());
break;
case "activityDate":
torrent.put(Constants.C_ACTIVITY_DATE, parser.getLongValue());
break;
case "corruptEver":
torrent.put(Constants.C_CORRUPT_EVER, parser.getLongValue());
break;
case "downloadDir":
torrent.put(Constants.C_DOWNLOAD_DIR, parser.getText());
break;
case "downloadedEver":
torrent.put(Constants.C_DOWNLOADED_EVER, parser.getLongValue());
break;
case "haveUnchecked":
torrent.put(Constants.C_HAVE_UNCHECKED, parser.getLongValue());
break;
case "haveValid":
torrent.put(Constants.C_HAVE_VALID, parser.getLongValue());
break;
case "comment":
torrent.put(Constants.C_COMMENT, parser.getText());
break;
case "creator":
torrent.put(Constants.C_CREATOR, parser.getText());
break;
case "dateCreated":
torrent.put(Constants.C_DATE_CREATED, parser.getLongValue());
break;
case "isPrivate":
torrent.put(Constants.C_IS_PRIVATE, parser.getBooleanValue());
break;
case "pieceCount":
torrent.put(Constants.C_PIECE_COUNT, parser.getIntValue());
break;
case "pieceSize":
torrent.put(Constants.C_PIECE_SIZE, parser.getLongValue());
break;
case Torrent.SetterFields.TORRENT_PRIORITY:
torrent.put(Constants.C_TORRENT_PRIORITY, parser.getIntValue());
break;
case Torrent.SetterFields.DOWNLOAD_LIMIT:
torrent.put(Constants.C_DOWNLOAD_LIMIT, parser.getLongValue());
break;
case Torrent.SetterFields.DOWNLOAD_LIMITED:
torrent.put(Constants.C_DOWNLOAD_LIMITED, parser.getBooleanValue());
break;
case Torrent.SetterFields.SESSION_LIMITS:
torrent.put(Constants.C_HONORS_SESSION_LIMITS, parser.getBooleanValue());
break;
case Torrent.SetterFields.UPLOAD_LIMIT:
torrent.put(Constants.C_UPLOAD_LIMIT, parser.getLongValue());
break;
case Torrent.SetterFields.UPLOAD_LIMITED:
torrent.put(Constants.C_UPLOAD_LIMITED, parser.getBooleanValue());
break;
case "webseedsSendingToUs":
torrent.put(Constants.C_WEBSEEDS_SENDING_TO_US, parser.getIntValue());
break;
case Torrent.SetterFields.PEER_LIMIT:
torrent.put(Constants.C_PEER_LIMIT, parser.getIntValue());
break;
case "trackers": {
if (values.trackers == null) {
values.trackers = new ArrayList<>();
}
int index = 0;
while (parser.nextToken() != JsonToken.END_ARRAY) {
ContentValues tracker;
if (index >= values.trackers.size()) {
tracker = new ContentValues();
values.trackers.add(index, tracker);
} else {
tracker = values.trackers.get(index);
}
while (parser.nextToken() != JsonToken.END_OBJECT) {
String argname = parser.getCurrentName();
parser.nextToken();
switch (argname) {
case "id":
tracker.put(Constants.C_TRACKER_ID, parser.getIntValue());
break;
case "announce":
tracker.put(Constants.C_ANNOUNCE, parser.getText());
break;
case "scrape":
tracker.put(Constants.C_SCRAPE, parser.getText());
break;
case "tier":
tracker.put(Constants.C_TIER, parser.getIntValue());
break;
}
}
++index;
}
break;
}
case "trackerStats": {
if (values.trackers == null) {
values.trackers = new ArrayList<>();
}
int index = 0;
while (parser.nextToken() != JsonToken.END_ARRAY) {
ContentValues tracker;
if (index >= values.trackers.size()) {
tracker = new ContentValues();
values.trackers.add(index, tracker);
} else {
tracker = values.trackers.get(index);
}
while (parser.nextToken() != JsonToken.END_OBJECT) {
String argname = parser.getCurrentName();
parser.nextToken();
switch (argname) {
case "id":
tracker.put(Constants.C_TRACKER_ID, parser.getIntValue());
break;
case "hasAnnounced":
tracker.put(Constants.C_HAS_ANNOUNCED, parser.getBooleanValue());
break;
case "lastAnnounceTime":
tracker.put(Constants.C_LAST_ANNOUNCE_TIME, parser.getLongValue());
break;
case "lastAnnounceSucceeded":
tracker.put(Constants.C_LAST_ANNOUNCE_SUCCEEDED, parser.getBooleanValue());
break;
case "lastAnnouncePeerCount":
tracker.put(Constants.C_LAST_ANNOUNCE_PEER_COUNT, parser.getIntValue());
break;
case "lastAnnounceResult":
tracker.put(Constants.C_LAST_ANNOUNCE_RESULT, parser.getText());
break;
case "hasScraped":
tracker.put(Constants.C_HAS_SCRAPED, parser.getBooleanValue());
break;
case "lastScrapeTime":
tracker.put(Constants.C_LAST_SCRAPE_TIME, parser.getLongValue());
break;
case "lastScrapeSucceeded":
tracker.put(Constants.C_LAST_SCRAPE_SUCCEEDED, parser.getBooleanValue());
break;
case "lastScrapeResult":
tracker.put(Constants.C_LAST_SCRAPE_RESULT, parser.getText());
break;
case "seederCount":
tracker.put(Constants.C_SEEDER_COUNT, parser.getIntValue());
break;
case "leecherCount":
tracker.put(Constants.C_LEECHER_COUNT, parser.getIntValue());
break;
}
}
++index;
}
break;
}
case "files": {
if (values.files == null) {
values.files = new ArrayList<>();
}
String lastFileName = null;
int index = 0;
while (parser.nextToken() != JsonToken.END_ARRAY) {
ContentValues file;
if (index >= values.files.size()) {
file = new ContentValues();
file.put(Constants.C_FILE_INDEX, index);
values.files.add(index, file);
} else {
file = values.files.get(index);
}
while (parser.nextToken() != JsonToken.END_OBJECT) {
String argname = parser.getCurrentName();
parser.nextToken();
if (argname.equals("name")) {
lastFileName = parser.getText();
file.put(Constants.C_NAME, lastFileName);
} else if (argname.equals("length")) {
file.put(Constants.C_LENGTH, parser.getLongValue());
}
}
++index;
}
if (values.files.size() > 1) {
mimeType = "inode/directory";
} else if (lastFileName != null) {
File f = new File(lastFileName);
String parent = f.getParent();
if (parent != null && !parent.equals("")) {
mimeType = "inode/directory";
} else {
int dotPos = lastFileName.lastIndexOf('.');
String ext = dotPos >= 0 ? lastFileName.substring(dotPos + 1) : "";
if (!ext.equals("")) {
MimeTypeMap map = MimeTypeMap.getSingleton();
String mime = map.getMimeTypeFromExtension(ext);
mimeType = mime;
}
}
}
break;
}
case "fileStats": {
if (values.files == null) {
values.files = new ArrayList<>();
}
int index = 0;
while (parser.nextToken() != JsonToken.END_ARRAY) {
ContentValues file;
if (index >= values.files.size()) {
file = new ContentValues();
file.put(Constants.C_FILE_INDEX, index);
values.files.add(index, file);
} else {
file = values.files.get(index);
}
while (parser.nextToken() != JsonToken.END_OBJECT) {
String argname = parser.getCurrentName();
parser.nextToken();
switch (argname) {
case "bytesCompleted":
file.put(Constants.C_BYTES_COMPLETED, parser.getLongValue());
break;
case "wanted":
file.put(Constants.C_WANTED, parser.getBooleanValue());
break;
case "priority":
file.put(Constants.C_PRIORITY, parser.getIntValue());
break;
}
}
++index;
}
break;
}
case "peers": {
if (values.peers == null) {
values.peers = new ArrayList<>();
}
int index = 0;
while (parser.nextToken() != JsonToken.END_ARRAY) {
ContentValues peer;
if (index >= values.peers.size()) {
peer = new ContentValues();
values.peers.add(index, peer);
} else {
peer = values.peers.get(index);
}
while (parser.nextToken() != JsonToken.END_OBJECT) {
String argname = parser.getCurrentName();
parser.nextToken();
switch (argname) {
case "address":
peer.put(Constants.C_ADDRESS, parser.getText());
break;
case "clientName":
peer.put(Constants.C_CLIENT_NAME, parser.getText());
break;
case "clientIsChoked":
peer.put(Constants.C_CLIENT_IS_CHOKED, parser.getBooleanValue());
break;
case "clientIsInterested":
peer.put(Constants.C_CLIENT_IS_INTERESTED, parser.getBooleanValue());
break;
case "isDownloadingFrom":
peer.put(Constants.C_IS_DOWNLOADING_FROM, parser.getBooleanValue());
break;
case "isEncrypted":
peer.put(Constants.C_IS_ENCRYPTED, parser.getBooleanValue());
break;
case "isIncoming":
peer.put(Constants.C_IS_INCOMING, parser.getBooleanValue());
break;
case "isUploadingTo":
peer.put(Constants.C_IS_UPLOADING_TO, parser.getBooleanValue());
break;
case "peerIsChoked":
peer.put(Constants.C_PEER_IS_CHOKED, parser.getBooleanValue());
break;
case "peerIsInterested":
peer.put(Constants.C_PEER_IS_INTERESTED, parser.getBooleanValue());
break;
case "port":
peer.put(Constants.C_PORT, parser.getIntValue());
break;
case "progress":
peer.put(Constants.C_PROGRESS, parser.getFloatValue());
break;
case "rateToClient":
peer.put(Constants.C_RATE_TO_CLIENT, parser.getLongValue());
break;
case "rateToPeer":
peer.put(Constants.C_RATE_TO_PEER, parser.getLongValue());
break;
}
}
++index;
}
break;
}
default:
parser.skipChildren();
break;
}
}
if (seedRatioMode == Torrent.SeedRatioMode.NO_LIMIT) {
seedLimit = 0;
} else if (seedRatioMode == Torrent.SeedRatioMode.GLOBAL_LIMIT) {
seedLimit = session.isSeedRatioLimitEnabled() ? session.getSeedRatioLimit() : 0;
}
String trafficText = null;
switch (status) {
case Torrent.Status.DOWNLOAD_WAITING:
case Torrent.Status.DOWNLOADING:
trafficText = String.format(
context.getString(R.string.traffic_downloading_format),
G.readableFileSize(sizeWhenDone - leftUntilDone),
G.readableFileSize(sizeWhenDone),
String.format(context.getString(R.string.traffic_downloading_percentage_format),
G.readablePercent(percentDone * 100)),
eta < 0
? context.getString(R.string.traffic_remaining_time_unknown)
: String.format(context.getString(R.string.traffic_remaining_time_format),
G.readableRemainingTime(eta, context))
);
break;
case Torrent.Status.SEED_WAITING:
case Torrent.Status.SEEDING:
trafficText = String.format(
context.getString(R.string.traffic_seeding_format),
G.readableFileSize(sizeWhenDone),
G.readableFileSize(uploadedEver),
String.format(context.getString(R.string.traffic_seeding_ratio_format),
G.readablePercent(uploadRatio),
seedLimit <= 0 ? "" : String.format(
context.getString(R.string.traffic_seeding_ratio_goal_format),
G.readablePercent(seedLimit))
),
seedLimit <= 0
? ""
: eta < 0
? context.getString(R.string.traffic_remaining_time_unknown)
: String.format(context.getString(R.string.traffic_remaining_time_format),
G.readableRemainingTime(eta, context))
);
break;
case Torrent.Status.CHECK_WAITING:
break;
case Torrent.Status.CHECKING:
break;
case Torrent.Status.STOPPED:
if (percentDone < 1) {
trafficText = String.format(
context.getString(R.string.traffic_downloading_format),
G.readableFileSize(sizeWhenDone - leftUntilDone),
G.readableFileSize(sizeWhenDone),
String.format(context.getString(R.string.traffic_downloading_percentage_format),
G.readablePercent(percentDone * 100)),
"<br/>" + String.format(
context.getString(R.string.traffic_seeding_format),
G.readableFileSize(sizeWhenDone),
G.readableFileSize(uploadedEver),
String.format(context.getString(R.string.traffic_seeding_ratio_format),
uploadRatio < 0 ? 0 : G.readablePercent(uploadRatio),
seedLimit <= 0 ? "" : String.format(
context.getString(R.string.traffic_seeding_ratio_goal_format),
G.readablePercent(seedLimit))
),
""
)
);
} else {
trafficText = String.format(
context.getString(R.string.traffic_seeding_format),
G.readableFileSize(sizeWhenDone),
G.readableFileSize(uploadedEver),
String.format(context.getString(R.string.traffic_seeding_ratio_format),
G.readablePercent(uploadRatio),
seedLimit <= 0 ? "" : String.format(
context.getString(R.string.traffic_seeding_ratio_goal_format),
G.readablePercent(seedLimit))
),
""
);
}
break;
default:
break;
}
String statusText = null;
String statusFormat = context.getString(R.string.status_format);
String statusType, statusMoreFormat, statusSpeedFormat, statusSpeed;
switch (status) {
case Torrent.Status.DOWNLOAD_WAITING:
case Torrent.Status.DOWNLOADING:
statusType = context.getString(status == Torrent.Status.DOWNLOADING
? metadataPercentComplete < 1
? R.string.status_state_downloading_metadata
: R.string.status_state_downloading
: R.string.status_state_download_waiting);
statusMoreFormat = context.getString(R.string.status_more_downloading_format);
statusSpeedFormat = context.getString(R.string.status_more_downloading_speed_format);
if (isStalled) {
statusSpeed = context.getString(R.string.status_more_idle);
} else {
statusSpeed = String.format(statusSpeedFormat,
G.readableFileSize(rateDownload),
G.readableFileSize(rateUpload)
);
}
statusText = String.format(statusFormat, statusType,
String.format(statusMoreFormat,
peersSendingToUs, peersConnected, statusSpeed
)
);
break;
case Torrent.Status.SEED_WAITING:
case Torrent.Status.SEEDING:
statusType = context.getString(status == Torrent.Status.SEEDING
? R.string.status_state_seeding : R.string.status_state_seed_waiting);
statusMoreFormat = context.getString(R.string.status_more_seeding_format);
statusSpeedFormat = context.getString(R.string.status_more_seeding_speed_format);
if (isStalled) {
statusSpeed = context.getString(R.string.status_more_idle);
} else {
statusSpeed = String.format(statusSpeedFormat,
G.readableFileSize(rateUpload)
);
}
statusText = String.format(statusFormat, statusType,
String.format(statusMoreFormat,
peersGettingFromUs, peersConnected, statusSpeed
)
);
break;
case Torrent.Status.CHECK_WAITING:
statusType = context.getString(R.string.status_state_check_waiting);
statusText = String.format(statusFormat,
statusType,
"-" + context.getString(R.string.status_more_idle)
);
break;
case Torrent.Status.CHECKING:
statusText = String.format(
context.getString(R.string.status_state_checking),
G.readablePercent(recheckProgress * 100));
break;
case Torrent.Status.STOPPED:
statusText = context.getString(uploadRatio < seedLimit
? R.string.status_state_paused
: R.string.status_state_finished
);
break;
default:
break;
}
if (trafficText != null) {
torrent.put(Constants.C_TRAFFIC_TEXT, trafficText);
}
if (statusText != null) {
torrent.put(Constants.C_STATUS_TEXT, statusText);
}
if (mimeType != null) {
torrent.put(Constants.C_MIME_TYPE, mimeType);
}
return values;
}
protected void removeTorrent(String hash) {
database.delete(Constants.T_TORRENT, Constants.C_HASH_STRING + " = ?",
new String[] { hash } );
}
protected void removeTorrent(String profile, int id) {
/* Delete the torrent for a given profile and torrent id
DELETE FROM torrent
WHERE hash_string IN (
SELECT torrent.hash_string FROM torrent_profile JOIN torrent
ON torrent_profile.hash_string = torrent.hash_string
WHERE profile_id = ? AND torrent_id = ?
)
*/
database.delete(Constants.T_TORRENT, Constants.C_HASH_STRING
+ " IN ("
+ " SELECT " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " JOIN " + Constants.T_TORRENT
+ " ON " + Constants.T_TORRENT_PROFILE + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ " AND " + Constants.C_TORRENT_ID + " = ?"
+ ")",
new String[] { profile, Integer.toString(id) });
}
protected void removeTracker(String hash, int id) {
database.delete(Constants.T_TRACKER, Constants.C_HASH_STRING + " = ?"
+ " AND " + Constants.C_TRACKER_ID + " = ?",
new String[] { hash, String.valueOf(id)});
}
protected void removeObsolete(String profile, List<String> validHashStrings) {
String[] args = new String[] { profile };
List<String> where = new ArrayList<>();
for (String hash : validHashStrings) {
where.add(DatabaseUtils.sqlEscapeString(hash));
}
database.delete(Constants.T_TORRENT, Constants.C_HASH_STRING + " NOT IN ("
+ TextUtils.join(", ", where)
+ ") AND " + Constants.C_HASH_STRING
+ " IN ("
+ " SELECT " + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TORRENT_PROFILE + " t1"
+ " WHERE NOT EXISTS ("
+ " SELECT 1"
+ " FROM " + Constants.T_TORRENT_PROFILE + " t2"
+ " WHERE t1." + Constants.C_HASH_STRING + " = t2." + Constants.C_HASH_STRING
+ " AND t1." + Constants.C_PROFILE_ID + " != t2." + Constants.C_PROFILE_ID
+ ")"
+ " AND t1." + Constants.C_PROFILE_ID + " = ?"
+ ")",
args);
database.delete(Constants.T_TORRENT_PROFILE, Constants.C_HASH_STRING + " NOT IN ("
+ TextUtils.join(", ", where)
+ ") AND " + Constants.C_PROFILE_ID + " = ?", args);
}
protected void removeAllTrackers(String profile) {
database.delete(Constants.T_TRACKER, Constants.C_HASH_STRING + " IN ("
+ " SELECT " + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TORRENT_PROFILE
+ " WHERE " + Constants.C_PROFILE_ID + " = ?"
+ ")",
new String[] { profile });
}
protected int[] queryTorrentIdChanges() {
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT max(rowid), count(rowid) FROM " + Constants.T_TORRENT, null
);
cursor.moveToFirst();
return new int [] { cursor.getInt(0), cursor.getInt(1) };
} finally {
if (cursor != null)
cursor.close();
}
}
protected int[] queryStatusCount() {
Cursor cursor = null;
try {
cursor = database.rawQuery(
"SELECT count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.CHECK_WAITING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.CHECKING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.DOWNLOAD_WAITING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.DOWNLOADING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.SEED_WAITING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.SEEDING
+ " THEN 1 ELSE NULL END), count(CASE WHEN "
+ Constants.C_STATUS + " = "
+ Torrent.Status.STOPPED
+ " THEN 1 ELSE NULL END) FROM " + Constants.T_TORRENT, null
);
cursor.moveToFirst();
return new int[] { cursor.getInt(0), cursor.getInt(1), cursor.getInt(2),
cursor.getInt(3), cursor.getInt(4), cursor.getInt(5), cursor.getInt(6) };
} finally {
if (cursor != null)
cursor.close();
}
}
protected TorrentCursorArgs getTorrentCursorArgs(SharedPreferences prefs) {
TorrentCursorArgs args = new TorrentCursorArgs();
String query = prefs.getString(G.PREF_LIST_SEARCH, null);
String directory = prefs.getString(G.PREF_LIST_DIRECTORY, null);
String tracker = prefs.getString(G.PREF_LIST_TRACKER, null);
G.FilterBy filter = G.FilterBy.ALL;
if (prefs.contains(G.PREF_LIST_FILTER)) {
try {
filter = G.FilterBy.valueOf(
prefs.getString(G.PREF_LIST_FILTER, G.FilterBy.ALL.name())
);
} catch (Exception ignored) { }
}
G.SortBy sortBy = G.SortBy.STATUS;
if (prefs.contains(G.PREF_LIST_SORT_BY)) {
try {
sortBy = G.SortBy.valueOf(
prefs.getString(G.PREF_LIST_SORT_BY, G.SortBy.STATUS.name())
);
} catch (Exception ignored) { }
}
G.SortOrder sortOrder = G.SortOrder.ASCENDING;
if (prefs.contains(G.PREF_LIST_SORT_ORDER)) {
try {
sortOrder = G.SortOrder.valueOf(
prefs.getString(G.PREF_LIST_SORT_ORDER, G.SortOrder.ASCENDING.name())
);
} catch (Exception ignored) { }
}
G.SortBy baseSortBy = G.SortBy.AGE;
if (prefs.contains(G.PREF_BASE_SORT)) {
try {
baseSortBy = G.SortBy.valueOf(
prefs.getString(G.PREF_BASE_SORT, G.SortBy.AGE.name())
);
} catch (Exception ignored) { }
}
G.SortOrder baseSortOrder = G.SortOrder.DESCENDING;
if (prefs.contains(G.PREF_BASE_SORT_ORDER)) {
String pref = prefs.getString(G.PREF_BASE_SORT_ORDER, "PRIMARY");
if (pref != null) {
switch (pref) {
case "ASCENDING":
baseSortOrder = G.SortOrder.ASCENDING;
break;
case "DESCENDING":
baseSortOrder = G.SortOrder.DESCENDING;
break;
case "PRIMARY":
baseSortOrder = sortOrder;
break;
case "REVERSE":
baseSortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING
: G.SortOrder.ASCENDING;
break;
}
}
}
List<String> selection = new ArrayList<>();
List<String> selectionArgs = new ArrayList<>();
if (query != null && query.length() > 0) {
StringBuilder queryPattern = new StringBuilder();
String[] split = query.toLowerCase(Locale.getDefault()).split("");
for (int i = 0; i < split.length; ++i) {
if (split[i].equals("") || split[i].equals(";")) {
continue;
}
queryPattern.append(split[i].equals("'") ? "''" : split[i]);
if (i < split.length - 1) {
queryPattern.append("%");
}
}
selection.add("LOWER(" + Constants.C_NAME + ") LIKE '%" + queryPattern.toString() +"%'");
}
if (!prefs.getBoolean(G.PREF_FILTER_DIRECTORIES, false)) {
directory = null;
}
if (!TextUtils.isEmpty(directory)) {
selection.add(Constants.C_DOWNLOAD_DIR + " = ?");
selectionArgs.add(directory);
}
if (!prefs.getBoolean(G.PREF_FILTER_TRACKERS, false)
|| (!prefs.getBoolean(G.PREF_FILTER_UNTRACKED, false)
&& G.FILTER_UNTRACKED.equals(tracker))) {
tracker = null;
}
if (!TextUtils.isEmpty(tracker)) {
if (G.FILTER_UNTRACKED.equals(tracker)) {
selection.add("NOT EXISTS ("
+ "SELECT 1"
+ " FROM " + Constants.T_TRACKER
+ " WHERE " + Constants.T_TORRENT + "." + Constants.C_HASH_STRING
+ " = " + Constants.T_TRACKER + "." + Constants.C_HASH_STRING
+ ")");
} else {
selection.add(Constants.T_TORRENT + "." + Constants.C_HASH_STRING + " IN ("
+ "SELECT " + Constants.C_HASH_STRING
+ " FROM " + Constants.T_TRACKER
+ " WHERE " + Constants.C_ANNOUNCE + " LIKE "
+ DatabaseUtils.sqlEscapeString("%" + tracker + "%")
+ ")");
}
}
if (filter != G.FilterBy.ALL) {
switch (filter) {
case DOWNLOADING:
if (prefs.getBoolean(G.PREF_FILTER_DOWNLOADING, false)) {
selection.add(Constants.C_STATUS + " = ?");
selectionArgs.add(Integer.toString(Torrent.Status.DOWNLOADING));
}
break;
case SEEDING:
if (prefs.getBoolean(G.PREF_FILTER_SEEDING, false)) {
selection.add(Constants.C_STATUS + " = ?");
selectionArgs.add(Integer.toString(Torrent.Status.SEEDING));
}
break;
case PAUSED:
if (prefs.getBoolean(G.PREF_FILTER_PAUSED, false)) {
selection.add(Constants.C_STATUS + " = ?");
selectionArgs.add(Integer.toString(Torrent.Status.STOPPED));
}
break;
case COMPLETE:
if (prefs.getBoolean(G.PREF_FILTER_COMPLETE, false)) {
selection.add(Constants.C_PERCENT_DONE + " = 1");
}
break;
case INCOMPLETE:
if (prefs.getBoolean(G.PREF_FILTER_INCOMPLETE, false)) {
selection.add(Constants.C_PERCENT_DONE + " < 1");
}
break;
case ACTIVE:
if (prefs.getBoolean(G.PREF_FILTER_ACTIVE, false)) {
selection.add(
Constants.C_IS_STALLED + " != 1"
+ " AND " + Constants.C_IS_FINISHED + " != 1"
+ " AND ("
+ "((" + Constants.C_STATUS + " = ?"
+ " OR " + Constants.C_STATUS + " = ?"
+ ") AND (" + Constants.C_RATE_DOWNLOAD + " != 0"
+ " OR " + Constants.C_RATE_UPLOAD + " != 0"
+ ")) OR (" + Constants.C_STATUS + " = ?" + ")"
+ ")"
);
selectionArgs.add(Integer.toString(Torrent.Status.DOWNLOADING));
selectionArgs.add(Integer.toString(Torrent.Status.SEEDING));
selectionArgs.add(Integer.toString(Torrent.Status.CHECKING));
}
break;
case CHECKING:
if (prefs.getBoolean(G.PREF_FILTER_CHECKING, false)) {
selection.add(Constants.C_STATUS + " = ?");
selectionArgs.add(Integer.toString(Torrent.Status.CHECKING));
}
break;
case ERRORS:
if (prefs.getBoolean(G.PREF_FILTER_ERRORS, false)) {
selection.add(Constants.C_ERROR + " != 0");
}
break;
}
}
args.selection = TextUtils.join(" AND ", selection);
args.selectionArgs = selectionArgs.toArray(new String[selectionArgs.size()]);
String mainOrder = sortToOrder(sortBy, sortOrder);
String baseOrder = sortToOrder(baseSortBy, baseSortOrder);
if (mainOrder != null && baseOrder != null) {
args.orderBy = mainOrder + ", " + baseOrder;
}
return args;
}
protected String sortToOrder(G.SortBy sortBy, G.SortOrder sortOrder) {
String sort;
switch(sortBy) {
case NAME:
sort = "LOWER(" + Constants.C_NAME + ")";
break;
case SIZE:
sort = Constants.C_TOTAL_SIZE;
break;
case STATUS:
sort = "(CASE " + Constants.C_STATUS
+ " WHEN " + Torrent.Status.STOPPED
+ " THEN (CASE WHEN "
+ Constants.C_SEED_RATIO_MODE + " = " + Torrent.SeedRatioMode.NO_LIMIT
+ " OR ("
+ Constants.C_SEED_RATIO_MODE + " = " + Torrent.SeedRatioMode.GLOBAL_LIMIT
+ " AND "
+ Constants.C_UPLOAD_RATIO + " < " + Float.toString(session.getSeedRatioLimit())
+ ") OR "
+ Constants.C_UPLOAD_RATIO + " < " + Constants.C_SEED_RATIO_LIMIT
+ " THEN " + (Torrent.Status.STOPPED + 40)
+ " ELSE " + (Torrent.Status.STOPPED + 50)
+ " END)"
+ " WHEN " + Torrent.Status.CHECK_WAITING
+ " THEN " + (Torrent.Status.CHECK_WAITING + 100)
+ " WHEN " + Torrent.Status.DOWNLOAD_WAITING
+ " THEN " + (Torrent.Status.DOWNLOAD_WAITING + 10)
+ " WHEN " + Torrent.Status.SEED_WAITING
+ " THEN " + (Torrent.Status.SEED_WAITING + 20)
+ " ELSE " + Constants.C_STATUS
+ " END)";
break;
case ACTIVITY:
sort = "(" + Constants.C_RATE_DOWNLOAD + " + " + Constants.C_RATE_UPLOAD + ")";
sortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING : G.SortOrder.ASCENDING;
break;
case AGE:
sort = Constants.C_ADDED_DATE;
sortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING : G.SortOrder.ASCENDING;
break;
case LOCATION:
sort = "LOWER(" + Constants.C_DOWNLOAD_DIR + ")";
break;
case PEERS:
sort = Constants.C_PEERS_CONNECTED;
break;
case PROGRESS:
sort = Constants.C_PERCENT_DONE;
break;
case QUEUE:
sort = Constants.C_QUEUE_POSITION;
break;
case RATE_DOWNLOAD:
sort = Constants.C_RATE_DOWNLOAD;
sortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING : G.SortOrder.ASCENDING;
break;
case RATE_UPLOAD:
sort = Constants.C_RATE_UPLOAD;
sortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING : G.SortOrder.ASCENDING;
break;
case RATIO:
sort = Constants.C_UPLOAD_RATIO;
sortOrder = sortOrder == G.SortOrder.ASCENDING
? G.SortOrder.DESCENDING : G.SortOrder.ASCENDING;
break;
default:
return null;
}
return sort + " " + (sortOrder == G.SortOrder.ASCENDING ? "ASC" : "DESC");
}
}