@ -17,16 +17,10 @@
* /
* /
package org.transdroid.daemon.BitComet ;
package org.transdroid.daemon.BitComet ;
import java.io.File ;
import com.android.internalcopy.http.multipart.BitCometFilePart ;
import java.io.FileNotFoundException ;
import com.android.internalcopy.http.multipart.MultipartEntity ;
import java.io.StringReader ;
import com.android.internalcopy.http.multipart.Part ;
import java.io.UnsupportedEncodingException ;
import com.android.internalcopy.http.multipart.Utf8StringPart ;
import java.net.URI ;
import java.text.DateFormat ;
import java.text.SimpleDateFormat ;
import java.util.ArrayList ;
import java.util.Date ;
import java.util.List ;
import org.apache.http.HttpEntity ;
import org.apache.http.HttpEntity ;
import org.apache.http.HttpResponse ;
import org.apache.http.HttpResponse ;
@ -38,18 +32,19 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient ;
import org.apache.http.impl.client.DefaultHttpClient ;
import org.apache.http.message.BasicNameValuePair ;
import org.apache.http.message.BasicNameValuePair ;
import org.apache.http.protocol.HTTP ;
import org.apache.http.protocol.HTTP ;
import org.transdroid.core.gui.log.Log ;
import org.transdroid.daemon.Daemon ;
import org.transdroid.daemon.Daemon ;
import org.transdroid.daemon.DaemonException ;
import org.transdroid.daemon.DaemonException ;
import org.transdroid.daemon.DaemonException.ExceptionType ;
import org.transdroid.daemon.DaemonSettings ;
import org.transdroid.daemon.DaemonSettings ;
import org.transdroid.daemon.IDaemonAdapter ;
import org.transdroid.daemon.IDaemonAdapter ;
import org.transdroid.daemon.Priority ;
import org.transdroid.daemon.Priority ;
import org.transdroid.daemon.Torrent ;
import org.transdroid.daemon.Torrent ;
import org.transdroid.daemon.TorrentFile ;
import org.transdroid.daemon.TorrentFile ;
import org.transdroid.daemon.TorrentStatus ;
import org.transdroid.daemon.TorrentStatus ;
import org.transdroid.daemon.DaemonException.ExceptionType ;
import org.transdroid.daemon.task.AddByFileTask ;
import org.transdroid.daemon.task.AddByFileTask ;
import org.transdroid.daemon.task.AddByUrlTask ;
import org.transdroid.daemon.task.AddByMagnetUrlTask ;
import org.transdroid.daemon.task.AddByMagnetUrlTask ;
import org.transdroid.daemon.task.AddByUrlTask ;
import org.transdroid.daemon.task.DaemonTask ;
import org.transdroid.daemon.task.DaemonTask ;
import org.transdroid.daemon.task.DaemonTaskFailureResult ;
import org.transdroid.daemon.task.DaemonTaskFailureResult ;
import org.transdroid.daemon.task.DaemonTaskResult ;
import org.transdroid.daemon.task.DaemonTaskResult ;
@ -60,26 +55,28 @@ import org.transdroid.daemon.task.RemoveTask;
import org.transdroid.daemon.task.RetrieveTask ;
import org.transdroid.daemon.task.RetrieveTask ;
import org.transdroid.daemon.task.RetrieveTaskSuccessResult ;
import org.transdroid.daemon.task.RetrieveTaskSuccessResult ;
import org.transdroid.daemon.task.SetTransferRatesTask ;
import org.transdroid.daemon.task.SetTransferRatesTask ;
import org.transdroid.daemon.util.DLog ;
import org.transdroid.daemon.util.HttpHelper ;
import org.transdroid.daemon.util.HttpHelper ;
import com.android.internalcopy.http.multipart.Part ;
import com.android.internalcopy.http.multipart.MultipartEntity ;
import com.android.internalcopy.http.multipart.BitCometFilePart ;
import com.android.internalcopy.http.multipart.Utf8StringPart ;
import org.xmlpull.v1.XmlPullParser ;
import org.xmlpull.v1.XmlPullParser ;
import org.xmlpull.v1.XmlPullParserException ;
import org.xmlpull.v1.XmlPullParserException ;
import org.xmlpull.v1.XmlPullParserFactory ;
import org.xmlpull.v1.XmlPullParserFactory ;
import java.io.File ;
import java.io.FileNotFoundException ;
import java.io.StringReader ;
import java.io.UnsupportedEncodingException ;
import java.net.URI ;
import java.text.DateFormat ;
import java.text.SimpleDateFormat ;
import java.util.ArrayList ;
import java.util.Date ;
import java.util.List ;
/ * *
/ * *
* The daemon adapter for the BitComet torrent client .
* The daemon adapter for the BitComet torrent client .
*
* @author SeNS ( sensboston )
* @author SeNS ( sensboston )
*
* < p / >
* 09 / 26 / 2012 : added AJAX support for BitComet v . 1 . 34 and up
* 09 / 26 / 2012 : added AJAX support for BitComet v . 1 . 34 and up : added additional tasks support
* : added additional tasks support
* /
* /
public class BitCometAdapter implements IDaemonAdapter {
public class BitCometAdapter implements IDaemonAdapter {
@ -92,128 +89,167 @@ public class BitCometAdapter implements IDaemonAdapter {
this . settings = settings ;
this . settings = settings ;
}
}
/ * *
* Returns the size of the torrent , as parsed form some string
* @param size The size in a string format , i . e . ' 691 MB '
* @return The size in bytes
* /
private static long convertSize ( String size ) {
try {
if ( size . endsWith ( "GB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "GB" ) ) ) * 1024 * 1024 * 1024 ) ;
} else if ( size . endsWith ( "MB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "MB" ) ) ) * 1024 * 1024 ) ;
} else if ( size . endsWith ( "kB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "kB" ) ) ) * 1024 ) ;
} else if ( size . endsWith ( "B" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "B" ) ) ) ) ;
}
} catch ( Exception e ) {
}
return 0 ;
}
/ * *
* Returns the part done ( or progress ) of a torrent , as parsed from some string
* @param progress The part done in a string format , i . e . ' 15 . 96 '
* @return The part done as [ 0 . . 1 ] fraction , i . e . 0 . 1596
* /
public static float convertProgress ( String progress ) {
return Float . parseFloat ( progress ) / 1000 . 0f ;
}
@Override
@Override
public DaemonTaskResult executeTask ( DaemonTask task ) {
public DaemonTaskResult executeTask ( Log log , DaemonTask task ) {
try {
try {
switch ( task . getMethod ( ) ) {
switch ( task . getMethod ( ) ) {
case Retrieve :
case Retrieve :
// Request all torrents from server
// Request all torrents from server
// first, check client for the new AJAX interface (BitComet v.1.34 and up)
// first, check client for the new AJAX interface (BitComet v.1.34 and up)
try {
try {
String xmlResult = makeRequest ( "/panel/task_list_xml" ) ;
String xmlResult = makeRequest ( log , "/panel/task_list_xml" ) ;
if ( xmlResult . startsWith ( "<?xml" , 0 ) ) {
if ( xmlResult . startsWith ( "<?xml" , 0 ) ) {
return new RetrieveTaskSuccessResult ( ( RetrieveTask ) task , parseXmlTorrents ( xmlResult ) , null ) ;
return new RetrieveTaskSuccessResult ( ( RetrieveTask ) task , parseXmlTorrents ( xmlResult ) ,
null ) ;
}
} catch ( Exception e ) {
// it's probably an old client, parse HTML instead
String htmlResult = makeRequest ( log , "/panel/task_list" ) ;
return new RetrieveTaskSuccessResult ( ( RetrieveTask ) task , parseHttpTorrents ( log , htmlResult ) ,
null ) ;
}
}
} catch ( Exception e ) {
// it's probably an old client, parse HTML instead
String htmlResult = makeRequest ( "/panel/task_list" ) ;
return new RetrieveTaskSuccessResult ( ( RetrieveTask ) task , parseHttpTorrents ( htmlResult ) , null ) ;
}
case GetFileList :
case GetFileList :
// Request files listing for a specific torrent
// Request files listing for a specific torrent
String fhash = ( ( GetFileListTask ) task ) . getTargetTorrent ( ) . getUniqueID ( ) ;
String fhash = task . getTargetTorrent ( ) . getUniqueID ( ) ;
String fileListResult = makeRequest ( "/panel/task_detail" , new BasicNameValuePair ( "id" , fhash ) ,
String fileListResult = makeRequest ( log , "/panel/task_detail" , new BasicNameValuePair ( "id" , fhash ) ,
new BasicNameValuePair ( "show" , "files" ) ) ;
new BasicNameValuePair ( "show" , "files" ) ) ;
return new GetFileListTaskSuccessResult ( ( GetFileListTask ) task , parseHttpTorrentFiles ( fileListResult ,
return new GetFileListTaskSuccessResult ( ( GetFileListTask ) task ,
fhash ) ) ;
parseHttpTorrentFiles ( fileListResult , fhash ) ) ;
case AddByFile :
case AddByFile :
// Upload a local .torrent file
// Upload a local .torrent file
String ufile = ( ( AddByFileTask ) task ) . getFile ( ) ;
String ufile = ( ( AddByFileTask ) task ) . getFile ( ) ;
makeFileUploadRequest ( "/panel/task_add_bt_result" , ufile ) ;
makeFileUploadRequest ( log , "/panel/task_add_bt_result" , ufile ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case AddByUrl :
case AddByUrl :
// Request to add a torrent by URL
// Request to add a torrent by URL
String url = ( ( AddByUrlTask ) task ) . getUrl ( ) ;
String url = ( ( AddByUrlTask ) task ) . getUrl ( ) ;
makeUploadUrlRequest ( "/panel/task_add_httpftp_result" , url ) ;
makeUploadUrlRequest ( log , "/panel/task_add_httpftp_result" , url ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case AddByMagnetUrl :
case AddByMagnetUrl :
// Request to add a torrent by URL
// Request to add a torrent by URL
String magnetUrl = ( ( AddByMagnetUrlTask ) task ) . getUrl ( ) ;
String magnetUrl = ( ( AddByMagnetUrlTask ) task ) . getUrl ( ) ;
makeUploadUrlRequest ( "/panel/task_add_httpftp_result" , magnetUrl ) ;
makeUploadUrlRequest ( log , "/panel/task_add_httpftp_result" , magnetUrl ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case Remove :
case Remove :
// Remove a torrent
// Remove a torrent
RemoveTask removeTask = ( RemoveTask ) task ;
RemoveTask removeTask = ( RemoveTask ) task ;
makeRequest ( "/panel/task_delete" , new BasicNameValuePair ( "id" , removeTask . getTargetTorrent ( ) . getUniqueID ( ) ) ,
makeRequest ( log , "/panel/task_delete" ,
new BasicNameValuePair ( "action" , ( removeTask . includingData ( ) ? "delete_all" : "delete_task" ) ) ) ;
new BasicNameValuePair ( "id" , removeTask . getTargetTorrent ( ) . getUniqueID ( ) ) ,
return new DaemonTaskSuccessResult ( task ) ;
new BasicNameValuePair ( "action" ,
( removeTask . includingData ( ) ? "delete_all" : "delete_task" ) ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
case Pause :
case Pause :
// Pause a torrent
// Pause a torrent
makeRequest ( "/panel/task_action" , new BasicNameValuePair ( "id" , task . getTargetTorrent ( ) . getUniqueID ( ) ) , new BasicNameValuePair ( "action" , "stop" ) ) ;
makeRequest ( log , "/panel/task_action" ,
return new DaemonTaskSuccessResult ( task ) ;
new BasicNameValuePair ( "id" , task . getTargetTorrent ( ) . getUniqueID ( ) ) ,
new BasicNameValuePair ( "action" , "stop" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
case Resume :
case Resume :
// Resume a torrent
// Resume a torrent
makeRequest ( "/panel/task_action" , new BasicNameValuePair ( "id" , task . getTargetTorrent ( ) . getUniqueID ( ) ) , new BasicNameValuePair ( "action" , "start" ) ) ;
makeRequest ( log , "/panel/task_action" ,
return new DaemonTaskSuccessResult ( task ) ;
new BasicNameValuePair ( "id" , task . getTargetTorrent ( ) . getUniqueID ( ) ) ,
new BasicNameValuePair ( "action" , "start" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
case PauseAll :
case PauseAll :
// Suspend (pause) all active torrents
// Suspend (pause) all active torrents
makeRequest ( "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "suspend_all" ) ) ;
makeRequest ( log , "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "suspend_all" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case ResumeAll :
case ResumeAll :
// Resume suspended torrents
// Resume suspended torrents
makeRequest ( "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "resume_all" ) ) ;
makeRequest ( log , "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "resume_all" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case StopAll :
case StopAll :
// Stop all torrents
// Stop all torrents
makeRequest ( "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "stop_all" ) ) ;
makeRequest ( log , "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "stop_all" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case StartAll :
case StartAll :
// Start all torrents for download and seeding
// Start all torrents for download and seeding
makeRequest ( "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "start_all_download" ) ) ;
makeRequest ( log , "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "start_all_download" ) ) ;
makeRequest ( "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "start_all_seeding" ) ) ;
makeRequest ( log , "/panel/tasklist_action" , new BasicNameValuePair ( "id" , "start_all_seeding" ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
return new DaemonTaskSuccessResult ( task ) ;
case SetTransferRates :
case SetTransferRates :
// Request to set the maximum transfer rates
// Request to set the maximum transfer rates
SetTransferRatesTask ratesTask = ( SetTransferRatesTask ) task ;
SetTransferRatesTask ratesTask = ( SetTransferRatesTask ) task ;
String dl = Integer . toString ( ( ratesTask . getDownloadRate ( ) = = null ? - 1 : ratesTask . getDownloadRate ( ) . intValue ( ) ) ) ;
String dl =
String ul = Integer . toString ( ( ratesTask . getUploadRate ( ) = = null ? - 1 : ratesTask . getUploadRate ( ) . intValue ( ) ) ) ;
Integer . toString ( ( ratesTask . getDownloadRate ( ) = = null ? - 1 : ratesTask . getDownloadRate ( ) ) ) ;
makeRequest ( "/panel/option_set" , new BasicNameValuePair ( "key" , "down_rate_max" ) , new BasicNameValuePair ( "value" , dl ) ) ;
String ul = Integer . toString ( ( ratesTask . getUploadRate ( ) = = null ? - 1 : ratesTask . getUploadRate ( ) ) ) ;
makeRequest ( "/panel/option_set" , new BasicNameValuePair ( "key" , "up_rate_max" ) , new BasicNameValuePair ( "value" , ul ) ) ;
makeRequest ( log , "/panel/option_set" , new BasicNameValuePair ( "key" , "down_rate_max" ) ,
return new DaemonTaskSuccessResult ( task ) ;
new BasicNameValuePair ( "value" , dl ) ) ;
makeRequest ( log , "/panel/option_set" , new BasicNameValuePair ( "key" , "up_rate_max" ) ,
new BasicNameValuePair ( "value" , ul ) ) ;
return new DaemonTaskSuccessResult ( task ) ;
default :
default :
return new DaemonTaskFailureResult ( task , new DaemonException ( ExceptionType . MethodUnsupported , task . getMethod ( ) + " is not supported by " + getType ( ) ) ) ;
return new DaemonTaskFailureResult ( task , new DaemonException ( ExceptionType . MethodUnsupported ,
task . getMethod ( ) + " is not supported by " + getType ( ) ) ) ;
}
}
}
} catch ( DaemonException e ) {
catch ( DaemonException e ) {
return new DaemonTaskFailureResult ( task , new DaemonException ( ExceptionType . ParsingFailed , e . toString ( ) ) ) ;
return new DaemonTaskFailureResult ( task , new DaemonException ( ExceptionType . ParsingFailed , e . toString ( ) ) ) ;
}
}
}
}
/ * *
/ * *
* Instantiates an HTTP client with proper credentials that can be used for all Buffalo NAS requests .
* Instantiates an HTTP client with proper credentials that can be used for all Buffalo NAS requests .
* @param connectionTimeout The connection timeout in milliseconds
* @throws DaemonException On conflicting or missing settings
* @throws DaemonException On conflicting or missing settings
* /
* /
private void initialise ( int connectionTimeout ) throws DaemonException {
private void initialise ( ) throws DaemonException {
httpclient = HttpHelper . createStandardHttpClient ( settings , true ) ;
httpclient = HttpHelper . createStandardHttpClient ( settings , true ) ;
}
}
@ -225,13 +261,13 @@ public class BitCometAdapter implements IDaemonAdapter {
return ( settings . getSsl ( ) ? "https://" : "http://" ) + settings . getAddress ( ) + ":" + settings . getPort ( ) + path ;
return ( settings . getSsl ( ) ? "https://" : "http://" ) + settings . getAddress ( ) + ":" + settings . getPort ( ) + path ;
}
}
private String makeRequest ( String url , NameValuePair . . . params ) throws DaemonException {
private String makeRequest ( Log log , String url , NameValuePair . . . params ) throws DaemonException {
try {
try {
// Initialize the HTTP client
// Initialize the HTTP client
if ( httpclient = = null ) {
if ( httpclient = = null ) {
initialise ( HttpHelper . DEFAULT_CONNECTION_TIMEOUT ) ;
initialise ( ) ;
}
}
// Add the parameters to the query string
// Add the parameters to the query string
@ -260,25 +296,25 @@ public class BitCometAdapter implements IDaemonAdapter {
return result ;
return result ;
}
}
DL og. d ( LOG_NAME , "Error: No entity in HTTP response" ) ;
l og. d ( LOG_NAME , "Error: No entity in HTTP response" ) ;
throw new DaemonException ( ExceptionType . UnexpectedResponse , "No HTTP entity object in response." ) ;
throw new DaemonException ( ExceptionType . UnexpectedResponse , "No HTTP entity object in response." ) ;
} catch ( UnsupportedEncodingException e ) {
} catch ( UnsupportedEncodingException e ) {
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
DL og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
l og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
}
}
}
}
private boolean makeFileUploadRequest ( String path , String file ) throws DaemonException {
private boolean makeFileUploadRequest ( Log log , String path , String file ) throws DaemonException {
try {
try {
// Initialize the HTTP client
// Initialize the HTTP client
if ( httpclient = = null ) {
if ( httpclient = = null ) {
initialise ( HttpHelper . DEFAULT_CONNECTION_TIMEOUT ) ;
initialise ( ) ;
}
}
// Get default download file location first
// Get default download file location first
@ -291,13 +327,14 @@ public class BitCometAdapter implements IDaemonAdapter {
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 ;
String defaultPath = result . substring ( idx , result . indexOf ( "'>" , idx ) ) ;
String defaultPath = result . substring ( idx , result . indexOf ( "'>" , idx ) ) ;
// Setup request using POST
// Setup request using POST
HttpPost httppost = new HttpPost ( buildWebUIUrl ( path ) ) ;
HttpPost httppost = new HttpPost ( buildWebUIUrl ( path ) ) ;
File upload = new File ( URI . create ( file ) ) ;
File upload = new File ( URI . create ( file ) ) ;
Part [ ] parts = { new BitCometFilePart ( "torrent_file" , upload ) , new Utf8StringPart ( "save_path" , defaultPath ) } ;
Part [ ] parts =
{ new BitCometFilePart ( "torrent_file" , upload ) , new Utf8StringPart ( "save_path" , defaultPath ) } ;
httppost . setEntity ( new MultipartEntity ( parts , httppost . getParams ( ) ) ) ;
httppost . setEntity ( new MultipartEntity ( parts , httppost . getParams ( ) ) ) ;
// Make the request
// Make the request
@ -309,7 +346,9 @@ public class BitCometAdapter implements IDaemonAdapter {
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" ) ;
}
}
}
return response . getStatusLine ( ) . getStatusCode ( ) = = HttpStatus . SC_OK ;
return response . getStatusLine ( ) . getStatusCode ( ) = = HttpStatus . SC_OK ;
@ -319,18 +358,18 @@ public class BitCometAdapter implements IDaemonAdapter {
} catch ( FileNotFoundException e ) {
} catch ( FileNotFoundException e ) {
throw new DaemonException ( ExceptionType . FileAccessError , e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . FileAccessError , e . toString ( ) ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
DL og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
l og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
}
}
}
}
private boolean makeUploadUrlRequest ( String path , String url ) throws DaemonException {
private boolean makeUploadUrlRequest ( Log log , String path , String url ) throws DaemonException {
try {
try {
// Initialize the HTTP client
// Initialize the HTTP client
if ( httpclient = = null ) {
if ( httpclient = = null ) {
initialise ( HttpHelper . DEFAULT_CONNECTION_TIMEOUT ) ;
initialise ( ) ;
}
}
// Get default download file location first
// Get default download file location first
@ -343,7 +382,7 @@ public class BitCometAdapter implements IDaemonAdapter {
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 ;
String defaultPath = result . substring ( idx , result . indexOf ( "'>" , idx ) ) ;
String defaultPath = result . substring ( idx , result . indexOf ( "'>" , idx ) ) ;
// Setup form fields and post request
// Setup form fields and post request
@ -375,34 +414,36 @@ public class BitCometAdapter implements IDaemonAdapter {
}
}
return false ;
return false ;
} catch ( Exception e ) {
} catch ( Exception e ) {
DL og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
l og. d ( LOG_NAME , "Error: " + e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
throw new DaemonException ( ExceptionType . ConnectionError , e . toString ( ) ) ;
}
}
}
}
/ * *
/ * *
* Parse BitComet HTML page ( http response )
* Parse BitComet HTML page ( http response )
* @param response
* @param response The raw HTML response from the server
* @return
* @return The parsed list of torrents from the raw HTML content
* @throws DaemonException
* @throws DaemonException
* /
* /
private ArrayList < Torrent > parseHttpTorrents ( String response ) throws DaemonException {
private ArrayList < Torrent > parseHttpTorrents ( Log log , String response ) throws DaemonException {
ArrayList < Torrent > torrents = new ArrayList < Torrent > ( ) ;
ArrayList < Torrent > torrents = new ArrayList < Torrent > ( ) ;
try {
try {
// Find, prepare and split substring with HTML tag TABLE
// Find, prepare and split substring with HTML tag TABLE
String [ ] parts = response . substring ( response . indexOf ( "<TABLE" ) , response . indexOf ( "</TABLE>" ) ) . replaceAll ( "</td>" , "" ) . replaceAll ( "</tr>" , "" ) . replaceAll ( "\n" , "" ) . split ( "<tr>" ) ;
String [ ] parts =
response . substring ( response . indexOf ( "<TABLE" ) , response . indexOf ( "</TABLE>" ) ) . replaceAll ( "</td>" , "" )
. replaceAll ( "</tr>" , "" ) . replaceAll ( "\n" , "" ) . split ( "<tr>" ) ;
for ( int i = 2 ; i < parts . length ; i + + ) {
for ( int i = 2 ; i < parts . length ; i + + ) {
String [ ] subParts = parts [ i ] . replaceAll ( "<td>" , "<td" ) . split ( "<td" ) ;
String [ ] subParts = parts [ i ] . replaceAll ( "<td>" , "<td" ) . split ( "<td" ) ;
if ( subParts . length = = 10 & & subParts [ 1 ] . contains ( "BT" ) ) {
if ( subParts . length = = 10 & & subParts [ 1 ] . contains ( "BT" ) ) {
String name = subParts [ 2 ] . substring ( subParts [ 2 ] . indexOf ( "/panel/task_detail" ) ) ;
String name = subParts [ 2 ] . substring ( subParts [ 2 ] . indexOf ( "/panel/task_detail" ) ) ;
name = name . substring ( name . indexOf ( ">" ) + 1 , name . indexOf ( "<" ) ) ;
name = name . substring ( name . indexOf ( ">" ) + 1 , name . indexOf ( "<" ) ) ;
TorrentStatus status = convertStatus ( subParts [ 3 ] ) ;
TorrentStatus status = convertStatus ( subParts [ 3 ] ) ;
String percenDoneStr = subParts [ 6 ] ;
String percenDoneStr = subParts [ 6 ] ;
@ -411,10 +452,11 @@ public class BitCometAdapter implements IDaemonAdapter {
long size = convertSize ( subParts [ 5 ] ) ;
long size = convertSize ( subParts [ 5 ] ) ;
float percentDone = Float . parseFloat ( percenDoneStr . substring ( 0 , percenDoneStr . indexOf ( "%" ) ) ) ;
float percentDone = Float . parseFloat ( percenDoneStr . substring ( 0 , percenDoneStr . indexOf ( "%" ) ) ) ;
long sizeDone = ( long ) ( size * percentDone / 100 ) ;
long sizeDone = ( long ) ( size * percentDone / 100 ) ;
int rateUp = 1000 * Integer . parseInt ( uploadRateStr . substring ( 0 , uploadRateStr . indexOf ( "kB/s" ) ) ) ;
int rateUp = 1000 * Integer . parseInt ( uploadRateStr . substring ( 0 , uploadRateStr . indexOf ( "kB/s" ) ) ) ;
int rateDown = 1000 * Integer . parseInt ( downloadRateStr . substring ( 0 , downloadRateStr . indexOf ( "kB/s" ) ) ) ;
int rateDown =
1000 * Integer . parseInt ( downloadRateStr . substring ( 0 , downloadRateStr . indexOf ( "kB/s" ) ) ) ;
// Unfortunately, there is no info for above values providing by BitComet now,
// Unfortunately, there is no info for above values providing by BitComet now,
// so we may only send additional request for that
// so we may only send additional request for that
@ -423,42 +465,49 @@ public class BitCometAdapter implements IDaemonAdapter {
int knownLeechers = 0 ;
int knownLeechers = 0 ;
int knownSeeders = 0 ;
int knownSeeders = 0 ;
int distributed_copies = 0 ;
int distributed_copies = 0 ;
long sizeUp = 0 ;
long sizeUp ;
String comment = "" ;
String comment ;
Date dateAdded = new Date ( ) ;
Date dateAdded ;
// Comment code below to speedup torrent listing
// Comment code below to speedup torrent listing
// P.S. feature request to extend torrents info is already sent to the BitComet developers
// P.S. feature request to extend torrents info is already sent to the BitComet developers
//*
//*
try {
// Lets make summary request and parse details
// Lets make summary request and parse details
String summary = makeRequest ( log , "/panel/task_detail" , new BasicNameValuePair ( "id" , "" + ( i - 2 ) ) ,
String summary = makeRequest ( "/panel/task_detail" , new BasicNameValuePair ( "id" , "" + ( i - 2 ) ) , new BasicNameValuePair ( "show" , "summary" ) ) ;
new BasicNameValuePair ( "show" , "summary" ) ) ;
String [ ] sumParts = summary . substring ( summary . indexOf ( "<div align=\"left\">Value</div></th>" ) ) . split ( "<tr><td>" ) ;
String [ ] sumParts = summary . substring ( summary . indexOf ( "<div align=\"left\">Value</div></th>" ) )
comment = sumParts [ 7 ] . substring ( sumParts [ 7 ] . indexOf ( "<td>" ) + 4 , sumParts [ 7 ] . indexOf ( "</td></tr>" ) ) ;
. split ( "<tr><td>" ) ;
comment = sumParts [ 7 ] . substring ( sumParts [ 7 ] . indexOf ( "<td>" ) + 4 , sumParts [ 7 ] . indexOf ( "</td></tr>" ) ) ;
// Indexes for date and uploaded size
int idx = 9 ;
// Indexes for date and uploaded size
int s izeI dx = 12 ;
int idx = 9 ;
int sizeIdx = 12 ;
if ( status = = TorrentStatus . Downloading ) {
seeders = Integer . parseInt ( sumParts [ 9 ] . substring ( sumParts [ 9 ] . indexOf ( "Seeds:" ) + 6 , sumParts [ 9 ] . indexOf ( "(Max possible" ) ) ) ;
if ( status = = TorrentStatus . Downloading ) {
leech ers = Integer . parseInt ( sumParts [ 9 ] . substring ( sumParts [ 9 ] . indexOf ( "Peers:" ) + 6 , sumParts [ 9 ] . lastIndexOf ( "(Max possible" ) ) ) ;
seed ers = Integer . parseInt ( sumParts [ 9 ]
knownSeeders = Integer . parseInt ( sumParts [ 9 ] . substring ( sumParts [ 9 ] . indexOf ( "(Max possible:" ) + 14 , sumParts [ 9 ] . indexOf ( ") " ) ) ) ;
. substring ( sumParts [ 9 ] . indexOf ( "Seeds:" ) + 6 , sumParts [ 9 ] . indexOf ( "(Max possible " ) ) ) ;
knownL eechers = Integer . parseInt ( sumParts [ 9 ] . substring ( sumParts [ 9 ] . lastIndexOf ( "(Max possible:" ) + 14 , sumParts [ 9 ] . lastIndexOf ( ")" ) ) ) ;
l eechers = Integer . parseInt ( sumParts [ 9 ] . substring ( sumParts [ 9 ] . indexOf ( "Peers:" ) + 6 ,
idx = 13 ;
sumParts [ 9 ] . lastIndexOf ( "(Max possible" ) ) ) ;
sizeIdx = 16 ;
knownSeeders = Integer . parseInt ( sumParts [ 9 ]
}
. substring ( sumParts [ 9 ] . indexOf ( "(Max possible:" ) + 14 , sumParts [ 9 ] . indexOf ( ")" ) ) ) ;
knownLeechers = Integer . parseInt ( sumParts [ 9 ]
DateFormat df = new SimpleDateFormat ( "yyyy-mm-dd kk:mm:ss" ) ;
. substring ( sumParts [ 9 ] . lastIndexOf ( "(Max possible:" ) + 14 ,
dateAdded = df . parse ( sumParts [ idx ] . substring ( sumParts [ idx ] . i ndexOf( "<td>" ) + 4 , sumParts [ idx ] . indexOf ( "</td></tr> ") ) ) ;
sumParts [ 9 ] . lastI ndexOf ( ")" ) ) ) ;
//sizeDone = convertSize(sumParts[sizeIdx].substring(sumParts[sizeIdx].indexOf("<td>")+4, sumParts[sizeIdx].indexOf(" (")));
idx = 13 ;
sizeUp = convertSize ( sumParts [ sizeIdx + 1 ] . substring ( sumParts [ sizeIdx + 1 ] . indexOf ( "<td>" ) + 4 , sumParts [ sizeIdx + 1 ] . indexOf ( " (" ) ) ) ;
sizeIdx = 16 ;
}
}
catch ( Exception e ) { }
DateFormat df = new SimpleDateFormat ( "yyyy-mm-dd kk:mm:ss" ) ;
dateAdded = df . parse ( sumParts [ idx ]
. substring ( sumParts [ idx ] . indexOf ( "<td>" ) + 4 , sumParts [ idx ] . indexOf ( "</td></tr>" ) ) ) ;
//sizeDone = convertSize(sumParts[sizeIdx].substring(sumParts[sizeIdx].indexOf("<td>")+4, sumParts[sizeIdx].indexOf(" (")));
sizeUp = convertSize ( sumParts [ sizeIdx + 1 ]
. substring ( sumParts [ sizeIdx + 1 ] . indexOf ( "<td>" ) + 4 , sumParts [ sizeIdx + 1 ] . indexOf ( " (" ) ) ) ;
//*
//*
// Add the parsed torrent to the list
// Add the parsed torrent to the list
// @formatter:off
torrents . add ( new Torrent (
torrents . add ( new Torrent (
( long ) i - 2 ,
( long ) i - 2 ,
null ,
null ,
@ -482,10 +531,10 @@ public class BitCometAdapter implements IDaemonAdapter {
null ,
null ,
null ,
null ,
settings . getType ( ) ) ) ;
settings . getType ( ) ) ) ;
// @formatter:on
}
}
}
}
}
} catch ( Exception e ) {
catch ( Exception e ) {
throw new DaemonException ( ExceptionType . UnexpectedResponse , "Invalid BitComet HTTP response." ) ;
throw new DaemonException ( ExceptionType . UnexpectedResponse , "Invalid BitComet HTTP response." ) ;
}
}
@ -493,13 +542,12 @@ public class BitCometAdapter implements IDaemonAdapter {
}
}
/ * *
/ * *
* Parse BitComet AJAX response
* Parse BitComet AJAX response that code was copy - pasted and slightly modified from \ Ktorrent \ StatsParser . java
* that code was copy - pasted and slightly modified from \ Ktorrent \ StatsParser . java
* @param response The raw XML data as string that was returned by the server
* @param response
* @return The parsed list of torrents from the XML
* @return
* @throws DaemonException
* @throws DaemonException
* /
* /
private ArrayList < Torrent > parseXmlTorrents ( String response ) throws DaemonException {
private ArrayList < Torrent > parseXmlTorrents ( String response ) throws DaemonException {
ArrayList < Torrent > torrents = new ArrayList < Torrent > ( ) ;
ArrayList < Torrent > torrents = new ArrayList < Torrent > ( ) ;
@ -511,8 +559,7 @@ public class BitCometAdapter implements IDaemonAdapter {
// Temp variables to load into torrent objects
// Temp variables to load into torrent objects
int id = 0 ;
int id = 0 ;
String name = "" ;
String name = "" ;
@SuppressWarnings ( "unused" )
@SuppressWarnings ( "unused" ) String hash = "" ;
String hash = "" ;
TorrentStatus status = TorrentStatus . Unknown ;
TorrentStatus status = TorrentStatus . Unknown ;
long sizeDone = 0 ;
long sizeDone = 0 ;
long sizeUp = 0 ;
long sizeUp = 0 ;
@ -537,6 +584,7 @@ public class BitCometAdapter implements IDaemonAdapter {
// End of a 'transfer' item, add gathered torrent data
// End of a 'transfer' item, add gathered torrent data
sizeDone = ( long ) ( totalSize * progress ) ;
sizeDone = ( long ) ( totalSize * progress ) ;
// @formatter:off
torrents . add ( new Torrent (
torrents . add ( new Torrent (
id ,
id ,
null , // hash, // we suppose to use simple integer IDs
null , // hash, // we suppose to use simple integer IDs
@ -560,10 +608,11 @@ public class BitCometAdapter implements IDaemonAdapter {
null ,
null ,
null , // Not supported in the web interface
null , // Not supported in the web interface
settings . getType ( ) ) ) ;
settings . getType ( ) ) ) ;
// @formatter:on
id + + ; // Stop/start/etc. requests are made by ID, which is the order number in the returned XML list :-S
id + + ; // Stop/start/etc. requests are made by ID, which is the order number in the returned XML list :-S
} else if ( next = = XmlPullParser . START_TAG & & tagName . equals ( "task" ) ) {
} else if ( next = = XmlPullParser . START_TAG & & tagName . equals ( "task" ) ) {
// Start of a new 'transfer' item; reset gathered torrent data
// Start of a new 'transfer' item; reset gathered torrent data
name = "" ;
name = "" ;
@ -582,7 +631,7 @@ public class BitCometAdapter implements IDaemonAdapter {
label = "" ;
label = "" ;
dateAdded = new Date ( ) ;
dateAdded = new Date ( ) ;
} else if ( next = = XmlPullParser . START_TAG ) {
} else if ( next = = XmlPullParser . START_TAG ) {
// Probably encountered a torrent property, i.e. '<type>BT</type>'
// Probably encountered a torrent property, i.e. '<type>BT</type>'
next = xpp . next ( ) ;
next = xpp . next ( ) ;
@ -638,8 +687,8 @@ public class BitCometAdapter implements IDaemonAdapter {
/ * *
/ * *
* Parse BitComet HTML page ( HTTP response )
* Parse BitComet HTML page ( HTTP response )
* @param response
* @param response The raw HTML response from the server
* @return
* @return The parsed list of files in the torrent from the raw HTML
* @throws DaemonException
* @throws DaemonException
* /
* /
private ArrayList < TorrentFile > parseHttpTorrentFiles ( String response , String hash ) throws DaemonException {
private ArrayList < TorrentFile > parseHttpTorrentFiles ( String response , String hash ) throws DaemonException {
@ -649,19 +698,21 @@ public class BitCometAdapter implements IDaemonAdapter {
try {
try {
String [ ] files = response . substring ( response . indexOf ( "Operation Method</div></th>" ) + 27 , response . lastIndexOf ( "</TABLE>" ) ) . replaceAll ( "</td>" , "" ) . replaceAll ( "</tr>" , "" ) . split ( "<tr>" ) ;
String [ ] files = response . substring ( response . indexOf ( "Operation Method</div></th>" ) + 27 ,
response . lastIndexOf ( "</TABLE>" ) ) . replaceAll ( "</td>" , "" ) . replaceAll ( "</tr>" , "" ) . split ( "<tr>" ) ;
for ( int i = 1 ; i < files . length ; i + + ) {
for ( int i = 1 ; i < files . length ; i + + ) {
String [ ] fileDetails = files [ i ] . replace ( ">" , "" ) . split ( "<td" ) ;
String [ ] fileDetails = files [ i ] . replace ( ">" , "" ) . split ( "<td" ) ;
long size = convertSize ( fileDetails [ 4 ] . substring ( fileDetails [ 4 ] . indexOf ( "   " ) + 11 ) ) ;
long size = convertSize ( fileDetails [ 4 ] . substring ( fileDetails [ 4 ] . indexOf ( "   " ) + 11 ) ) ;
long sizeDone = 0 ;
long sizeDone = 0 ;
if ( ! fileDetails [ 2 ] . contains ( "--" ) ) {
if ( ! fileDetails [ 2 ] . contains ( "--" ) ) {
double percentDone = Double . parseDouble ( fileDetails [ 2 ] . substring ( 0 , fileDetails [ 2 ] . indexOf ( "%" ) ) ) ;
double percentDone = Double . parseDouble ( fileDetails [ 2 ] . substring ( 0 , fileDetails [ 2 ] . indexOf ( "%" ) ) ) ;
sizeDone = ( long ) ( size / 100 . 0 * percentDone ) ;
sizeDone = ( long ) ( size / 100 . 0 * percentDone ) ;
}
}
// @formatter:off
torrentfiles . add ( new TorrentFile (
torrentfiles . add ( new TorrentFile (
hash ,
hash ,
fileDetails [ 3 ] ,
fileDetails [ 3 ] ,
@ -670,9 +721,9 @@ public class BitCometAdapter implements IDaemonAdapter {
size ,
size ,
sizeDone ,
sizeDone ,
convertPriority ( fileDetails [ 1 ] ) ) ) ;
convertPriority ( fileDetails [ 1 ] ) ) ) ;
// @formatter:on
}
}
}
} catch ( Exception e ) {
catch ( Exception e ) {
throw new DaemonException ( ExceptionType . UnexpectedResponse , "Invalid BitComet HTTP response." ) ;
throw new DaemonException ( ExceptionType . UnexpectedResponse , "Invalid BitComet HTTP response." ) ;
}
}
@ -680,30 +731,9 @@ public class BitCometAdapter implements IDaemonAdapter {
return torrentfiles ;
return torrentfiles ;
}
}
/ * *
* Returns the size of the torrent , as parsed form some string
* @param size The size in a string format , i . e . ' 691 MB '
* @return The size in bytes
* /
private static long convertSize ( String size ) {
try {
if ( size . endsWith ( "GB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "GB" ) ) ) * 1024 * 1024 * 1024 ) ;
} else if ( size . endsWith ( "MB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "MB" ) ) ) * 1024 * 1024 ) ;
} else if ( size . endsWith ( "kB" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "kB" ) ) ) * 1024 ) ;
} else if ( size . endsWith ( "B" ) ) {
return ( long ) ( Float . parseFloat ( size . substring ( 0 , size . indexOf ( "B" ) ) ) ) ;
}
}
catch ( Exception e ) { }
return 0 ;
}
/ * *
/ * *
* Parse BitComet torrent files priority
* Parse BitComet torrent files priority
* * /
* /
private Priority convertPriority ( String priority ) {
private Priority convertPriority ( String priority ) {
if ( priority . equals ( "Very High" ) | | priority . equals ( "High" ) ) {
if ( priority . equals ( "Very High" ) | | priority . equals ( "High" ) ) {
return Priority . High ;
return Priority . High ;
@ -715,7 +745,7 @@ public class BitCometAdapter implements IDaemonAdapter {
/ * *
/ * *
* Parse BitComet torrent status
* Parse BitComet torrent status
* * /
* /
private TorrentStatus convertStatus ( String state ) {
private TorrentStatus convertStatus ( String state ) {
// Status is given as a descriptive string and an indication if the torrent was stopped/paused
// Status is given as a descriptive string and an indication if the torrent was stopped/paused
if ( state . equals ( "stopped" ) ) {
if ( state . equals ( "stopped" ) ) {
@ -726,15 +756,6 @@ public class BitCometAdapter implements IDaemonAdapter {
return TorrentStatus . Unknown ;
return TorrentStatus . Unknown ;
}
}
/ * *
* Returns the part done ( or progress ) of a torrent , as parsed from some string
* @param progress The part done in a string format , i . e . ' 15 . 96 '
* @return The part done as [ 0 . . 1 ] fraction , i . e . 0 . 1596
* /
public static float convertProgress ( String progress ) {
return Float . parseFloat ( progress ) / 1000 . 0f ;
}
@Override
@Override
public Daemon getType ( ) {
public Daemon getType ( ) {
return settings . getType ( ) ;
return settings . getType ( ) ;