/*
* This file is part of Transdroid Torrent Search
* <http://code.google.com/p/transdroid-search/>
*
* Transdroid Torrent Search is free software: you can redistribute
* it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later
* version.
*
* Transdroid Torrent Search is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Transdroid. If not, see <http://www.gnu.org/licenses/>.
*/
package org.transdroid.search.AsiaTorrents;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidParameterException;
import java.text.*;
import java.util.*;
import javax.security.auth.login.LoginException;
import org.apache.http.*;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.transdroid.search.ISearchAdapter;
import org.transdroid.search.SearchResult;
import org.transdroid.search.SortOrder;
import org.transdroid.search.TorrentSite;
import org.transdroid.search.gui.SettingsHelper;
import org.transdroid.util.HttpHelper;
import android.content.SharedPreferences;
/**
* An adapter that provides access to AsiaTorrents searches by parsing the raw HTML output.
*/
public class AsiaTorrentsAdapter implements ISearchAdapter {
private static final String LOGIN_USER = "uid";
private static final String LOGIN_PASS = "pwd";
private static final String LOGINURL = "http://www.asiatorrents.me/index.php?page=login";
private static final String QUERYURL = "http://www.asiatorrents.me/index.php?page=torrents&search=%1$s";
private static final int CONNECTION_TIMEOUT = 8000;
private final SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy", Locale.US);
private DefaultHttpClient prepareRequest(SharedPreferences prefs) throws Exception {
String username = SettingsHelper.getSiteUser(prefs, TorrentSite.AsiaTorrents);
String password = SettingsHelper.getSitePass(prefs, TorrentSite.AsiaTorrents);
if (username == null || password == null) {
throw new InvalidParameterException("No username or password was provided, while this is required for this private site.");
}
// Setup request using GET
HttpParams httpparams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpparams, CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpparams, CONNECTION_TIMEOUT);
DefaultHttpClient httpclient = new DefaultHttpClient(httpparams);
// First log in
HttpPost loginPost = new HttpPost(LOGINURL);
loginPost.setEntity(new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair[]{new BasicNameValuePair(LOGIN_USER, username), new BasicNameValuePair(LOGIN_PASS, password)})));
HttpResponse loginResult = httpclient.execute(loginPost);
if (loginResult.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
// Failed to sign in
throw new LoginException("Login failure for AsiaTorrents with user " + username);
}
return httpclient;
}
@Override
public List<SearchResult> search(SharedPreferences prefs, String query, SortOrder order, int maxResults) throws Exception {
DefaultHttpClient httpclient = prepareRequest(prefs);
// Build a search request parameters
String encodedQuery = "";
try {
encodedQuery = URLEncoder.encode(query, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw e;
}
final String url = String.format(QUERYURL, encodedQuery/*, (order == SortOrder.BySeeders ? SORT_SEEDS : SORT_COMPOSITE)*/);
// Start synchronous search
// Make request
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
// Read HTML response
InputStream instream = response.getEntity().getContent();
String html = HttpHelper.convertStreamToString(instream);
instream.close();
return parseHtml(html, maxResults);
}
@Override
public InputStream getTorrentFile(SharedPreferences prefs, String url) throws Exception {
// Provide an authenticated file handle to the requested url
DefaultHttpClient httpclient = prepareRequest(prefs);
HttpResponse response = httpclient.execute(new HttpGet(url));
return response.getEntity().getContent();
}
protected List<SearchResult> parseHtml(String html, int maxResults) throws Exception {
try {
// Texts to find subsequently
final String RESULTS = "<td align=\"center\" width=\"20\" class=\"header\">Dl</td>";
final String TORRENT = "<td class=\"lista\" valign=\"middle\" onMouseOver=";
// Parse the search results from HTML by looking for the identifying texts
List<SearchResult> results = new ArrayList<SearchResult>();
//if (html.indexOf(NOMATCH) >= 0)
//return results; // Success, but no result for this query
int resultsStart = html.indexOf(RESULTS) + RESULTS.length();
android.util.Log.d("resultsStart", "" + resultsStart);
int torStart = html.indexOf(TORRENT, resultsStart);
android.util.Log.d("torStart", "" + torStart);
while (torStart >= 0 && results.size() < maxResults) {
int nextTorrentIndex = html.indexOf(TORRENT, torStart + TORRENT.length());
if (nextTorrentIndex >= 0) {
results.add(parseHtmlItem(html.substring(torStart + TORRENT.length(), nextTorrentIndex)));
} else {
results.add(parseHtmlItem(html.substring(torStart + TORRENT.length())));
}
torStart = nextTorrentIndex;
}
return results;
} catch (OutOfMemoryError e) {
throw new Exception(e);
} catch (Exception e) {
throw new Exception(e);
}
}
private SearchResult parseHtmlItem(String htmlItem) {
// Texts to find subsequently
final String DETAILS_START = "<a href=\"";
final String DETAILS_END = "\"";
final String NAME_START = "\">";
final String NAME_END = "</a>";
final String LINK = "<a href=\"download.php";
final String LINK_END = "\">";
final String DATE_TAG_START = "<td align=\"center\" width=\"85\" class=\"lista\"";
final String DATE_START = "\">";
final String DATE_END = "</td>";
final String SIZE = "\">";
final String SIZE_END = "</td>";
final String SEEDERS = "title=\"Click here to view peers details\">";
final String SEEDERS_END = "</a></td>";
final String LEECHERS = "title=\"Click here to view peers details\">";
final String LEECHERS_END = "</a></td>";
final String prefix = "http://asiatorrents.me/";
int detailsStart = htmlItem.indexOf(DETAILS_START) + DETAILS_START.length();
String details = htmlItem.substring(detailsStart, htmlItem.indexOf(DETAILS_END, detailsStart));
details = prefix + details.replace("&", "&");
int nameStart = htmlItem.indexOf(NAME_START) + NAME_START.length();
nameStart = htmlItem.indexOf(NAME_START, nameStart) + NAME_START.length();
String name = htmlItem.substring(nameStart, htmlItem.indexOf(NAME_END, nameStart));
int logoStart = name.indexOf(" ");
if (logoStart > 0)
name = name.substring(0, logoStart);
int linkStart = htmlItem.indexOf(LINK, nameStart) + DETAILS_START.length();
String link = htmlItem.substring(linkStart, htmlItem.indexOf(LINK_END, linkStart));
link = prefix + link.replace("&", "&");
int dateStart = htmlItem.indexOf(DATE_TAG_START, linkStart) + DATE_TAG_START.length();
dateStart = htmlItem.indexOf(DATE_START, dateStart) + DATE_START.length();
String dateText = htmlItem.substring(dateStart, htmlItem.indexOf(DATE_END, dateStart));
Date date = null;
try {
date = df.parse(dateText);
} catch (java.text.ParseException e) {
// Not parsable; just leave it at null
}
int sizeStart = htmlItem.indexOf(SIZE, dateStart) + SIZE.length();
String size = htmlItem.substring(sizeStart, htmlItem.indexOf(SIZE_END, sizeStart));
int seedersStart = htmlItem.indexOf(SEEDERS, sizeStart) + SEEDERS.length();
int seeders = 0;
if (seedersStart >= 0) {
try {
String seedersText = htmlItem.substring(seedersStart, htmlItem.indexOf(SEEDERS_END, seedersStart));
seeders = Integer.parseInt(seedersText);
} catch (Exception e) {
// Number of seeders not found; ignore
}
}
int leechersStart = htmlItem.indexOf(LEECHERS, seedersStart) + LEECHERS.length();
int leechers = 0;
if (leechersStart >= 0) {
try {
String leechersText = htmlItem.substring(leechersStart, htmlItem.indexOf(LEECHERS_END, leechersStart));
leechers = Integer.parseInt(leechersText);
} catch (Exception e) {
// Number of seeders not found; ignore
}
}
return new SearchResult(name, link, details, size, date, seeders, leechers);
}
@Override
public String buildRssFeedUrlFromSearch(String query, SortOrder order) {
// AsiaTorrents doesn't support RSS feed-based searches
return null;
}
@Override
public String getSiteName() {
return "AsiaTorrents";
}
@Override
public boolean isPrivateSite() {
return true;
}
@Override
public boolean usesToken() {
return false;
}
}