summaryrefslogtreecommitdiff
path: root/vdrmanager
diff options
context:
space:
mode:
authorbju <bju@maxi.fritz.box>2013-03-27 02:33:23 +0100
committerbju <bju@maxi.fritz.box>2013-03-27 02:33:23 +0100
commit4b463c74709701f2328d314811974a30a6e54e17 (patch)
tree1bfb66963dd05b11f278ce85e56d13c8b5baa0d8 /vdrmanager
parentdbf28d356eb97b3075229bbc42a8a3ccf1c94ec0 (diff)
downloadvdr-manager-4b463c74709701f2328d314811974a30a6e54e17.tar.gz
vdr-manager-4b463c74709701f2328d314811974a30a6e54e17.tar.bz2
SSL without server certificate validation is working now
Diffstat (limited to 'vdrmanager')
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/MySSLSocketFactory.java178
-rw-r--r--vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java899
2 files changed, 624 insertions, 453 deletions
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/MySSLSocketFactory.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/MySSLSocketFactory.java
new file mode 100644
index 0000000..9ef0788
--- /dev/null
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/MySSLSocketFactory.java
@@ -0,0 +1,178 @@
+package de.bjusystems.vdrmanager.utils.svdrp;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+
+/**
+ * SSLSocketFactory
+ * @author bju
+ */
+public class MySSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory {
+
+ /** the key store */
+ private KeyStore keyStore;
+
+ /** the real socket factory */
+ private final SSLSocketFactory sslFactory;
+
+ /** the trust managers */
+ private X509TrustManager[] trustManagers;
+
+ public MySSLSocketFactory(final boolean acceptAllCertificates)
+ throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException {
+
+ super(null);
+
+ // accept all host names
+ this.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+
+ // load the keystore
+ initKeyStore();
+
+ // init the trust managers
+ if (acceptAllCertificates) {
+ initInsecureTrustManagers();
+ } else {
+ initSecureTrustManagers();
+ }
+
+ // create SSL context
+ final SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, trustManagers, new SecureRandom());
+
+ // create the real factory
+ sslFactory = context.getSocketFactory();
+
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return sslFactory.createSocket();
+ }
+
+ /**
+ * initialize the key store
+ * @return KeyStore
+ * @throws KeyStoreException
+ */
+ private void initKeyStore() throws KeyStoreException {
+
+ keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ // keyStore.load(...);
+ }
+
+ /**
+ * initialize the trust managers validating certificates
+ * @param acceptAllCertificates accept all certificates
+ * @throws NoSuchAlgorithmException
+ * @throws KeyStoreException
+ */
+ private void initSecureTrustManagers() throws NoSuchAlgorithmException, KeyStoreException {
+
+ final List<X509TrustManager> trustManagerList = new ArrayList<X509TrustManager>();
+
+ // init the trust manager accepting certificates contained in the key store
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
+ trustManagerFactory.init(keyStore);
+ X509TrustManager trustManager = getTrustManager(trustManagerFactory);
+ if (trustManager != null) {
+ trustManagerList.add(trustManager);
+ }
+
+ // init the trust manager accepting certificates accepted from the system
+ trustManagerFactory = TrustManagerFactory.getInstance("X509");
+ trustManagerFactory.init((KeyStore)null);
+ trustManager = getTrustManager(trustManagerFactory);
+ if (trustManager != null) {
+ trustManagerList.add(trustManager);
+ }
+
+ trustManagers = new X509TrustManager[] {
+ new X509TrustManager() {
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ @Override
+ public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
+ CertificateException lastException = null;
+ for(final X509TrustManager tm : trustManagerList) {
+ try {
+ tm.checkServerTrusted(chain, authType);
+ return;
+ } catch (final CertificateException e) {
+ lastException = e;
+ }
+ }
+ if (lastException != null) {
+ throw lastException;
+ }
+
+ throw new CertificateException("Certificate not validated");
+ }
+
+ @Override
+ public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
+ // NOP
+ }
+ }
+ };
+ }
+
+ /**
+ * initializes the trust managers validating nothing
+ */
+ private void initInsecureTrustManagers() {
+
+ trustManagers = new X509TrustManager[] {
+ new X509TrustManager() {
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ @Override
+ public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
+ }
+
+ @Override
+ public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
+ }
+ }
+ };
+ }
+
+ /**
+ * finds the X509 trust manager
+ * @param trustManagerFactory TrustManager factory
+ * @return X509 trust manager
+ */
+ private X509TrustManager getTrustManager(final TrustManagerFactory trustManagerFactory) {
+
+ for(final TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
+ if (trustManager instanceof X509TrustManager) {
+ return (X509TrustManager) trustManager;
+ }
+ }
+ return null;
+ }
+}
diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java
index f6307f5..755d75c 100644
--- a/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java
+++ b/vdrmanager/src/de/bjusystems/vdrmanager/utils/svdrp/SvdrpClient.java
@@ -13,9 +13,6 @@ import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-
import android.util.Log;
import de.bjusystems.vdrmanager.app.C;
import de.bjusystems.vdrmanager.data.Preferences;
@@ -28,455 +25,451 @@ import de.bjusystems.vdrmanager.data.Preferences;
*/
public abstract class SvdrpClient<Result> {
- private final String TAG = getClass().getName();
-
- /** Socket for connection to SVDRP */
- private Socket socket;
- /** Output stream for sending commands */
- private OutputStream outputStream;
- /** Input stream for reading answer lines */
- private InputStream inputStream;
- /** flag for stopping the current request */
- private boolean abort;
- /** listener */
- private final List<SvdrpListener> svdrpListeners = new ArrayList<SvdrpListener>();
-
- private final List<SvdrpResultListener<Result>> svdrpResultListeners = new ArrayList<SvdrpResultListener<Result>>();
-
- private final List<SvdrpExceptionListener> svdrpExceptionListeners = new ArrayList<SvdrpExceptionListener>();
-
- private final List<SvdrpFinishedListener<Result>> svdrpFinishedListeners = new ArrayList<SvdrpFinishedListener<Result>>();
-
- /** list of results */
- // private final List<Result> results = new ArrayList<Result>();
- /** should the listener be informed about each received result */
- // private boolean resultInfoEnabled = false;
- /**
- * @return true if the client has result
- */
- // public boolean hasResults(){
- // return results.isEmpty() == false;
- // }
-
- private Timer watchDog = new Timer();
-
- // private NativeDES crypt = new NativeDES();
-
- public boolean isConnected() {
- if (socket == null) {
- return false;
- }
- return socket.isConnected();
- }
-
- /**
- * Parse received answer line
- *
- * @param line
- * line
- * @return received data object or null if not completed yet
- */
- protected abstract Result parseAnswer(String line);
-
- public abstract int getProgressTextId();
-
- public abstract void run();
-
- /**
- * Constructor
- *
- * @param prefs
- * Preferences
- */
- protected SvdrpClient() {
- // results.clear();
- }
-
- /**
- * Remove all listeners
- */
- public void clearListener() {
- svdrpExceptionListeners.clear();
- svdrpListeners.clear();
- svdrpResultListeners.clear();
- }
-
- /**
- * Adds the listener to the list of listeners
- *
- * @param listener
- * listener
- */
- public void addSvdrpListener(final SvdrpListener listener) {
- svdrpListeners.add(listener);
- }
-
- /**
- * Adds the listener to the list of listeners
- *
- * @param listener
- * listener
- */
- public void addSvdrpResultListener(
- final SvdrpResultListener<Result> listener) {
- svdrpResultListeners.add(listener);
- }
-
- /**
- * Adds the listener to the list of listeners
- *
- * @param listener
- * listener
- */
- public void addSvdrpFinishedListener(
- final SvdrpFinishedListener<Result> listener) {
- svdrpFinishedListeners.add(listener);
- }
-
- /**
- * Adds the listener to the list of listeners
- *
- * @param listener
- * listener
- */
- public void addSvdrpExceptionListener(final SvdrpExceptionListener listener) {
- svdrpExceptionListeners.add(listener);
- }
-
- /**
- * Removes the listener from the list of listeners
- *
- * @param listener
- * listener
- */
- public void removeSvdrpListener(final SvdrpListener listener) {
- svdrpListeners.remove(listener);
- }
-
- public void removeSvdrpResultListener(
- final SvdrpResultListener<Result> listener) {
- svdrpResultListeners.remove(listener);
- }
-
- public void removeSvdrpExceptionListener(
- final SvdrpExceptionListener listener) {
- svdrpExceptionListeners.remove(listener);
- }
-
- /**
- * Cancel the current request
- */
- public void abort() {
- abort = true;
- try {
- if (isConnected()) {
- socket.shutdownInput();
- socket.shutdownOutput();
- socket.close();
- }
- } catch (Exception ex) {
- Log.w(TAG, ex);
- }
-
- }
-
- // /**
- // * Gets the list of results
- // *
- // * @return results
- // */
- // public List<Result> getResults() {
- // return results;
- // }
-
- /**
- * Connect to SVDRP
- *
- * @param host
- * host
- * @param port
- * port
- * @param ssl
- * use SSL
- * @throws IOException
- * on errors
- */
- protected boolean connect() throws IOException {
-
- final Preferences prefs = Preferences.get();
- try {
- // connect
- informListener(SvdrpEvent.CONNECTING);
-
- if (false && Preferences.get().isSecure()) {
-
- SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
- .getDefault(); // Erzeugt eine SSLSocketFactory mit
- // Standartkonfiguration
- socket = (SSLSocket) factory.createSocket();
- } else {
- socket = new Socket();
- }
-
- socket.connect(
- new InetSocketAddress(prefs.getSvdrpHost(), prefs
- .getSvdrpPort()),
- prefs.getConnectionTimeout() * 1000);// 8 secs for connect
- if (abort) {
- informListener(SvdrpEvent.ABORTED);
- }
- //
- socket.setSoTimeout(prefs.getReadTimeout() * 1000);// 15 sec for
- // each read
- final long delay = C.ONE_MINUTE_IN_MILLIS * prefs.getTimeout() * 60; // in
- // 3
- // minutes
- // we
- // abort
- // the
- // communication
- watchDog.schedule(new TimerTask() {
- @Override
- public void run() {
- Log.w(TAG, "Aborted after " + delay + " ms");
- abort = true;
- }
- }, delay);
- informListener(SvdrpEvent.CONNECTED);
- } catch (final SocketTimeoutException sote) {
- Log.w(TAG, sote);
- if (abort) {
- informListener(SvdrpEvent.ABORTED);
- } else {
- informListener(SvdrpEvent.CONNECTION_TIMEOUT);
- }
- return false;
- } catch (final Exception e) {
-
- Log.w(TAG, e);
- if (abort) {
- informListener(SvdrpEvent.ABORTED);
- } else {
- informListener(SvdrpEvent.CONNECT_ERROR);
- }
- return false;
- }
-
- // create streams
- outputStream = socket.getOutputStream();
- inputStream = socket.getInputStream();
- // TODO http://projects.vdr-developer.org/issues/790
- // inputStream = new InflaterInputStream(socket.getInputStream())
-
- // password needed?
- informListener(SvdrpEvent.LOGIN);
- writeLine("passwd " + prefs.getPassword());
- if (!readLine().startsWith("!OK")) {
- informListener(SvdrpEvent.LOGIN_ERROR);
- disconnect();
- return false;
- } else {
- informListener(SvdrpEvent.LOGGED_IN);
- }
- return true;
- }
-
- /**
- * Disconnect from SVDRP if connected
- *
- * @throws IOException
- * on errors
- */
- protected void disconnect() throws IOException {
- informListener(SvdrpEvent.DISCONNECTING);
- if (socket != null && socket.isConnected()) {
- socket.close();
- socket = null;
- }
- informListener(SvdrpEvent.DISCONNECTED);
- }
-
- /**
- * Sends one line to SVDRP
- *
- * @param line
- * line of text
- * @throws IOException
- * on errors
- */
- protected void writeLine(final String line) throws IOException {
-
- String command = line + "\r\n";
- // if (false && Preferences.get().isSecure()) {
- // command = crypt.encrypt(command, Preferences.get().getPassword());
- // }
- final byte[] bytes = command.getBytes("utf-8");
- outputStream.write(bytes);
- outputStream.flush();
- }
-
- /**
- * Reads one line from SVDRP
- *
- * @return line read
- * @throws IOException
- * on errors
- */
- protected String readLine() throws IOException {
-
- // handle not gzipped input
- final ByteArrayOutputStream lineBytes = new ByteArrayOutputStream();
-
- for (;;) {
-
- // read next char
- final int d = inputStream.read();
- if (d < 0) {
- break;
- }
- final char c = (char) d;
-
- // skip '\r'
- if (c == '\r') {
- continue;
- }
-
- // with '\n' the line is completed
- if (c == '\n') {
- break;
- }
-
- // remember char
- lineBytes.write(c);
- }
-
- String line = null;
- try {
- line = lineBytes.toString(Preferences.get().getEncoding());
- } catch (UnsupportedEncodingException usex) {
- Log.w(TAG, usex);
- line = lineBytes.toString();
- }
- // if (false && Preferences.get().isSecure()) {
- // line = crypt.decrypt(line, Preferences.get().getPassword());
- // }
- return line;
- }
-
- public void runCommand(final String command) {
-
- try {
-
- // reset cancel flag
- abort = false;
-
- // clear results
- // results.clear();
-
- // connect
- final boolean connected = connect();
- if (!connected) {
- return;
- }
-
- // send command
- informListener(SvdrpEvent.COMMAND_SENDING);
- writeLine(command);
- informListener(SvdrpEvent.COMMAND_SENT);
- Log.i(TAG, SvdrpEvent.COMMAND_SENT + ":" + command);
-
- // read first line
- String line = readLine();
- if (!line.startsWith("START")) {
- Log.w(TAG, line);
- throw new IOException("Answer not wellformed: " + line);
- }
-
- // read answer lines
- for (; !abort;) {
-
- // get next line
- line = readLine();
- if (line.length() == 0) {
- break;
- }
-
- // last line?
- if (line.startsWith("END")) {
- break;
- }
-
- // error?
- if (line.startsWith("!ERROR")) {
- Log.w(TAG, line);
- String msg;
- if (line.startsWith("!ERROR:")) {
- msg = line.substring(7);
- } else {
- msg = line;
- }
- disconnect();
- informListener(SvdrpEvent.ERROR, new SvdrpException(msg));
- break;
- }
-
- // delegate analysis
- Result result = null;
- try {
- result = parseAnswer(line);
-
- } catch (Exception ex) {
- Log.w(TAG, ex);
- disconnect();
- Log.w(TAG, "line: " + line);
- informListener(SvdrpEvent.ERROR, ex);
- return;
- }
- if (result != null) {
- informListener(result);
- // results.add(result);
- // if (resultInfoEnabled) {
-
- // }
- }
-
- }
-
- // disconnect
- disconnect();
-
- if (abort) {
- informListener(SvdrpEvent.ABORTED);
- } else {
- informListener(SvdrpEvent.FINISHED_SUCCESS);
- }
-
- } catch (final Exception e) {
- Log.w(TAG, e);
- informListener(SvdrpEvent.FINISHED_ABNORMALY, e);
- }
- }
-
- // public void setResultInfoEnabled(final boolean resultInfoEnabled) {
- // this.resultInfoEnabled = resultInfoEnabled;
- // }
-
- protected void informListener(final SvdrpEvent event, final Throwable e) {
- for (final SvdrpExceptionListener listener : svdrpExceptionListeners) {
- listener.svdrpEvent(event, e);
- }
- }
-
- protected void informListener(final SvdrpEvent event) {
- for (final SvdrpListener listener : svdrpListeners) {
- listener.svdrpEvent(event);
- }
- }
-
- protected void informListener(final Result result) {
- for (final SvdrpResultListener<Result> listener : svdrpResultListeners) {
- listener.svdrpEvent(result);
- }
- }
+ private final String TAG = getClass().getName();
+
+ /** Socket for connection to SVDRP */
+ private Socket socket;
+ /** Output stream for sending commands */
+ private OutputStream outputStream;
+ /** Input stream for reading answer lines */
+ private InputStream inputStream;
+ /** flag for stopping the current request */
+ private boolean abort;
+ /** listener */
+ private final List<SvdrpListener> svdrpListeners = new ArrayList<SvdrpListener>();
+
+ private final List<SvdrpResultListener<Result>> svdrpResultListeners = new ArrayList<SvdrpResultListener<Result>>();
+
+ private final List<SvdrpExceptionListener> svdrpExceptionListeners = new ArrayList<SvdrpExceptionListener>();
+
+ private final List<SvdrpFinishedListener<Result>> svdrpFinishedListeners = new ArrayList<SvdrpFinishedListener<Result>>();
+
+ /** list of results */
+ // private final List<Result> results = new ArrayList<Result>();
+ /** should the listener be informed about each received result */
+ // private boolean resultInfoEnabled = false;
+ /**
+ * @return true if the client has result
+ */
+ // public boolean hasResults(){
+ // return results.isEmpty() == false;
+ // }
+
+ private final Timer watchDog = new Timer();
+
+ // private NativeDES crypt = new NativeDES();
+
+ public boolean isConnected() {
+ if (socket == null) {
+ return false;
+ }
+ return socket.isConnected();
+ }
+
+ /**
+ * Parse received answer line
+ *
+ * @param line
+ * line
+ * @return received data object or null if not completed yet
+ */
+ protected abstract Result parseAnswer(String line);
+
+ public abstract int getProgressTextId();
+
+ public abstract void run();
+
+ /**
+ * Constructor
+ *
+ * @param prefs
+ * Preferences
+ */
+ protected SvdrpClient() {
+ // results.clear();
+ }
+
+ /**
+ * Remove all listeners
+ */
+ public void clearListener() {
+ svdrpExceptionListeners.clear();
+ svdrpListeners.clear();
+ svdrpResultListeners.clear();
+ }
+
+ /**
+ * Adds the listener to the list of listeners
+ *
+ * @param listener
+ * listener
+ */
+ public void addSvdrpListener(final SvdrpListener listener) {
+ svdrpListeners.add(listener);
+ }
+
+ /**
+ * Adds the listener to the list of listeners
+ *
+ * @param listener
+ * listener
+ */
+ public void addSvdrpResultListener(
+ final SvdrpResultListener<Result> listener) {
+ svdrpResultListeners.add(listener);
+ }
+
+ /**
+ * Adds the listener to the list of listeners
+ *
+ * @param listener
+ * listener
+ */
+ public void addSvdrpFinishedListener(
+ final SvdrpFinishedListener<Result> listener) {
+ svdrpFinishedListeners.add(listener);
+ }
+
+ /**
+ * Adds the listener to the list of listeners
+ *
+ * @param listener
+ * listener
+ */
+ public void addSvdrpExceptionListener(final SvdrpExceptionListener listener) {
+ svdrpExceptionListeners.add(listener);
+ }
+
+ /**
+ * Removes the listener from the list of listeners
+ *
+ * @param listener
+ * listener
+ */
+ public void removeSvdrpListener(final SvdrpListener listener) {
+ svdrpListeners.remove(listener);
+ }
+
+ public void removeSvdrpResultListener(
+ final SvdrpResultListener<Result> listener) {
+ svdrpResultListeners.remove(listener);
+ }
+
+ public void removeSvdrpExceptionListener(
+ final SvdrpExceptionListener listener) {
+ svdrpExceptionListeners.remove(listener);
+ }
+
+ /**
+ * Cancel the current request
+ */
+ public void abort() {
+ abort = true;
+ try {
+ if (isConnected()) {
+ socket.shutdownInput();
+ socket.shutdownOutput();
+ socket.close();
+ }
+ } catch (final Exception ex) {
+ Log.w(TAG, ex);
+ }
+
+ }
+
+ // /**
+ // * Gets the list of results
+ // *
+ // * @return results
+ // */
+ // public List<Result> getResults() {
+ // return results;
+ // }
+
+ /**
+ * Connect to SVDRP
+ *
+ * @param host
+ * host
+ * @param port
+ * port
+ * @param ssl
+ * use SSL
+ * @throws IOException
+ * on errors
+ */
+ protected boolean connect() throws IOException {
+
+ final Preferences prefs = Preferences.get();
+ try {
+ // connect
+ informListener(SvdrpEvent.CONNECTING);
+
+ if (true || Preferences.get().isSecure()) {
+ socket = new MySSLSocketFactory(true).createSocket();
+ } else {
+ socket = new Socket();
+ }
+
+ socket.connect(
+ new InetSocketAddress(prefs.getSvdrpHost(), prefs
+ .getSvdrpPort()),
+ prefs.getConnectionTimeout() * 1000);// 8 secs for connect
+ if (abort) {
+ informListener(SvdrpEvent.ABORTED);
+ }
+ //
+ socket.setSoTimeout(prefs.getReadTimeout() * 1000);// 15 sec for
+ // each read
+ final long delay = C.ONE_MINUTE_IN_MILLIS * prefs.getTimeout() * 60; // in
+ // 3
+ // minutes
+ // we
+ // abort
+ // the
+ // communication
+ watchDog.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ Log.w(TAG, "Aborted after " + delay + " ms");
+ abort = true;
+ }
+ }, delay);
+ informListener(SvdrpEvent.CONNECTED);
+ } catch (final SocketTimeoutException sote) {
+ Log.w(TAG, sote);
+ if (abort) {
+ informListener(SvdrpEvent.ABORTED);
+ } else {
+ informListener(SvdrpEvent.CONNECTION_TIMEOUT);
+ }
+ return false;
+ } catch (final Exception e) {
+
+ Log.w(TAG, e);
+ if (abort) {
+ informListener(SvdrpEvent.ABORTED);
+ } else {
+ informListener(SvdrpEvent.CONNECT_ERROR);
+ }
+ return false;
+ }
+
+ // create streams
+ outputStream = socket.getOutputStream();
+ inputStream = socket.getInputStream();
+ // TODO http://projects.vdr-developer.org/issues/790
+ // inputStream = new InflaterInputStream(socket.getInputStream())
+
+ // password needed?
+ informListener(SvdrpEvent.LOGIN);
+ writeLine("passwd " + prefs.getPassword());
+ if (!readLine().startsWith("!OK")) {
+ informListener(SvdrpEvent.LOGIN_ERROR);
+ disconnect();
+ return false;
+ } else {
+ informListener(SvdrpEvent.LOGGED_IN);
+ }
+ return true;
+ }
+
+ /**
+ * Disconnect from SVDRP if connected
+ *
+ * @throws IOException
+ * on errors
+ */
+ protected void disconnect() throws IOException {
+ informListener(SvdrpEvent.DISCONNECTING);
+ if (socket != null && socket.isConnected()) {
+ socket.close();
+ socket = null;
+ }
+ informListener(SvdrpEvent.DISCONNECTED);
+ }
+
+ /**
+ * Sends one line to SVDRP
+ *
+ * @param line
+ * line of text
+ * @throws IOException
+ * on errors
+ */
+ protected void writeLine(final String line) throws IOException {
+
+ final String command = line + "\r\n";
+ // if (false && Preferences.get().isSecure()) {
+ // command = crypt.encrypt(command, Preferences.get().getPassword());
+ // }
+ final byte[] bytes = command.getBytes("utf-8");
+ outputStream.write(bytes);
+ outputStream.flush();
+ }
+
+ /**
+ * Reads one line from SVDRP
+ *
+ * @return line read
+ * @throws IOException
+ * on errors
+ */
+ protected String readLine() throws IOException {
+
+ // handle not gzipped input
+ final ByteArrayOutputStream lineBytes = new ByteArrayOutputStream();
+
+ for (;;) {
+
+ // read next char
+ final int d = inputStream.read();
+ if (d < 0) {
+ break;
+ }
+ final char c = (char) d;
+
+ // skip '\r'
+ if (c == '\r') {
+ continue;
+ }
+
+ // with '\n' the line is completed
+ if (c == '\n') {
+ break;
+ }
+
+ // remember char
+ lineBytes.write(c);
+ }
+
+ String line = null;
+ try {
+ line = lineBytes.toString(Preferences.get().getEncoding());
+ } catch (final UnsupportedEncodingException usex) {
+ Log.w(TAG, usex);
+ line = lineBytes.toString();
+ }
+ // if (false && Preferences.get().isSecure()) {
+ // line = crypt.decrypt(line, Preferences.get().getPassword());
+ // }
+ return line;
+ }
+
+ public void runCommand(final String command) {
+
+ try {
+
+ // reset cancel flag
+ abort = false;
+
+ // clear results
+ // results.clear();
+
+ // connect
+ final boolean connected = connect();
+ if (!connected) {
+ return;
+ }
+
+ // send command
+ informListener(SvdrpEvent.COMMAND_SENDING);
+ writeLine(command);
+ informListener(SvdrpEvent.COMMAND_SENT);
+ Log.i(TAG, SvdrpEvent.COMMAND_SENT + ":" + command);
+
+ // read first line
+ String line = readLine();
+ if (!line.startsWith("START")) {
+ Log.w(TAG, line);
+ throw new IOException("Answer not wellformed: " + line);
+ }
+
+ // read answer lines
+ for (; !abort;) {
+
+ // get next line
+ line = readLine();
+ if (line.length() == 0) {
+ break;
+ }
+
+ // last line?
+ if (line.startsWith("END")) {
+ break;
+ }
+
+ // error?
+ if (line.startsWith("!ERROR")) {
+ Log.w(TAG, line);
+ String msg;
+ if (line.startsWith("!ERROR:")) {
+ msg = line.substring(7);
+ } else {
+ msg = line;
+ }
+ disconnect();
+ informListener(SvdrpEvent.ERROR, new SvdrpException(msg));
+ break;
+ }
+
+ // delegate analysis
+ Result result = null;
+ try {
+ result = parseAnswer(line);
+
+ } catch (final Exception ex) {
+ Log.w(TAG, ex);
+ disconnect();
+ Log.w(TAG, "line: " + line);
+ informListener(SvdrpEvent.ERROR, ex);
+ return;
+ }
+ if (result != null) {
+ informListener(result);
+ // results.add(result);
+ // if (resultInfoEnabled) {
+
+ // }
+ }
+
+ }
+
+ // disconnect
+ disconnect();
+
+ if (abort) {
+ informListener(SvdrpEvent.ABORTED);
+ } else {
+ informListener(SvdrpEvent.FINISHED_SUCCESS);
+ }
+
+ } catch (final Exception e) {
+ Log.w(TAG, e);
+ informListener(SvdrpEvent.FINISHED_ABNORMALY, e);
+ }
+ }
+
+ // public void setResultInfoEnabled(final boolean resultInfoEnabled) {
+ // this.resultInfoEnabled = resultInfoEnabled;
+ // }
+
+ protected void informListener(final SvdrpEvent event, final Throwable e) {
+ for (final SvdrpExceptionListener listener : svdrpExceptionListeners) {
+ listener.svdrpEvent(event, e);
+ }
+ }
+
+ protected void informListener(final SvdrpEvent event) {
+ for (final SvdrpListener listener : svdrpListeners) {
+ listener.svdrpEvent(event);
+ }
+ }
+
+ protected void informListener(final Result result) {
+ for (final SvdrpResultListener<Result> listener : svdrpResultListeners) {
+ listener.svdrpEvent(result);
+ }
+ }
}