Merge branch 'develop' into refactor_remote_operation_to_create_folder
authorDavid A. Velasco <dvelasco@solidgear.es>
Tue, 12 Nov 2013 14:22:36 +0000 (15:22 +0100)
committerDavid A. Velasco <dvelasco@solidgear.es>
Tue, 12 Nov 2013 14:22:36 +0000 (15:22 +0100)
33 files changed:
1  2 
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java
oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java
oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java
project.properties
src/com/owncloud/android/authentication/AccountAuthenticator.java
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/files/OwnCloudFileObserver.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
src/com/owncloud/android/operations/RenameFileOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/UpdateOCVersionOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
src/com/owncloud/android/syncadapter/ContactSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/ui/activity/AccountSelectActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/FileDownloadFragment.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java
src/com/owncloud/android/ui/preview/PreviewVideoActivity.java
src/com/owncloud/android/utils/FileStorageUtils.java
tests/.classpath

index badb243,0000000..e24fa36
mode 100644,000000..100644
--- /dev/null
@@@ -1,241 -1,0 +1,242 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012 Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.oc_framework.network;
 +
 +import java.io.IOException;
 +import java.net.InetAddress;
 +import java.net.InetSocketAddress;
 +import java.net.Socket;
 +import java.net.SocketAddress;
 +import java.net.UnknownHostException;
 +import java.security.cert.X509Certificate;
 +
 +import javax.net.SocketFactory;
 +import javax.net.ssl.SSLContext;
 +import javax.net.ssl.SSLException;
 +import javax.net.ssl.SSLHandshakeException;
 +import javax.net.ssl.SSLPeerUnverifiedException;
 +import javax.net.ssl.SSLSession;
 +import javax.net.ssl.SSLSocket;
 +
 +import org.apache.commons.httpclient.ConnectTimeoutException;
 +import org.apache.commons.httpclient.params.HttpConnectionParams;
 +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
 +import org.apache.http.conn.ssl.X509HostnameVerifier;
 +
 +import android.util.Log;
 +
 +
++
 +/**
 + * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with 
 + * a custom SSLContext and an optional Hostname Verifier.
 + * 
 + * @author David A. Velasco
 + */
 +
 +public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
 +
 +    private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
 +    
 +    private SSLContext mSslContext = null;
 +    private AdvancedX509TrustManager mTrustManager = null;
 +    private X509HostnameVerifier mHostnameVerifier = null;
 +
 +    public SSLContext getSslContext() {
 +        return mSslContext;
 +    }
 +    
 +    /**
 +     * Constructor for AdvancedSSLProtocolSocketFactory.
 +     */
 +    public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) {
 +        if (sslContext == null)
 +            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
 +        if (trustManager == null)
 +            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null Trust Manager");
 +        mSslContext = sslContext;
 +        mTrustManager = trustManager;
 +        mHostnameVerifier = hostnameVerifier;
 +    }
 +
 +    /**
 +     * @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
 +     */
 +    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
 +        Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
 +        verifyPeerIdentity(host, port, socket);
 +        return socket;
 +    }
 +
 +    
 +    /**
 +     * Attempts to get a new socket connection to the given host within the
 +     * given time limit.
 +     * 
 +     * @param host the host name/IP
 +     * @param port the port on the host
 +     * @param clientHost the local host name/IP to bind the socket to
 +     * @param clientPort the port on the local machine
 +     * @param params {@link HttpConnectionParams Http connection parameters}
 +     * 
 +     * @return Socket a new socket
 +     * 
 +     * @throws IOException if an I/O error occurs while creating the socket
 +     * @throws UnknownHostException if the IP address of the host cannot be
 +     *             determined
 +     */
 +    public Socket createSocket(final String host, final int port,
 +            final InetAddress localAddress, final int localPort,
 +            final HttpConnectionParams params) throws IOException,
 +            UnknownHostException, ConnectTimeoutException {
 +        Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
 +        if (params == null) {
 +            throw new IllegalArgumentException("Parameters may not be null");
 +        } 
 +        int timeout = params.getConnectionTimeout();
 +        SocketFactory socketfactory = mSslContext.getSocketFactory();
 +        Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
 +        Socket socket = socketfactory.createSocket();
 +        SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
 +        SocketAddress remoteaddr = new InetSocketAddress(host, port);
 +        socket.setSoTimeout(params.getSoTimeout());
 +        socket.bind(localaddr);
 +        socket.connect(remoteaddr, timeout);
 +        verifyPeerIdentity(host, port, socket);
 +        return socket;
 +    }
 +
 +    /**
 +     * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
 +     */
 +    public Socket createSocket(String host, int port) throws IOException,
 +            UnknownHostException {
 +      Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
 +        Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
 +        verifyPeerIdentity(host, port, socket);
 +        return socket; 
 +    }
 +
 +    public boolean equals(Object obj) {
 +        return ((obj != null) && obj.getClass().equals(
 +                AdvancedSslSocketFactory.class));
 +    }
 +
 +    public int hashCode() {
 +        return AdvancedSslSocketFactory.class.hashCode();
 +    }
 +
 +
 +    public X509HostnameVerifier getHostNameVerifier() {
 +        return mHostnameVerifier;
 +    }
 +    
 +    
 +    public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
 +        mHostnameVerifier = hostnameVerifier;
 +    }
 +    
 +    /**
 +     * Verifies the identity of the server. 
 +     * 
 +     * The server certificate is verified first.
 +     * 
 +     * Then, the host name is compared with the content of the server certificate using the current host name verifier, if any.
 +     * @param socket
 +     */
 +    private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
 +        try {
 +            CertificateCombinedException failInHandshake = null;
 +            /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an instance of AdvancedX509TrustManager) 
 +            try {
 +                SSLSocket sock = (SSLSocket) socket;    // a new SSLSession instance is created as a "side effect" 
 +                sock.startHandshake();
 +                
 +            } catch (RuntimeException e) {
 +                
 +                if (e instanceof CertificateCombinedException) {
 +                    failInHandshake = (CertificateCombinedException) e;
 +                } else {
 +                    Throwable cause = e.getCause();
 +                    Throwable previousCause = null;
 +                    while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
 +                        previousCause = cause;
 +                        cause = cause.getCause();
 +                    }
 +                    if (cause != null && cause instanceof CertificateCombinedException) {
 +                        failInHandshake = (CertificateCombinedException)cause;
 +                    }
 +                }
 +                if (failInHandshake == null) {
 +                    throw e;
 +                }
 +                failInHandshake.setHostInUrl(host);
 +                
 +            }
 +            
 +            /// 2. VERIFY HOSTNAME
 +            SSLSession newSession = null;
 +            boolean verifiedHostname = true;
 +            if (mHostnameVerifier != null) {
 +                if (failInHandshake != null) {
 +                    /// 2.1 : a new SSLSession instance was NOT created in the handshake
 +                    X509Certificate serverCert = failInHandshake.getServerCertificate();
 +                    try {
 +                        mHostnameVerifier.verify(host, serverCert);
 +                    } catch (SSLException e) {
 +                        verifiedHostname = false;
 +                    }
 +                
 +                } else {
 +                    /// 2.2 : a new SSLSession instance was created in the handshake
 +                    newSession = ((SSLSocket)socket).getSession();
 +                    if (!mTrustManager.isKnownServer((X509Certificate)(newSession.getPeerCertificates()[0]))) {
 +                        verifiedHostname = mHostnameVerifier.verify(host, newSession); 
 +                    }
 +                }
 +            }
 +
 +            /// 3. Combine the exceptions to throw, if any
 +            if (!verifiedHostname) {
 +                SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException("Names in the server certificate do not match to " + host + " in the URL");
 +                if (failInHandshake == null) {
 +                    failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]);
 +                    failInHandshake.setHostInUrl(host);
 +                }
 +                failInHandshake.setSslPeerUnverifiedException(pue);
 +                pue.initCause(failInHandshake);
 +                throw pue;
 +                
 +            } else if (failInHandshake != null) {
 +                SSLHandshakeException hse = new SSLHandshakeException("Server certificate could not be verified");
 +                hse.initCause(failInHandshake);
 +                throw hse;
 +            }
 +            
 +        } catch (IOException io) {        
 +            try {
 +                socket.close();
 +            } catch (Exception x) {
 +                // NOTHING - irrelevant exception for the caller 
 +            }
 +            throw io;
 +        }
 +    }
 +
 +}
index 7d78f78,0000000..4bad3ef
mode 100644,000000..100644
--- /dev/null
@@@ -1,147 -1,0 +1,148 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.oc_framework.network;
 +
 +import java.security.KeyStore;
 +import java.security.KeyStoreException;
 +import java.security.NoSuchAlgorithmException;
 +import java.security.cert.CertPathValidatorException;
 +import java.security.cert.CertStoreException;
 +import java.security.cert.CertificateException;
 +import java.security.cert.CertificateExpiredException;
 +import java.security.cert.CertificateNotYetValidException;
 +import java.security.cert.X509Certificate;
 +
 +import javax.net.ssl.TrustManager;
 +import javax.net.ssl.TrustManagerFactory;
 +import javax.net.ssl.X509TrustManager;
 +
 +import android.util.Log;
 +
 +
++
 +/**
 + * @author David A. Velasco
 + */
 +public class AdvancedX509TrustManager implements X509TrustManager {
 +    
 +    private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
 +
 +    private X509TrustManager mStandardTrustManager = null;
 +    private KeyStore mKnownServersKeyStore;
 +
 +    /**
 +     * Constructor for AdvancedX509TrustManager
 +     * 
 +     * @param  knownServersCertStore    Local certificates store with server certificates explicitly trusted by the user.
 +     * @throws CertStoreException       When no default X509TrustManager instance was found in the system.
 +     */
 +    public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
 +            throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
 +        super();
 +        TrustManagerFactory factory = TrustManagerFactory
 +                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
 +        factory.init((KeyStore)null);
 +        mStandardTrustManager = findX509TrustManager(factory);
 +
 +        mKnownServersKeyStore = knownServersKeyStore;
 +    }
 +    
 +    
 +    /**
 +     * Locates the first X509TrustManager provided by a given TrustManagerFactory
 +     * @param factory               TrustManagerFactory to inspect in the search for a X509TrustManager
 +     * @return                      The first X509TrustManager found in factory.
 +     * @throws CertStoreException   When no X509TrustManager instance was found in factory
 +     */
 +    private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
 +        TrustManager tms[] = factory.getTrustManagers();
 +        for (int i = 0; i < tms.length; i++) {
 +            if (tms[i] instanceof X509TrustManager) {
 +                return (X509TrustManager) tms[i];
 +            }
 +        }
 +        return null;
 +    }
 +    
 +
 +    /**
 +     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
 +     *      String authType)
 +     */
 +    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
 +        mStandardTrustManager.checkClientTrusted(certificates, authType);
 +    }
 +
 +    
 +    /**
 +     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
 +     *      String authType)
 +     */
 +    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
 +        if (!isKnownServer(certificates[0])) {
 +              CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
 +              try {
 +                      certificates[0].checkValidity();
 +              } catch (CertificateExpiredException c) {
 +                      result.setCertificateExpiredException(c);
 +                      
 +              } catch (CertificateNotYetValidException c) {
 +                result.setCertificateNotYetException(c);
 +              }
 +              
 +              try {
 +                  mStandardTrustManager.checkServerTrusted(certificates, authType);
 +              } catch (CertificateException c) {
 +                Throwable cause = c.getCause();
 +                Throwable previousCause = null;
 +                while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) {     // getCause() is not funny
 +                    previousCause = cause;
 +                    cause = cause.getCause();
 +                }
 +                if (cause != null && cause instanceof CertPathValidatorException) {
 +                      result.setCertPathValidatorException((CertPathValidatorException)cause);
 +                } else {
 +                      result.setOtherCertificateException(c);
 +                }
 +              }
 +              
 +              if (result.isException())
 +                      throw result;
 +
 +        }
 +    }
 +    
 +    
 +    /**
 +     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
 +     */
 +    public X509Certificate[] getAcceptedIssuers() {
 +        return mStandardTrustManager.getAcceptedIssuers();
 +    }
 +
 +    
 +    public boolean isKnownServer(X509Certificate cert) {
 +        try {
 +            return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
 +        } catch (KeyStoreException e) {
 +            Log.d(TAG, "Fail while checking certificate in the known-servers store");
 +            return false;
 +        }
 +    }
 +    
 +}
index 20e7366,0000000..37698d6
mode 100644,000000..100644
--- /dev/null
@@@ -1,271 -1,0 +1,272 @@@
 +package com.owncloud.android.oc_framework.network;
 +/* ownCloud Android client application
 + *   Copyright (C) 2012  ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +
 +
 +import java.util.Map;
 +
 +import org.apache.commons.httpclient.Credentials;
 +import org.apache.commons.httpclient.HttpMethod;
 +import org.apache.commons.httpclient.auth.AuthChallengeParser;
 +import org.apache.commons.httpclient.auth.AuthScheme;
 +import org.apache.commons.httpclient.auth.AuthenticationException;
 +import org.apache.commons.httpclient.auth.InvalidCredentialsException;
 +import org.apache.commons.httpclient.auth.MalformedChallengeException;
 +
 +import android.util.Log;
 +
 +
++
 +/**
 + * Bearer authentication scheme as defined in RFC 6750.
 + * 
 + * @author David A. Velasco
 + */
 +
 +public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
 +    
 +    private static final String TAG = BearerAuthScheme.class.getSimpleName();
 +
 +    public static final String AUTH_POLICY = "Bearer";
 +    
 +    /** Whether the bearer authentication process is complete */
 +    private boolean mComplete;
 +    
 +    /** Authentication parameter map */
 +    @SuppressWarnings("rawtypes")
 +      private Map mParams = null;
 +    
 +    
 +    /**
 +     * Default constructor for the bearer authentication scheme.
 +     */
 +    public BearerAuthScheme() {
 +        mComplete = false;
 +    }
 +
 +    /**
 +     * Constructor for the basic authentication scheme.
 +     * 
 +     * @param   challenge                       Authentication challenge
 +     * 
 +     * @throws  MalformedChallengeException     Thrown if the authentication challenge is malformed
 +     * 
 +     * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} method
 +     */
 +    public BearerAuthScheme(final String challenge) throws MalformedChallengeException {
 +        processChallenge(challenge);
 +        mComplete = true;
 +    }
 +
 +    /**
 +     * Returns textual designation of the bearer authentication scheme.
 +     * 
 +     * @return "Bearer"
 +     */
 +    public String getSchemeName() {
 +        return "bearer";
 +    }
 +
 +    /**
 +     * Processes the Bearer challenge.
 +     *  
 +     * @param   challenge                   The challenge string
 +     * 
 +     * @throws MalformedChallengeException  Thrown if the authentication challenge is malformed
 +     */
 +    public void processChallenge(String challenge) throws MalformedChallengeException {
 +        String s = AuthChallengeParser.extractScheme(challenge);
 +        if (!s.equalsIgnoreCase(getSchemeName())) {
 +            throw new MalformedChallengeException(
 +              "Invalid " + getSchemeName() + " challenge: " + challenge); 
 +        }
 +        mParams = AuthChallengeParser.extractParams(challenge);
 +        mComplete = true;
 +    }
 +
 +    /**
 +     * Tests if the Bearer authentication process has been completed.
 +     * 
 +     * @return 'true' if Bearer authorization has been processed, 'false' otherwise.
 +     */
 +    public boolean isComplete() {
 +        return this.mComplete;
 +    }
 +
 +    /**
 +     * Produces bearer authorization string for the given set of 
 +     * {@link Credentials}.
 +     * 
 +     * @param   credentials                     The set of credentials to be used for authentication
 +     * @param   method                          Method name is ignored by the bearer authentication scheme
 +     * @param   uri                             URI is ignored by the bearer authentication scheme
 +     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable 
 +     *                                          for this authentication scheme
 +     * @throws  AuthenticationException         If authorization string cannot be generated due to an authentication failure
 +     * @return  A bearer authorization string
 +     * 
 +     * @deprecated Use {@link #authenticate(Credentials, HttpMethod)}
 +     */
 +    public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
 +        Log.d(TAG, "enter BearerScheme.authenticate(Credentials, String, String)");
 +
 +        BearerCredentials bearer = null;
 +        try {
 +            bearer = (BearerCredentials) credentials;
 +        } catch (ClassCastException e) {
 +            throw new InvalidCredentialsException(
 +             "Credentials cannot be used for bearer authentication: " 
 +              + credentials.getClass().getName());
 +        }
 +        return BearerAuthScheme.authenticate(bearer);
 +    }
 +
 +    
 +    /**
 +     * Returns 'false'. Bearer authentication scheme is request based.
 +     * 
 +     * @return 'false'.
 +     */
 +    public boolean isConnectionBased() {
 +        return false;    
 +    }
 +
 +    /**
 +     * Produces bearer authorization string for the given set of {@link Credentials}.
 +     * 
 +     * @param   credentials                     The set of credentials to be used for authentication
 +     * @param   method                          The method being authenticated
 +     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable for this authentication 
 +     *                                          scheme.
 +     * @throws AuthenticationException         If authorization string cannot be generated due to an authentication failure.
 +     * 
 +     * @return a basic authorization string
 +     */
 +    public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
 +        Log.d(TAG, "enter BearerScheme.authenticate(Credentials, HttpMethod)");
 +
 +        if (method == null) {
 +            throw new IllegalArgumentException("Method may not be null");
 +        }
 +        BearerCredentials bearer = null;
 +        try {
 +            bearer = (BearerCredentials) credentials;
 +        } catch (ClassCastException e) {
 +            throw new InvalidCredentialsException(
 +                    "Credentials cannot be used for bearer authentication: " 
 +                    + credentials.getClass().getName());
 +        }
 +        return BearerAuthScheme.authenticate(
 +            bearer, 
 +            method.getParams().getCredentialCharset());
 +    }
 +    
 +    /**
 +     * @deprecated Use {@link #authenticate(BearerCredentials, String)}
 +     * 
 +     * Returns a bearer Authorization header value for the given 
 +     * {@link BearerCredentials}.
 +     * 
 +     * @param   credentials     The credentials to encode.
 +     * 
 +     * @return                  A bearer authorization string
 +     */
 +    public static String authenticate(BearerCredentials credentials) {
 +        return authenticate(credentials, "ISO-8859-1");
 +    }
 +
 +    /**
 +     * Returns a bearer Authorization header value for the given 
 +     * {@link BearerCredentials} and charset.
 +     * 
 +     * @param   credentials         The credentials to encode.
 +     * @param   charset             The charset to use for encoding the credentials
 +     * 
 +     * @return                      A bearer authorization string
 +     * 
 +     * @since 3.0
 +     */
 +    public static String authenticate(BearerCredentials credentials, String charset) {
 +        Log.d(TAG, "enter BearerAuthScheme.authenticate(BearerCredentials, String)");
 +
 +        if (credentials == null) {
 +            throw new IllegalArgumentException("Credentials may not be null"); 
 +        }
 +        if (charset == null || charset.length() == 0) {
 +            throw new IllegalArgumentException("charset may not be null or empty");
 +        }
 +        StringBuffer buffer = new StringBuffer();
 +        buffer.append(credentials.getAccessToken());
 +        
 +        //return "Bearer " + EncodingUtil.getAsciiString(EncodingUtil.getBytes(buffer.toString(), charset));
 +        return "Bearer " + buffer.toString();
 +    }
 +
 +    /**
 +     * Returns a String identifying the authentication challenge.  This is
 +     * used, in combination with the host and port to determine if
 +     * authorization has already been attempted or not.  Schemes which
 +     * require multiple requests to complete the authentication should
 +     * return a different value for each stage in the request.
 +     * 
 +     * Additionally, the ID should take into account any changes to the
 +     * authentication challenge and return a different value when appropriate.
 +     * For example when the realm changes in basic authentication it should be
 +     * considered a different authentication attempt and a different value should
 +     * be returned.
 +     * 
 +     * This method simply returns the realm for the challenge.
 +     * 
 +     * @return String       a String identifying the authentication challenge.
 +     * 
 +     * @deprecated no longer used
 +     */
 +    @Override
 +    public String getID() {
 +        return getRealm();
 +    }
 +
 +    /**
 +     * Returns authentication parameter with the given name, if available.
 +     * 
 +     * @param   name    The name of the parameter to be returned
 +     * 
 +     * @return          The parameter with the given name
 +     */
 +    @Override
 +    public String getParameter(String name) {
 +        if (name == null) {
 +            throw new IllegalArgumentException("Parameter name may not be null"); 
 +        }
 +        if (mParams == null) {
 +            return null;
 +        }
 +        return (String) mParams.get(name.toLowerCase());
 +    }
 +
 +    /**
 +     * Returns authentication realm. The realm may not be null.
 +     * 
 +     * @return  The authentication realm
 +     */
 +    @Override
 +    public String getRealm() {
 +        return getParameter("realm");
 +    }
 +    
 +}
index 4587737,0000000..6a4200d
mode 100644,000000..100644
--- /dev/null
@@@ -1,146 -1,0 +1,145 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.oc_framework.network.webdav;
 +
 +import java.io.File;
 +import java.io.IOException;
 +import java.io.OutputStream;
 +import java.nio.ByteBuffer;
 +import java.nio.channels.FileChannel;
 +import java.util.Collection;
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.Set;
 +
 +import org.apache.commons.httpclient.methods.RequestEntity;
 +
 +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
 +
 +import android.util.Log;
 +
 +
 +/**
 + * A RequestEntity that represents a PIECE of a file.
 + * 
 + * @author David A. Velasco
 + */
 +public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
 +
 +    private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
 +    
 +    //private final File mFile;
 +    private final FileChannel mChannel;
 +    private final String mContentType;
 +    private final long mChunkSize;
 +    private final File mFile;
 +    private long mOffset;
 +    private long mTransferred;
 +    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
 +    private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
 +
 +    public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
 +        super();
 +        if (channel == null) {
 +            throw new IllegalArgumentException("File may not be null");
 +        }
 +        if (chunkSize <= 0) {
 +            throw new IllegalArgumentException("Chunk size must be greater than zero");
 +        }
 +        mChannel = channel;
 +        mContentType = contentType;
 +        mChunkSize = chunkSize;
 +        mFile = file;
 +        mOffset = 0;
 +        mTransferred = 0;
 +    }
 +    
 +    public void setOffset(long offset) {
 +        mOffset = offset;
 +    }
 +    
 +    public long getContentLength() {
 +        try {
 +            return Math.min(mChunkSize, mChannel.size() - mChannel.position());
 +        } catch (IOException e) {
 +            return mChunkSize;
 +        }
 +    }
 +
 +    public String getContentType() {
 +        return mContentType;
 +    }
 +
 +    public boolean isRepeatable() {
 +        return true;
 +    }
 +    
 +    @Override
 +    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.add(listener);
 +        }
 +    }
 +    
 +    @Override
 +    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.addAll(listeners);
 +        }
 +    }
 +    
 +    @Override
 +    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.remove(listener);
 +        }
 +    }
 +    
 +    
 +    public void writeRequest(final OutputStream out) throws IOException {
 +        int readCount = 0;
 +        Iterator<OnDatatransferProgressListener> it = null;
 +        
 +       try {
 +            mChannel.position(mOffset);
 +            long size = mFile.length();
 +            if (size == 0) size = -1;
 +            long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
 +            while (mChannel.position() < maxCount) {
 +                readCount = mChannel.read(mBuffer);
 +                out.write(mBuffer.array(), 0, readCount);
 +                mBuffer.clear();
 +                if (mTransferred < maxCount) {  // condition to avoid accumulate progress for repeated chunks
 +                    mTransferred += readCount;
 +                }
 +                synchronized (mDataTransferListeners) {
 +                    it = mDataTransferListeners.iterator();
 +                    while (it.hasNext()) {
 +                        it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
 +                    }
 +                }
 +            }
 +            
 +        } catch (IOException io) {
 +            Log.e(TAG, io.getMessage());
 +            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
 +            
 +        }
 +    }
 +
 +}
index 0b1214a,0000000..3f066f9
mode 100644,000000..100644
--- /dev/null
@@@ -1,134 -1,0 +1,132 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012 Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.oc_framework.network.webdav;
 +
 +import java.io.File;
 +import java.io.IOException;
 +import java.io.OutputStream;
 +import java.io.RandomAccessFile;
 +import java.nio.ByteBuffer;
 +import java.nio.channels.FileChannel;
 +import java.util.Collection;
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.Set;
 +
 +import org.apache.commons.httpclient.methods.RequestEntity;
 +
 +import android.util.Log;
 +
 +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
 +
 +
 +/**
 + * A RequestEntity that represents a File.
 + * 
 + */
 +public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
 +
 +    final File mFile;
 +    final String mContentType;
 +    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
 +
 +    public FileRequestEntity(final File file, final String contentType) {
 +        super();
 +        this.mFile = file;
 +        this.mContentType = contentType;
 +        if (file == null) {
 +            throw new IllegalArgumentException("File may not be null");
 +        }
 +    }
 +    
 +    @Override
 +    public long getContentLength() {
 +        return mFile.length();
 +    }
 +
 +    @Override
 +    public String getContentType() {
 +        return mContentType;
 +    }
 +
 +    @Override
 +    public boolean isRepeatable() {
 +        return true;
 +    }
 +
 +    @Override
 +    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.add(listener);
 +        }
 +    }
 +    
 +    @Override
 +    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.addAll(listeners);
 +        }
 +    }
 +    
 +    @Override
 +    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
 +        synchronized (mDataTransferListeners) {
 +            mDataTransferListeners.remove(listener);
 +        }
 +    }
 +    
 +    
 +    @Override
 +    public void writeRequest(final OutputStream out) throws IOException {
 +        //byte[] tmp = new byte[4096];
 +        ByteBuffer tmp = ByteBuffer.allocate(4096);
 +        int readResult = 0;
 +        
 +        // TODO(bprzybylski): each mem allocation can throw OutOfMemoryError we need to handle it
 +        //                    globally in some fashionable manner
 +        RandomAccessFile raf = new RandomAccessFile(mFile, "r");
 +        FileChannel channel = raf.getChannel();
 +        Iterator<OnDatatransferProgressListener> it = null;
 +        long transferred = 0;
 +        long size = mFile.length();
 +        if (size == 0) size = -1;
 +        try {
 +            while ((readResult = channel.read(tmp)) >= 0) {
 +                out.write(tmp.array(), 0, readResult);
 +                tmp.clear();
 +                transferred += readResult;
 +                synchronized (mDataTransferListeners) {
 +                    it = mDataTransferListeners.iterator();
 +                    while (it.hasNext()) {
 +                        it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
 +                    }
 +                }
 +            }
 +            
 +        } catch (IOException io) {
 +            Log.e("FileRequestException", io.getMessage());
 +            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
 +            
 +        } finally {
 +            channel.close();
 +            raf.close();
 +        }
 +    }
 +
 +}
index 72274c9,0000000..543374c
mode 100644,000000..100644
--- /dev/null
@@@ -1,246 -1,0 +1,245 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2011  Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.oc_framework.network.webdav;
 +
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import org.apache.commons.httpclient.Credentials;
 +import org.apache.commons.httpclient.Header;
 +import org.apache.commons.httpclient.HttpClient;
 +import org.apache.commons.httpclient.HttpConnectionManager;
 +import org.apache.commons.httpclient.HttpException;
 +import org.apache.commons.httpclient.HttpMethod;
 +import org.apache.commons.httpclient.HttpMethodBase;
 +import org.apache.commons.httpclient.HttpVersion;
 +import org.apache.commons.httpclient.URI;
 +import org.apache.commons.httpclient.UsernamePasswordCredentials;
 +import org.apache.commons.httpclient.auth.AuthPolicy;
 +import org.apache.commons.httpclient.auth.AuthScope;
 +import org.apache.commons.httpclient.cookie.CookiePolicy;
 +import org.apache.commons.httpclient.methods.HeadMethod;
 +import org.apache.commons.httpclient.params.HttpMethodParams;
 +import org.apache.http.HttpStatus;
 +import org.apache.http.params.CoreProtocolPNames;
 +
 +import com.owncloud.android.oc_framework.network.BearerAuthScheme;
 +import com.owncloud.android.oc_framework.network.BearerCredentials;
 +
 +import android.net.Uri;
 +import android.util.Log;
 +
 +public class WebdavClient extends HttpClient {
 +    private static final int MAX_REDIRECTIONS_COUNT = 3;
 +    
 +    private Uri mUri;
 +    private Credentials mCredentials;
 +    private boolean mFollowRedirects;
 +    private String mSsoSessionCookie;
 +    final private static String TAG = WebdavClient.class.getSimpleName();
 +    public static final String USER_AGENT = "Android-ownCloud";
 +    
 +    static private byte[] sExhaustBuffer = new byte[1024];
 +    
 +    /**
 +     * Constructor
 +     */
 +    public WebdavClient(HttpConnectionManager connectionMgr) {
 +        super(connectionMgr);
 +        Log.d(TAG, "Creating WebdavClient");
 +        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
 +        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
 +        mFollowRedirects = true;
 +        mSsoSessionCookie = null;
 +    }
 +
 +    public void setBearerCredentials(String accessToken) {
 +        AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
 +        
 +        List<String> authPrefs = new ArrayList<String>(1);
 +        authPrefs.add(BearerAuthScheme.AUTH_POLICY);
 +        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
 +        
 +        mCredentials = new BearerCredentials(accessToken);
 +        getState().setCredentials(AuthScope.ANY, mCredentials);
 +        mSsoSessionCookie = null;
 +    }
 +
 +    public void setBasicCredentials(String username, String password) {
 +        List<String> authPrefs = new ArrayList<String>(1);
 +        authPrefs.add(AuthPolicy.BASIC);
 +        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
 +        
 +        getParams().setAuthenticationPreemptive(true);
 +        mCredentials = new UsernamePasswordCredentials(username, password);
 +        getState().setCredentials(AuthScope.ANY, mCredentials);
 +        mSsoSessionCookie = null;
 +    }
 +    
 +    public void setSsoSessionCookie(String accessToken) {
 +        getParams().setAuthenticationPreemptive(false);
 +        getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
 +        mSsoSessionCookie = accessToken;
 +        mCredentials = null;
 +    }
 +    
 +    
 +    /**
 +     * Check if a file exists in the OC server
 +     * 
 +     * TODO replace with ExistenceOperation
 +     * 
 +     * @return              'true' if the file exists; 'false' it doesn't exist
 +     * @throws  Exception   When the existence could not be determined
 +     */
 +    public boolean existsFile(String path) throws IOException, HttpException {
 +        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
 +        try {
 +            int status = executeMethod(head);
 +            Log.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
 +            exhaustResponse(head.getResponseBodyAsStream());
 +            return (status == HttpStatus.SC_OK);
 +            
 +        } finally {
 +            head.releaseConnection();    // let the connection available for other methods
 +        }
 +    }
 +    
 +    /**
 +     * Requests the received method with the received timeout (milliseconds).
 +     * 
 +     * Executes the method through the inherited HttpClient.executedMethod(method).
 +     * 
 +     * Sets the socket and connection timeouts only for the method received.
 +     * 
 +     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
 +     * 
 +     * @param method            HTTP method request.
 +     * @param readTimeout       Timeout to set for data reception
 +     * @param conntionTimout    Timeout to set for connection establishment
 +     */
 +    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
 +        int oldSoTimeout = getParams().getSoTimeout();
 +        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
 +        try {
 +            if (readTimeout >= 0) { 
 +                method.getParams().setSoTimeout(readTimeout);   // this should be enough...
 +                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS
 +            }
 +            if (connectionTimeout >= 0) {
 +                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
 +            }
 +            return executeMethod(method);
 +        } finally {
 +            getParams().setSoTimeout(oldSoTimeout);
 +            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
 +        }
 +    }
 +    
 +    
 +    @Override
 +    public int executeMethod(HttpMethod method) throws IOException, HttpException {
 +        boolean customRedirectionNeeded = false;
 +        try {
 +            method.setFollowRedirects(mFollowRedirects);
 +        } catch (Exception e) {
 +            //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
 +            customRedirectionNeeded = mFollowRedirects;
 +        }
 +        if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
 +            method.setRequestHeader("Cookie", mSsoSessionCookie);
 +        }
 +        int status = super.executeMethod(method);
 +        int redirectionsCount = 0;
 +        while (customRedirectionNeeded &&
 +                redirectionsCount < MAX_REDIRECTIONS_COUNT &&
 +                (   status == HttpStatus.SC_MOVED_PERMANENTLY || 
 +                    status == HttpStatus.SC_MOVED_TEMPORARILY ||
 +                    status == HttpStatus.SC_TEMPORARY_REDIRECT)
 +                ) {
 +            
 +            Header location = method.getResponseHeader("Location");
 +            if (location != null) {
 +                Log.d(TAG,  "Location to redirect: " + location.getValue());
 +                method.setURI(new URI(location.getValue(), true));
 +                status = super.executeMethod(method);
 +                redirectionsCount++;
 +                
 +            } else {
 +                Log.d(TAG,  "No location to redirect!");
 +                status = HttpStatus.SC_NOT_FOUND;
 +            }
 +        }
 +        
 +        return status;
 +    }
 +
 +
 +    /**
 +     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
 +     * 
 +     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.
 +     */
 +    public void exhaustResponse(InputStream responseBodyAsStream) {
 +        if (responseBodyAsStream != null) {
 +            try {
 +                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
 +                responseBodyAsStream.close();
 +            
 +            } catch (IOException io) {
 +                Log.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
 +            }
 +        }
 +    }
 +
 +    /**
 +     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
 +     */
 +    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
 +            getParams().setSoTimeout(defaultDataTimeout);
 +            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
 +    }
 +
 +    /**
 +     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
 +     * @param uri
 +     */
 +    public void setBaseUri(Uri uri) {
 +        mUri = uri;
 +    }
 +
 +    public Uri getBaseUri() {
 +        return mUri;
 +    }
 +
 +    public final Credentials getCredentials() {
 +        return mCredentials;
 +    }
 +    
 +    public final String getSsoSessionCookie() {
 +        return mSsoSessionCookie;
 +    }
 +
 +    public void setFollowRedirects(boolean followRedirects) {
 +        mFollowRedirects = followRedirects;
 +    }
 +
 +}
index 85a45df,0000000..3bcfa36
mode 100644,000000..100644
--- /dev/null
@@@ -1,149 -1,0 +1,150 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012  ownCloud
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +package com.owncloud.android.oc_framework.network.webdav;
 +
 +import java.util.Date;
 +
 +import org.apache.jackrabbit.webdav.MultiStatusResponse;
 +import org.apache.jackrabbit.webdav.property.DavProperty;
 +import org.apache.jackrabbit.webdav.property.DavPropertyName;
 +import org.apache.jackrabbit.webdav.property.DavPropertySet;
 +
 +
++
 +import android.net.Uri;
 +import android.util.Log;
 +
 +public class WebdavEntry {
 +    private String mName, mPath, mUri, mContentType, mEtag;
 +    private long mContentLength, mCreateTimestamp, mModifiedTimestamp;
 +
 +    public WebdavEntry(MultiStatusResponse ms, String splitElement) {
 +        resetData();
 +        if (ms.getStatus().length != 0) {
 +            mUri = ms.getHref();
 +
 +            mPath = mUri.split(splitElement, 2)[1];
 +
 +            int status = ms.getStatus()[0].getStatusCode();
 +            DavPropertySet propSet = ms.getProperties(status);
 +            @SuppressWarnings("rawtypes")
 +            DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
 +            if (prop != null) {
 +                mName = (String) prop.getName().toString();
 +                mName = mName.substring(1, mName.length()-1);
 +            }
 +            else {
 +                String[] tmp = mPath.split("/");
 +                if (tmp.length > 0)
 +                    mName = tmp[tmp.length - 1];
 +            }
 +
 +            // use unknown mimetype as default behavior
 +            mContentType = "application/octet-stream";
 +            prop = propSet.get(DavPropertyName.GETCONTENTTYPE);
 +            if (prop != null) {
 +                mContentType = (String) prop.getValue();
 +                // dvelasco: some builds of ownCloud server 4.0.x added a trailing ';' to the MIME type ; if looks fixed, but let's be cautious
 +                if (mContentType.indexOf(";") >= 0) {
 +                    mContentType = mContentType.substring(0, mContentType.indexOf(";"));
 +                }
 +            }
 +            
 +            // check if it's a folder in the standard way: see RFC2518 12.2 . RFC4918 14.3 
 +            prop = propSet.get(DavPropertyName.RESOURCETYPE);
 +            if (prop!= null) {
 +                Object value = prop.getValue();
 +                if (value != null) {
 +                    mContentType = "DIR";   // a specific attribute would be better, but this is enough; unless while we have no reason to distinguish MIME types for folders
 +                }
 +            }
 +
 +            prop = propSet.get(DavPropertyName.GETCONTENTLENGTH);
 +            if (prop != null)
 +                mContentLength = Long.parseLong((String) prop.getValue());
 +
 +            prop = propSet.get(DavPropertyName.GETLASTMODIFIED);
 +            if (prop != null) {
 +                Date d = WebdavUtils
 +                        .parseResponseDate((String) prop.getValue());
 +                mModifiedTimestamp = (d != null) ? d.getTime() : 0;
 +            }
 +
 +            prop = propSet.get(DavPropertyName.CREATIONDATE);
 +            if (prop != null) {
 +                Date d = WebdavUtils
 +                        .parseResponseDate((String) prop.getValue());
 +                mCreateTimestamp = (d != null) ? d.getTime() : 0;
 +            }
 +            
 +            prop = propSet.get(DavPropertyName.GETETAG);
 +            if (prop != null) {
 +                mEtag = (String) prop.getValue();
 +                mEtag = mEtag.substring(1, mEtag.length()-1);
 +            }
 +
 +        } else {
 +            Log.e("WebdavEntry",
 +                    "General fuckup, no status for webdav response");
 +        }
 +    }
 +
 +    public String path() {
 +        return mPath;
 +    }
 +    
 +    public String decodedPath() {
 +        return Uri.decode(mPath);
 +    }
 +
 +    public String name() {
 +        return mName;
 +    }
 +
 +    public boolean isDirectory() {
 +        return mContentType.equals("DIR");
 +    }
 +
 +    public String contentType() {
 +        return mContentType;
 +    }
 +
 +    public String uri() {
 +        return mUri;
 +    }
 +
 +    public long contentLength() {
 +        return mContentLength;
 +    }
 +
 +    public long createTimestamp() {
 +        return mCreateTimestamp;
 +    }
 +
 +    public long modifiedTimestamp() {
 +        return mModifiedTimestamp;
 +    }
 +    
 +    public String etag() {
 +        return mEtag;
 +    }
 +
 +    private void resetData() {
 +        mName = mUri = mContentType = null;
 +        mContentLength = mCreateTimestamp = mModifiedTimestamp = 0;
 +    }
 +}
index 6411e16,0000000..e18ae53
mode 100644,000000..100644
--- /dev/null
@@@ -1,286 -1,0 +1,287 @@@
 +/* ownCloud Android client application
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License version 2,
 + *   as published by the Free Software Foundation.
 + *
 + *   This program 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 General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +package com.owncloud.android.oc_framework.operations;
 +
 +import java.io.IOException;
 +
 +import org.apache.commons.httpclient.Credentials;
 +
 +import com.owncloud.android.oc_framework.network.BearerCredentials;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 +
 +
++
 +import android.accounts.Account;
 +import android.accounts.AccountManager;
 +import android.accounts.AccountsException;
 +import android.app.Activity;
 +import android.content.Context;
 +import android.os.Handler;
 +import android.util.Log;
 +
 +
 +/**
 + * Operation which execution involves one or several interactions with an ownCloud server.
 + * 
 + * Provides methods to execute the operation both synchronously or asynchronously.
 + * 
 + * @author David A. Velasco 
 + */
 +public abstract class RemoteOperation implements Runnable {
 +      
 +    private static final String TAG = RemoteOperation.class.getSimpleName();
 +
 +    /** ownCloud account in the remote ownCloud server to operate */
 +    private Account mAccount = null;
 +    
 +    /** Android Application context */
 +    private Context mContext = null;
 +    
 +      /** Object to interact with the remote server */
 +      private WebdavClient mClient = null;
 +      
 +      /** Callback object to notify about the execution of the remote operation */
 +      private OnRemoteOperationListener mListener = null;
 +      
 +      /** Handler to the thread where mListener methods will be called */
 +      private Handler mListenerHandler = null;
 +
 +      /** Activity */
 +    private Activity mCallerActivity;
 +
 +      
 +      /**
 +       *  Abstract method to implement the operation in derived classes.
 +       */
 +      protected abstract RemoteOperationResult run(WebdavClient client); 
 +      
 +
 +    /**
 +     * Synchronously executes the remote operation on the received ownCloud account.
 +     * 
 +     * Do not call this method from the main thread.
 +     * 
 +     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
 +     * 
 +     * @param account   ownCloud account in remote ownCloud server to reach during the execution of the operation.
 +     * @param context   Android context for the component calling the method.
 +     * @return          Result of the operation.
 +     */
 +    public final RemoteOperationResult execute(Account account, Context context) {
 +        if (account == null)
 +            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
 +        if (context == null)
 +            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
 +        mAccount = account;
 +        mContext = context.getApplicationContext();
 +        try {
 +            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
 +        } catch (Exception e) {
 +            Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
 +            return new RemoteOperationResult(e);
 +        }
 +        return run(mClient);
 +    }
 +    
 +      
 +      /**
 +       * Synchronously executes the remote operation
 +       * 
 +     * Do not call this method from the main thread.
 +     * 
 +       * @param client        Client object to reach an ownCloud server during the execution of the operation.
 +       * @return                      Result of the operation.
 +       */
 +      public final RemoteOperationResult execute(WebdavClient client) {
 +              if (client == null)
 +                      throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
 +              mClient = client;
 +              return run(client);
 +      }
 +
 +      
 +    /**
 +     * Asynchronously executes the remote operation
 +     * 
 +     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
 +     * 
 +     * @param account           ownCloud account in remote ownCloud server to reach during the execution of the operation.
 +     * @param context           Android context for the component calling the method.
 +     * @param listener          Listener to be notified about the execution of the operation.
 +     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
 +     * @return                  Thread were the remote operation is executed.
 +     */
 +    public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
 +        if (account == null)
 +            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
 +        if (context == null)
 +            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
 +        mAccount = account;
 +        mContext = context.getApplicationContext();
 +        mCallerActivity = callerActivity;
 +        mClient = null;     // the client instance will be created from mAccount and mContext in the runnerThread to create below
 +        
 +        mListener = listener;
 +        
 +        mListenerHandler = listenerHandler;
 +        
 +        Thread runnerThread = new Thread(this);
 +        runnerThread.start();
 +        return runnerThread;
 +    }
 +
 +    
 +      /**
 +       * Asynchronously executes the remote operation
 +       * 
 +       * @param client                        Client object to reach an ownCloud server during the execution of the operation.
 +       * @param listener                      Listener to be notified about the execution of the operation.
 +       * @param listenerHandler       Handler associated to the thread where the methods of the listener objects must be called.
 +       * @return                                      Thread were the remote operation is executed.
 +       */
 +      public final Thread execute(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
 +              if (client == null) {
 +                      throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
 +              }
 +              mClient = client;
 +              
 +              if (listener == null) {
 +                      throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
 +              }
 +              mListener = listener;
 +              
 +              if (listenerHandler == null) {
 +                      throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
 +              }
 +              mListenerHandler = listenerHandler;
 +              
 +              Thread runnerThread = new Thread(this);
 +              runnerThread.start();
 +              return runnerThread;
 +      }
 +      
 +    /**
 +     * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
 +     * 
 +     * @param listener          Listener to be notified about the execution of the operation.
 +     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
 +     * @return                  Thread were the remote operation is executed.
 +     */
 +    public final RemoteOperationResult retry() {
 +        return execute(mClient);
 +    }
 +    
 +    /**
 +     * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
 +     * 
 +     * @param listener          Listener to be notified about the execution of the operation.
 +     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
 +     * @return                  Thread were the remote operation is executed.
 +     */
 +    public final Thread retry(OnRemoteOperationListener listener, Handler listenerHandler) {
 +        return execute(mClient, listener, listenerHandler);
 +    }
 +      
 +      
 +      /**
 +       * Asynchronous execution of the operation 
 +       * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}, 
 +       * and result posting.
 +       * 
 +       * TODO refactor && clean the code; now it's a mess
 +       */
 +    @Override
 +    public final void run() {
 +        RemoteOperationResult result = null;
 +        boolean repeat = false;
 +        do {
 +            try{
 +                if (mClient == null) {
 +                    if (mAccount != null && mContext != null) {
 +                        if (mCallerActivity != null) {
 +                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext, mCallerActivity);
 +                        } else {
 +                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
 +                        }
 +                    } else {
 +                        throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
 +                    }
 +                }
 +            
 +            } catch (IOException e) {
 +                Log.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
 +                result = new RemoteOperationResult(e);
 +            
 +            } catch (AccountsException e) {
 +                Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
 +                result = new RemoteOperationResult(e);
 +            }
 +      
 +            if (result == null)
 +                result = run(mClient);
 +        
 +            repeat = false;
 +            if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() &&
 +//                    (result.getCode() == ResultCode.UNAUTHORIZED || (result.isTemporalRedirection() && result.isIdPRedirection()))) {
 +                    (result.getCode() == ResultCode.UNAUTHORIZED || result.isIdPRedirection())) {
 +                /// possible fail due to lack of authorization in an operation performed in foreground
 +                Credentials cred = mClient.getCredentials();
 +                String ssoSessionCookie = mClient.getSsoSessionCookie();
 +                if (cred != null || ssoSessionCookie != null) {
 +                    /// confirmed : unauthorized operation
 +                    AccountManager am = AccountManager.get(mContext);
 +                    boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
 +                    boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
 +                    if (bearerAuthorization) {
 +                        am.invalidateAuthToken(mAccount.type, ((BearerCredentials)cred).getAccessToken());
 +                    } else if (samlBasedSsoAuthorization ) {
 +                        am.invalidateAuthToken(mAccount.type, ssoSessionCookie);
 +                    } else {
 +                        am.clearPassword(mAccount);
 +                    }
 +                    mClient = null;
 +                    repeat = true;  // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity
 +                    result = null;
 +                }
 +            }
 +        } while (repeat);
 +        
 +        final RemoteOperationResult resultToSend = result;
 +        if (mListenerHandler != null && mListener != null) {
 +              mListenerHandler.post(new Runnable() {
 +                @Override
 +                public void run() {
 +                    mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
 +                }
 +            });
 +        }
 +    }
 +
 +
 +    /**
 +     * Returns the current client instance to access the remote server.
 +     * 
 +     * @return      Current client instance to access the remote server.
 +     */
 +    public final WebdavClient getClient() {
 +        return mClient;
 +    }
 +
 +
 +}
@@@ -8,6 -8,5 +8,6 @@@
  # project structure.
  
  # Project target.
- target=android-17
- android.library.reference.1=actionbarsherlock\\library
+ target=android-19
+ android.library.reference.1=actionbarsherlock/library
 +android.library.reference.2=oc_framework
@@@ -25,11 -29,7 +29,7 @@@ import android.os.Bundle
  import android.os.Handler;
  import android.widget.Toast;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.MainApp;
--
- import com.owncloud.android.R;
 +import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
  
  
  /**
@@@ -69,9 -66,11 +69,8 @@@ import com.owncloud.android.oc_framewor
  import com.owncloud.android.ui.dialog.SamlWebViewDialog;\r
  import com.owncloud.android.ui.dialog.SslValidatorDialog;\r
  import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;\r
 -import com.owncloud.android.utils.OwnCloudVersion;\r
 -\r
 -\r
 -import eu.alefzero.webdav.WebdavClient;\r
 +import com.owncloud.android.oc_framework.utils.OwnCloudVersion;\r
  \r
\r
  /**\r
   * This Activity is used to add an ownCloud account to the App\r
   * \r
@@@ -1649,16 -1645,9 +1645,9 @@@ implements  OnRemoteOperationListener, 
          mAuthMessage.setVisibility(View.GONE);\r
      }\r
  \r
-     private void syncAccount(){\r
-         /// immediately request for the synchronization of the new account\r
-         Bundle bundle = new Bundle();\r
-         bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);\r
-         ContentResolver.requestSync(mAccount, MainApp.getAuthTokenType(), bundle);\r
-     }\r
-     \r
      @Override\r
      public boolean onTouchEvent(MotionEvent event) {\r
 -        if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) &&\r
 +        if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&\r
                  mHostUrlInput.hasFocus() && event.getAction() == MotionEvent.ACTION_DOWN) {\r
              checkOcServer();\r
          }\r
@@@ -28,6 -28,9 +28,8 @@@ import java.util.Vector
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
  
 -import com.owncloud.android.MainApp;
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
  import com.owncloud.android.authentication.AuthenticatorActivity;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
@@@ -59,9 -62,8 +61,6 @@@ import android.os.Message
  import android.os.Process;
  import android.widget.RemoteViews;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
 -import eu.alefzero.webdav.WebdavClient;
--
  public class FileDownloader extends Service implements OnDatatransferProgressListener {
      
      public static final String EXTRA_ACCOUNT = "ACCOUNT";
@@@ -37,21 -40,28 +40,27 @@@ import com.owncloud.android.authenticat
  import com.owncloud.android.authentication.AuthenticatorActivity;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
 -import com.owncloud.android.network.OwnCloudClientUtils;
+ import com.owncloud.android.db.DbHandler;
  import com.owncloud.android.operations.ChunkedUploadFileOperation;
  import com.owncloud.android.operations.CreateFolderOperation;
  import com.owncloud.android.operations.ExistenceCheckOperation;
 -import com.owncloud.android.operations.RemoteOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
  import com.owncloud.android.operations.UploadFileOperation;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
 +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
 +import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
 +import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+ import com.owncloud.android.ui.activity.FailedUploadActivity;
+ import com.owncloud.android.ui.activity.FileActivity;
+ import com.owncloud.android.ui.activity.FileDisplayActivity;
+ import com.owncloud.android.ui.activity.InstantUploadActivity;
+ import com.owncloud.android.ui.preview.PreviewImageActivity;
+ import com.owncloud.android.ui.preview.PreviewImageFragment;
 -import com.owncloud.android.utils.OwnCloudVersion;
 -
 -
 -import eu.alefzero.webdav.OnDatatransferProgressListener;
 -import eu.alefzero.webdav.WebdavEntry;
 -import eu.alefzero.webdav.WebdavUtils;
 -
  
  import android.accounts.Account;
  import android.accounts.AccountManager;
@@@ -71,17 -81,8 +80,7 @@@ import android.os.Process
  import android.webkit.MimeTypeMap;
  import android.widget.RemoteViews;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.MainApp;
- import com.owncloud.android.R;
- import com.owncloud.android.db.DbHandler;
- import com.owncloud.android.ui.activity.FailedUploadActivity;
- import com.owncloud.android.ui.activity.FileActivity;
- import com.owncloud.android.ui.activity.FileDisplayActivity;
- import com.owncloud.android.ui.activity.InstantUploadActivity;
- import com.owncloud.android.ui.preview.PreviewImageActivity;
- import com.owncloud.android.ui.preview.PreviewImageFragment;
  
 -import eu.alefzero.webdav.WebdavClient;
  
  public class FileUploader extends Service implements OnDatatransferProgressListener {
  
@@@ -29,13 -29,14 +29,14 @@@ import org.apache.commons.httpclient.me
  
  import com.owncloud.android.Log_OC;
  import com.owncloud.android.datamodel.OCFile;
 -import com.owncloud.android.network.ProgressiveDataTransferer;
 +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
 +import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
  
  import android.accounts.Account;
  
 -import eu.alefzero.webdav.ChunkFromFileChannelRequestEntity;
 -import eu.alefzero.webdav.WebdavClient;
 -import eu.alefzero.webdav.WebdavUtils;
  
  public class ChunkedUploadFileOperation extends UploadFileOperation {
      
@@@ -28,13 -25,15 +25,17 @@@ import org.apache.jackrabbit.webdav.cli
  import com.owncloud.android.Log_OC;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.utils.FileStorageUtils;
+ //import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
+ import android.accounts.Account;
  
 -import eu.alefzero.webdav.WebdavClient;
 -import eu.alefzero.webdav.WebdavUtils;
  
  /**
   * Remote operation performing the rename of a remote file (or folder?) in the ownCloud server.
@@@ -32,14 -28,17 +28,18 @@@ import com.owncloud.android.datamodel.F
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
  import com.owncloud.android.files.services.FileUploader;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  
+ import android.accounts.Account;
+ import android.content.Context;
+ import android.content.Intent;
  
 -import eu.alefzero.webdav.WebdavClient;
 -import eu.alefzero.webdav.WebdavEntry;
 -import eu.alefzero.webdav.WebdavUtils;
 -
  public class SynchronizeFileOperation extends RemoteOperation {
  
      private String TAG = SynchronizeFileOperation.class.getSimpleName();
@@@ -22,21 -22,19 +22,20 @@@ import org.apache.commons.httpclient.me
  import org.json.JSONException;
  import org.json.JSONObject;
  
- import android.accounts.Account;
- import android.accounts.AccountManager;
- import android.content.Context;
- import com.owncloud.android.authentication.AccountAuthenticator;
- import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.Log_OC;
 -import com.owncloud.android.authentication.AccountAuthenticator;
+ import com.owncloud.android.authentication.AccountUtils;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 -import com.owncloud.android.utils.OwnCloudVersion;
 +import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
  
+ import android.accounts.Account;
+ import android.accounts.AccountManager;
+ import android.content.Context;
  
 -import eu.alefzero.webdav.WebdavClient;
 -
  /**
   * Remote operation that checks the version of an ownCloud server and stores it locally
   * 
@@@ -33,22 -33,22 +33,22 @@@ import org.apache.commons.httpclient.me
  import org.apache.http.HttpStatus;
  
  import com.owncloud.android.Log_OC;
- import android.accounts.Account;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileUploader;
 -import com.owncloud.android.network.ProgressiveDataTransferer;
 -import com.owncloud.android.operations.RemoteOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
 +import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity;
 +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
 +import com.owncloud.android.oc_framework.operations.OperationCancelledException;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.utils.FileStorageUtils;
  
+ import android.accounts.Account;
  
 -import eu.alefzero.webdav.FileRequestEntity;
 -import eu.alefzero.webdav.OnDatatransferProgressListener;
 -import eu.alefzero.webdav.WebdavClient;
 -import eu.alefzero.webdav.WebdavUtils;
 -
  /**
   * Remote operation performing the upload of a file to an ownCloud server
   * 
@@@ -24,12 -24,12 +24,13 @@@ import org.apache.http.HttpRequest
  import org.apache.http.HttpResponse;\r
  import org.apache.http.client.ClientProtocolException;\r
  \r
 -import com.owncloud.android.authentication.AccountUtils;\r
 -import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;\r
  import com.owncloud.android.datamodel.FileDataStorageManager;\r
 -import com.owncloud.android.network.OwnCloudClientUtils;\r
 +import com.owncloud.android.oc_framework.accounts.AccountUtils;\r
 +import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;\r
 +import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
  \r
\r
  import android.accounts.Account;\r
  import android.accounts.AccountManager;\r
  import android.accounts.AuthenticatorException;\r
@@@ -26,8 -26,8 +26,9 @@@ import org.apache.http.entity.ByteArray
  
  import com.owncloud.android.authentication.AccountAuthenticator;
  import com.owncloud.android.authentication.AccountUtils;
 +import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
  
  import android.accounts.Account;
  import android.accounts.AccountManager;
  import android.accounts.AuthenticatorException;
@@@ -32,12 -32,13 +32,13 @@@ import com.owncloud.android.R
  import com.owncloud.android.authentication.AuthenticatorActivity;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
 -import com.owncloud.android.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
  import com.owncloud.android.operations.SynchronizeFolderOperation;
  import com.owncloud.android.operations.UpdateOCVersionOperation;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
  
  import android.accounts.Account;
  import android.accounts.AccountsException;
  import android.app.Notification;
@@@ -47,15 -47,14 +47,14 @@@ import com.actionbarsherlock.app.Sherlo
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuInflater;
  import com.actionbarsherlock.view.MenuItem;
- import com.owncloud.android.authentication.AccountAuthenticator;
 +import com.owncloud.android.authentication.AuthenticatorActivity;
 +import com.owncloud.android.authentication.AccountUtils;
 +import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
  import com.owncloud.android.Log_OC;
  import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
 -import com.owncloud.android.authentication.AccountAuthenticator;
 -import com.owncloud.android.authentication.AccountUtils;
 -import com.owncloud.android.authentication.AuthenticatorActivity;
  
  public class AccountSelectActivity extends SherlockListActivity implements
          AccountManagerCallback<Boolean> {
  
@@@ -63,15 -65,15 +65,15 @@@ import com.owncloud.android.R
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
- import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  import com.owncloud.android.files.services.FileObserverService;
  import com.owncloud.android.files.services.FileUploader;
+ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
  import com.owncloud.android.operations.CreateFolderOperation;
 -import com.owncloud.android.operations.OnRemoteOperationListener;
 -import com.owncloud.android.operations.RemoteOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
@@@ -29,6 -29,12 +29,9 @@@ import java.util.Map
  
  import javax.security.auth.x500.X500Principal;
  
 -import com.owncloud.android.network.CertificateCombinedException;
 -import com.owncloud.android.network.OwnCloudClientUtils;
 -import com.owncloud.android.operations.RemoteOperationResult;
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
  import android.app.Dialog;
  import android.content.Context;
  import android.os.Bundle;
@@@ -37,11 -43,6 +40,9 @@@ import android.view.Window
  import android.widget.Button;
  import android.widget.TextView;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
 +import com.owncloud.android.oc_framework.network.CertificateCombinedException;
 +import com.owncloud.android.oc_framework.network.NetworkUtils;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
  
  /**
   * Dialog to request the user about a certificate that could not be validated with the certificates store in the system.
@@@ -48,15 -48,13 +48,15 @@@ import com.owncloud.android.Log_OC
  import com.owncloud.android.R;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  import com.owncloud.android.files.services.FileObserverService;
  import com.owncloud.android.files.services.FileUploader;
+ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 -import com.owncloud.android.operations.OnRemoteOperationListener;
 -import com.owncloud.android.operations.RemoteOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
 +import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
@@@ -31,15 -37,10 +37,9 @@@ import android.widget.ImageButton
  import android.widget.ProgressBar;
  import android.widget.TextView;
  
- import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
- import com.owncloud.android.ui.fragment.FileFragment;
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
  
  
 -import eu.alefzero.webdav.OnDatatransferProgressListener;
 -
  /**
   * This Fragment is used to monitor the progress of a file downloading.
   * 
@@@ -50,19 -50,19 +50,18 @@@ import android.widget.Toast
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuInflater;
  import com.actionbarsherlock.view.MenuItem;
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
 -import com.owncloud.android.operations.OnRemoteOperationListener;
 -import com.owncloud.android.operations.RemoteOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
 +import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
  import com.owncloud.android.ui.fragment.FileFragment;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
 -import eu.alefzero.webdav.WebdavUtils;
--
  
  /**
   * This fragment shows a preview of a downloaded image.
@@@ -67,8 -68,7 +69,6 @@@ import com.owncloud.android.ui.activity
  import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
  import com.owncloud.android.ui.fragment.FileFragment;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
 -import eu.alefzero.webdav.WebdavUtils;
  
  /**
   * This fragment shows a preview of a downloaded media file (audio or video).
  
  package com.owncloud.android.ui.preview;
  
 -import com.owncloud.android.authentication.AccountUtils;
 -import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.media.MediaService;
+ import com.owncloud.android.ui.activity.FileActivity;
  import android.accounts.Account;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
@@@ -30,15 -39,6 +37,9 @@@ import android.os.Bundle
  import android.widget.MediaController;
  import android.widget.VideoView;
  
- import com.owncloud.android.Log_OC;
- import com.owncloud.android.R;
- import com.owncloud.android.datamodel.FileDataStorageManager;
 +import com.owncloud.android.oc_framework.accounts.AccountUtils;
 +import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
- import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.media.MediaService;
- import com.owncloud.android.ui.activity.FileActivity;
 +
  /**
   *  Activity implementing a basic video player.
   * 
@@@ -1,11 -1,10 +1,4 @@@
  <?xml version="1.0" encoding="UTF-8"?>
  <classpath>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
--      <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
--      <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
--      <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
--      <classpathentry combineaccessrules="false" kind="src" path="/owncloud-android"/>
-       <classpathentry kind="lib" path="/oc_framework/bin/oc_framework.jar"/>
 -      <classpathentry kind="src" path="src"/>
 -      <classpathentry kind="src" path="gen"/>
        <classpathentry kind="output" path="bin/classes"/>
  </classpath>