Commit e21efa45 authored by Habib Kazemi's avatar Habib Kazemi Committed by Geoffrey Métais

Update Subtitle downloader

Subtitle downloader now uses the opensubtitle rest api
So I removed the XMLRPC library and old subtitle downloader
and I added dialog fragment to choose subtitles from availabls subtitles
we also support manual search for subtitles now.
Signed-off-by: default avatarGeoffrey Métais <geoffrey.metais@gmail.com>
parent 32409efe
......@@ -32,6 +32,7 @@ ext {
junitVersion = '4.12'
mockito = '2.8.9'
powerMock = '1.7.4'
retrofit = '2.4.0'
espressoVersion = '3.0.1'
supportTest = '1.0.2'
minSdkVersion = 17
......
apply plugin: 'java'
sourceCompatibility = 1.6
targetCompatibility = 1.6
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
\ No newline at end of file
package de.timroes.axmlrpc;
import de.timroes.base64.Base64;
import java.net.HttpURLConnection;
/**
* The AuthenticationManager handle basic HTTP authentication.
*
* @author Tim Roes
*/
public class AuthenticationManager {
private String user;
private String pass;
/**
* Clear the username and password. No basic HTTP authentication will be used
* in the next calls.
*/
public void clearAuthData() {
this.user = null;
this.pass = null;
}
/**
* Set the username and password that should be used to perform basic
* http authentication.
*
* @param user Username
* @param pass Password
*/
public void setAuthData(String user, String pass) {
this.user = user;
this.pass = pass;
}
/**
* Set the authentication at the HttpURLConnection.
*
* @param http The HttpURLConnection to set authentication.
*/
public void setAuthentication(HttpURLConnection http) {
if(user == null || pass == null
|| user.length() <= 0 || pass.length() <= 0) {
return;
}
String base64login = Base64.encode(user + ":" + pass);
http.addRequestProperty("Authorization", "Basic " + base64login);
}
}
\ No newline at end of file
package de.timroes.axmlrpc;
import de.timroes.axmlrpc.serializer.SerializerHandler;
import de.timroes.axmlrpc.xmlcreator.SimpleXMLCreator;
import de.timroes.axmlrpc.xmlcreator.XmlElement;
/**
* A Call object represents a call of a remote methode.
* It contains the name of the method to be called and the parameters to use
* in this remote procedure call. To send it over the network the method getXML
* returns an xml representation according to the XML-RPC specification as a String.
*
* @author Tim Roes
*/
public class Call {
private String method;
private Object[] params;
/**
* Create a new method call with the given name and no parameters.
* @param method The method to be called.
*/
public Call(String method) {
this(method, null);
}
/**
* Create a new method call with the given name and parameters.
* @param method The method to be called.
* @param params An array of parameters for the method.
*/
public Call(String method, Object[] params) {
this.method = method;
this.params = params;
}
/**
* Return an xml representation of the method call as specified in
* http://www.xmlrpc.com/spec. If flags have been set in the XMLRPCClient
* the returning xml does not comply strict to the standard.
*
* @return The string of the xml representing this call.
* @throws XMLRPCException Will be thrown whenever the xml representation cannot
* be build without errors.
* @see XMLRPCClient
*/
public String getXML(boolean debugMode) throws XMLRPCException {
SimpleXMLCreator creator = new SimpleXMLCreator();
XmlElement methodCall = new XmlElement(XMLRPCClient.METHOD_CALL);
creator.setRootElement(methodCall);
XmlElement methodName = new XmlElement(XMLRPCClient.METHOD_NAME);
methodName.setContent(method);
methodCall.addChildren(methodName);
if(params != null && params.length > 0) {
XmlElement params = new XmlElement(XMLRPCClient.PARAMS);
methodCall.addChildren(params);
for(Object o : this.params) {
params.addChildren(getXMLParam(o));
}
}
String result = creator.toString();
if ( debugMode){
System.out.println(result);
}
return result;
}
/**
* Generates the param xml tag for a specific parameter object.
*
* @param o The parameter object.
* @return The object serialized into an xml tag.
* @throws XMLRPCException Will be thrown if the serialization failed.
*/
private XmlElement getXMLParam(Object o) throws XMLRPCException {
XmlElement param = new XmlElement(XMLRPCClient.PARAM);
XmlElement value = new XmlElement(XMLRPCClient.VALUE);
param.addChildren(value);
value.addChildren(SerializerHandler.getDefault().serialize(o));
return param;
}
}
package de.timroes.axmlrpc;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* The CookieManager handles cookies for the http requests.
* If the FLAGS_ENABLE_COOKIES has been set, it will save cookies
* and send it with every request.
*
* @author Tim Roes
*/
class CookieManager {
private static final String SET_COOKIE = "Set-Cookie";
private static final String COOKIE = "Cookie";
private int flags;
private Map<String,String> cookies = new ConcurrentHashMap<String, String>();
/**
* Create a new CookieManager with the given flags.
*
* @param flags A combination of flags to be set.
*/
public CookieManager(int flags) {
this.flags = flags;
}
/**
* Delete all cookies.
*/
public void clearCookies() {
cookies.clear();
}
/**
* Returns a {@link Map} of all cookies.
*
* @return All cookies
*/
public Map<String,String> getCookies() {
return cookies;
}
/**
* Read the cookies from an http response. It will look at every Set-Cookie
* header and put the cookie to the map of cookies.
*
* @param http A http connection.
*/
public void readCookies(HttpURLConnection http) {
// Only save cookies if FLAGS_ENABLE_COOKIES has been set.
if((flags & XMLRPCClient.FLAGS_ENABLE_COOKIES) == 0)
return;
String cookie, key;
String[] split;
// Extract every Set-Cookie field and put the cookie to the cookies map.
for(int i = 0; i < http.getHeaderFields().size(); i++) {
key = http.getHeaderFieldKey(i);
if(key != null && SET_COOKIE.toLowerCase().equals(key.toLowerCase())) {
cookie = http.getHeaderField(i).split(";")[0];
split = cookie.split("=");
if(split.length >= 2)
cookies.put(split[0], split[1]);
}
}
}
/**
* Write the cookies to a http connection. It will set the Cookie field
* to all currently set cookies in the map.
*
* @param http A http connection.
*/
public void setCookies(HttpURLConnection http) {
// Only save cookies if FLAGS_ENABLE_COOKIES has been set.
if((flags & XMLRPCClient.FLAGS_ENABLE_COOKIES) == 0)
return;
String concat = "";
for(Map.Entry<String,String> cookie : cookies.entrySet()) {
concat += cookie.getKey() + "=" + cookie.getValue() + "; ";
}
http.setRequestProperty(COOKIE, concat);
}
}
\ No newline at end of file
package de.timroes.axmlrpc;
import de.timroes.axmlrpc.serializer.SerializerHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* The ResponseParser parses the response of an XMLRPC server to an object.
*
* @author Tim Roes
*/
class ResponseParser {
private static final String FAULT_CODE = "faultCode";
private static final String FAULT_STRING = "faultString";
/**
* The given InputStream must contain the xml response from an xmlrpc server.
* This method extract the content of it as an object.
*
* @param response The InputStream of the server response.
* @return The returned object.
* @throws XMLRPCException Will be thrown whenever something fails.
* @throws XMLRPCServerException Will be thrown, if the server returns an error.
*/
public Object parse(InputStream response, boolean debugMode) throws XMLRPCException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(response);
if (debugMode ){
printDocument(dom, System.out);
}
Element e = dom.getDocumentElement();
// Check for root tag
if(!e.getNodeName().equals(XMLRPCClient.METHOD_RESPONSE)) {
throw new XMLRPCException("MethodResponse root tag is missing.");
}
e = XMLUtil.getOnlyChildElement(e.getChildNodes());
if(e.getNodeName().equals(XMLRPCClient.PARAMS)) {
e = XMLUtil.getOnlyChildElement(e.getChildNodes());
if(!e.getNodeName().equals(XMLRPCClient.PARAM)) {
throw new XMLRPCException("The params tag must contain a param tag.");
}
return getReturnValueFromElement(e);
} else if(e.getNodeName().equals(XMLRPCClient.FAULT)) {
@SuppressWarnings("unchecked")
Map<String,Object> o = (Map<String,Object>)getReturnValueFromElement(e);
throw new XMLRPCServerException((String)o.get(FAULT_STRING), (Integer)o.get(FAULT_CODE));
}
throw new XMLRPCException("The methodResponse tag must contain a fault or params tag.");
} catch (Exception ex) {
if(ex instanceof XMLRPCServerException)
throw (XMLRPCServerException)ex;
else
throw new XMLRPCException("Error getting result from server.", ex);
}
}
public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}
/**
* This method takes an element (must be a param or fault element) and
* returns the deserialized object of this param tag.
*
* @param element An param element.
* @return The deserialized object within the given param element.
* @throws XMLRPCException Will be thrown when the structure of the document
* doesn't match the XML-RPC specification.
*/
private Object getReturnValueFromElement(Element element) throws XMLRPCException {
element = XMLUtil.getOnlyChildElement(element.getChildNodes());
return SerializerHandler.getDefault().deserialize(element);
}
}
\ No newline at end of file
package de.timroes.axmlrpc;
/**
* The XMLRPCCallback interface must be implemented by a listener for an
* asynchronous call to a server method.
* When the server responds, the corresponding method on the listener is called.
*
* @author Tim Roes
*/
public interface XMLRPCCallback {
/**
* This callback is called whenever the server successfully responds.
*
* @param id The id as returned by the XMLRPCClient.asyncCall(..) method for this request.
* @param result The Object returned from the server.
*/
public void onResponse(long id, Object result);
/**
* This callback is called whenever an error occurs during the method call.
*
* @param id The id as returned by the XMLRPCClient.asyncCall(..) method for this request.
* @param error The error occured.
*/
public void onError(long id, XMLRPCException error);
/**
* This callback is called whenever the server returns an error.
*
* @param id The id as returned by the XMLRPCClient.asyncCall(..) method for this request.
* @param error The error returned from the server.
*/
public void onServerError(long id, XMLRPCServerException error);
}
package de.timroes.axmlrpc;
import de.timroes.axmlrpc.serializer.SerializerHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.*;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.*;
/**
* An XMLRPCClient is a client used to make XML-RPC (Extensible Markup Language
* Remote Procedure Calls).
* The specification of XMLRPC can be found at http://www.xmlrpc.com/spec.
* You can use flags to extend the functionality of the client to some extras.
* Further information on the flags can be found in the documentation of these.
* For a documentation on how to use this class see also the README file delivered
* with the source of this library.
*
* @author Tim Roes
*/
public class XMLRPCClient {
private static final String DEFAULT_USER_AGENT = "aXMLRPC";
/**
* Constants from the http protocol.
*/
static final String USER_AGENT = "User-Agent";
static final String CONTENT_TYPE = "Content-Type";
static final String TYPE_XML = "text/xml; charset=utf-8";
static final String HOST = "Host";
static final String CONTENT_LENGTH = "Content-Length";
static final String HTTP_POST = "POST";
/**
* XML elements to be used.
*/
static final String METHOD_RESPONSE = "methodResponse";
static final String PARAMS = "params";
static final String PARAM = "param";
public static final String VALUE = "value";
static final String FAULT = "fault";
static final String METHOD_CALL = "methodCall";
static final String METHOD_NAME = "methodName";
static final String STRUCT_MEMBER = "member";
/**
* No flags should be set.
*/
public static final int FLAGS_NONE = 0x0;
/**
* The client should parse responses strict to specification.
* It will check if the given content-type is right.
* The method name in a call must only contain of A-Z, a-z, 0-9, _, ., :, /
* Normally this is not needed.
*/
public static final int FLAGS_STRICT = 0x01;
/**
* The client will be able to handle 8 byte integer values (longs).
* The xml type tag &lt;i8&gt; will be used. This is not in the specification
* but some libraries and servers support this behaviour.
* If this isn't enabled you cannot recieve 8 byte integers and if you try to
* send a long the value must be within the 4byte integer range.
*/
public static final int FLAGS_8BYTE_INT = 0x02;
/**
* With this flag, the client will be able to handle cookies, meaning saving cookies
* from the server and sending it with every other request again. This is needed
* for some XML-RPC interfaces that support login.
*/
public static final int FLAGS_ENABLE_COOKIES = 0x04;
/**
* The client will be able to send null values. A null value will be send
* as <nil/>. This extension is described under: http://ontosys.com/xml-rpc/extensions.php
*/
public static final int FLAGS_NIL = 0x08;
/**
* With this flag enabled, the XML-RPC client will ignore the HTTP status
* code of the response from the server. According to specification the
* status code must be 200. This flag is only needed for the use with
* not standard compliant servers.
*/
public static final int FLAGS_IGNORE_STATUSCODE = 0x10;
/**
* With this flag enabled, the client will forward the request, if
* the 301 or 302 HTTP status code has been received. If this flag has not
* been set, the client will throw an exception on these HTTP status codes.
*/
public static final int FLAGS_FORWARD = 0x20;
/**
* With this flag enabled, the client will ignore, if the URL doesn't match
* the SSL Certificate. This should be used with caution. Normally the URL
* should always match the URL in the SSL certificate, even with self signed
* certificates.
*/
public static final int FLAGS_SSL_IGNORE_INVALID_HOST = 0x40;
/**
* With this flag enabled, the client will ignore all unverified SSL/TLS
* certificates. This must be used, if you use self-signed certificates
* or certificated from unknown (or untrusted) authorities. If this flag is
* used, calls to {@link #installCustomTrustManager(javax.net.ssl.TrustManager)}
* won't have any effect.
*/
public static final int FLAGS_SSL_IGNORE_INVALID_CERT = 0x80;
/**
* With this flag enabled, a value with a missing type tag, will be parsed
* as a string element. This is just for incoming messages. Outgoing messages
* will still be generated according to specification.
*/
public static final int FLAGS_DEFAULT_TYPE_STRING = 0x100;
/**
* With this flag enabled, the {@link XMLRPCClient} ignores all namespaces
* used within the response from the server.
*/
public static final int FLAGS_IGNORE_NAMESPACES = 0x200;
/**
* With this flag enabled, the {@link XMLRPCClient} will use the system http
* proxy to connect to the XML-RPC server.
*/
public static final int FLAGS_USE_SYSTEM_PROXY = 0x400;
/**
* This prevents the decoding of incoming strings, meaning &amp; and &lt;
* won't be decoded to the & sign and the "less then" sign. See
* {@link #FLAGS_NO_STRING_ENCODE} for the counterpart.
*/
public static final int FLAGS_NO_STRING_DECODE = 0x800;
/**
* By default outgoing string values will be encoded according to specification.
* Meaning the & sign will be encoded to &amp; and the "less then" sign to &lt;.
* If you set this flag, the encoding won't be done for outgoing string values.
* See {@link #FLAGS_NO_STRING_ENCODE} for the counterpart.
*/
public static final int FLAGS_NO_STRING_ENCODE = 0x1000;
/**
* Activate debug mode.
* Do NOT use if you don't need it.
*/
public static final int FLAGS_DEBUG = 0x2000;
/**
* This flag disables all SSL warnings. It is an alternative to use
* FLAGS_SSL_IGNORE_INVALID_CERT | FLAGS_SSL_IGNORE_INVALID_HOST. There
* is no functional difference.
*/
public static final int FLAGS_SSL_IGNORE_ERRORS =
FLAGS_SSL_IGNORE_INVALID_CERT | FLAGS_SSL_IGNORE_INVALID_HOST;
/**
* This flag should be used if the server is an apache ws xmlrpc server.
* This will set some flags, so that the not standard conform behavior
* of the server will be ignored.
* This will enable the following flags: FLAGS_IGNORE_NAMESPACES, FLAGS_NIL,
* FLAGS_DEFAULT_TYPE_STRING
*/
public static final int FLAGS_APACHE_WS = FLAGS_IGNORE_NAMESPACES | FLAGS_NIL
| FLAGS_DEFAULT_TYPE_STRING;
private final int flags;
private URL url;
private Map<String,String> httpParameters = new ConcurrentHashMap<String, String>();
private Map<Long,Caller> backgroundCalls = new ConcurrentHashMap<Long, Caller>();
private ResponseParser responseParser;
private CookieManager cookieManager;
private AuthenticationManager authManager;
private TrustManager[] trustManagers;
private KeyManager[] keyManagers;
private Proxy proxy;
private int timeout;
/**
* Create a new XMLRPC client for the given URL.
*
* @param url The URL to send the requests to.
* @param userAgent A user agent string to use in the HTTP requests.
* @param flags A combination of flags to be set.
*/
public XMLRPCClient(URL url, String userAgent, int flags) {
SerializerHandler.initialize(flags);
this.url = url;
this.flags = flags;
// Create a parser for the http responses.
responseParser = new ResponseParser();
cookieManager = new CookieManager(flags);
authManager = new AuthenticationManager();
httpParameters.put(CONTENT_TYPE, TYPE_XML);
httpParameters.put(USER_AGENT, userAgent);
// If invalid ssl certs are ignored, instantiate an all trusting TrustManager
if(isFlagSet(FLAGS_SSL_IGNORE_INVALID_CERT)) {
trustManagers = new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string)
throws CertificateException { }
public void checkServerTrusted(X509Certificate[] xcs, String string)
throws CertificateException { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
}
if(isFlagSet(FLAGS_USE_SYSTEM_PROXY)) {
// Read system proxy settings and generate a proxy from that
Properties prop = System.getProperties();
String proxyHost = prop.getProperty("http.proxyHost");
int proxyPort = Integer.parseInt(prop.getProperty("http.proxyPort", "0"));
if(proxyPort > 0 && proxyHost.length() > 0