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;
 +    }
 +
 +
 +}
diff --combined project.properties
@@@ -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
  
  package com.owncloud.android.authentication;
  
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.MainApp;
+ import com.owncloud.android.R;
  import android.accounts.*;
  import android.content.Context;
  import android.content.Intent;
@@@ -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;
  
  
  /**
@@@ -53,6 -53,34 +53,6 @@@ public class AccountAuthenticator exten
      public static final String KEY_LOGIN_OPTIONS = "loginOptions";
      public static final String KEY_ACCOUNT = "account";
      
 -    /**
 -     * Value under this key should handle path to webdav php script. Will be
 -     * removed and usage should be replaced by combining
 -     * {@link com.owncloud.android.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
 -     * {@link com.owncloud.android.utils.OwnCloudVersion}
 -     * 
 -     * @deprecated
 -     */
 -    public static final String KEY_OC_URL = "oc_url";
 -    /**
 -     * Version should be 3 numbers separated by dot so it can be parsed by
 -     * {@link com.owncloud.android.utils.OwnCloudVersion}
 -     */
 -    public static final String KEY_OC_VERSION = "oc_version";
 -    /**
 -     * Base url should point to owncloud installation without trailing / ie:
 -     * http://server/path or https://owncloud.server
 -     */
 -    public static final String KEY_OC_BASE_URL = "oc_base_url";
 -    /**
 -     * Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
 -     */
 -    public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
 -    /**
 -     * Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
 -     */
 -    public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
 -    
      private static final String TAG = AccountAuthenticator.class.getSimpleName();
      
      private Context mContext;
          /// check if required token is stored
          final AccountManager am = AccountManager.get(mContext);
          String accessToken;
 -        if (authTokenType.equals(MainApp.getAuthTokenTypePass())) {
 +        if (authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType()))) {
              accessToken = am.getPassword(account);
          } else {
              accessToken = am.peekAuthToken(account, authTokenType);
      private void validateAuthTokenType(String authTokenType)\r
              throws UnsupportedAuthTokenTypeException {\r
          if (!authTokenType.equals(MainApp.getAuthTokenType()) &&\r
 -            !authTokenType.equals(MainApp.getAuthTokenTypePass()) &&\r
 -            !authTokenType.equals(MainApp.getAuthTokenTypeAccessToken()) &&\r
 -            !authTokenType.equals(MainApp.getAuthTokenTypeRefreshToken()) &&
 -            !authTokenType.equals(MainApp.getAuthTokenTypeSamlSessionCookie())) {\r
 +            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType())) &&\r
 +            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType())) &&\r
 +            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeRefreshToken(MainApp.getAccountType())) &&
 +            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()))) {\r
              throw new UnsupportedAuthTokenTypeException();\r
          }\r
      }\r
@@@ -55,23 -55,22 +55,22 @@@ import com.owncloud.android.Log_OC
  import com.owncloud.android.MainApp;\r
  import com.owncloud.android.R;\r
  import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;\r
 -import com.owncloud.android.network.OwnCloudClientUtils;\r
 +import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;\r
 +import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;\r
 +import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
  import com.owncloud.android.operations.ExistenceCheckOperation;\r
  import com.owncloud.android.operations.OAuth2GetAccessToken;\r
 -import com.owncloud.android.operations.OnRemoteOperationListener;\r
 +import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;\r
  import com.owncloud.android.operations.OwnCloudServerCheckOperation;\r
 -import com.owncloud.android.operations.RemoteOperation;\r
 -import com.owncloud.android.operations.RemoteOperationResult;\r
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;\r
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;\r
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;\r
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;\r
  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
@@@ -194,11 -193,16 +193,16 @@@ implements  OnRemoteOperationListener, 
          /// set Host Url Input Enabled\r
          mHostUrlInputEnabled = getResources().getBoolean(R.bool.show_server_url_input);\r
          \r
\r
-         /// complete label for 'register account' button\r
-         Button b = (Button) findViewById(R.id.account_register);\r
-         if (b != null) {\r
-             b.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));\r
+         /// set visibility of link for new users\r
+         boolean accountRegisterVisibility = getResources().getBoolean(R.bool.show_welcome_link);\r
+         Button welcomeLink = (Button) findViewById(R.id.welcome_link);\r
+         if (welcomeLink != null) {\r
+             if (accountRegisterVisibility) {\r
+                 welcomeLink.setVisibility(View.VISIBLE);\r
+                 welcomeLink.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));            \r
+             } else {\r
+                 findViewById(R.id.welcome_link).setVisibility(View.GONE);\r
+             }\r
          }\r
  \r
          /// initialization\r
              /// retrieve extras from intent\r
              mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);\r
              if (mAccount != null) {\r
 -                String ocVersion = mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION);\r
 +                String ocVersion = mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION);\r
                  if (ocVersion != null) {\r
                      mDiscoveredVersion = new OwnCloudVersion(ocVersion);\r
                  }\r
 -                mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL));\r
 +                mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL));\r
                  mHostUrlInput.setText(mHostBaseUrl);\r
                  String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));\r
                  mUsernameInput.setText(userName);\r
              mAccount = savedInstanceState.getParcelable(KEY_ACCOUNT);\r
              mAuthTokenType = savedInstanceState.getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
              if (mAuthTokenType == null) {\r
 -                mAuthTokenType =  MainApp.getAuthTokenTypePass();\r
 +                mAuthTokenType =  AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
                  \r
              }\r
  \r
          if (mServerIsChecked && !mServerIsValid && refreshButtonEnabled) showRefreshButton();\r
          mOkButton.setEnabled(mServerIsValid); // state not automatically recovered in configuration changes\r
  \r
 -        if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) || \r
 +        if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) || \r
                  !AUTH_OPTIONAL.equals(getString(R.string.auth_method_oauth2))) {\r
              mOAuth2Check.setVisibility(View.GONE);\r
          }\r
              @Override\r
              public boolean onTouch(View view, MotionEvent event) {\r
                  if (event.getAction() == MotionEvent.ACTION_DOWN) {\r
 -                    if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) &&\r
 +                    if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&\r
                              mHostUrlInput.hasFocus()) {\r
                          checkOcServer();\r
                      }\r
          if (mAuthTokenType == null) {    \r
              if (mAccount != null) {\r
                  /// same authentication method than the one used to create the account to update\r
 -                oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);\r
 -                samlWebSsoRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null);\r
 +                oAuthRequired = (mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null);\r
 +                samlWebSsoRequired = (mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null);\r
              \r
              } else {\r
                  /// use the one set in setup.xml\r
                  samlWebSsoRequired = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));            \r
              }\r
              if (oAuthRequired) {\r
 -                mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();\r
 +                mAuthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
              } else if (samlWebSsoRequired) {\r
 -                mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();\r
 +                mAuthTokenType = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());\r
              } else {\r
 -                mAuthTokenType = MainApp.getAuthTokenTypePass();\r
 +                mAuthTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
              }\r
          }\r
      \r
              mUsernameInput.setText(userName);\r
          }\r
          \r
 -        mOAuth2Check.setChecked(MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType));\r
 +        mOAuth2Check.setChecked(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType));\r
          \r
      }\r
  \r
      protected void onResume() {\r
          super.onResume();\r
          if (mAction == ACTION_UPDATE_TOKEN && mJustCreated && getIntent().getBooleanExtra(EXTRA_ENFORCED_UPDATE, false)) {\r
 -            if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
 +            if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                  //Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show();\r
                  showAuthMessage(getString(R.string.auth_expired_oauth_token_toast));\r
 -            } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
 +            } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                  //Toast.makeText(this, R.string.auth_expired_saml_sso_token_toast, Toast.LENGTH_LONG).show();\r
                  showAuthMessage(getString(R.string.auth_expired_saml_sso_token_toast));\r
              } else {\r
                  getString(R.string.oauth2_grant_type),\r
                  queryParameters);\r
          //WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
 -        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
 +        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
          operation.execute(client, this, mHandler);\r
      }\r
  \r
              mServerStatusIcon = R.drawable.progress_small;\r
              showServerStatus();\r
              mOcServerChkOperation = new  OwnCloudServerCheckOperation(uri, this);\r
 -            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this, true);\r
 +            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);\r
              mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);\r
          } else {\r
              mServerStatusText = 0;\r
              return;\r
          }\r
  \r
 -        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
 +        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
              startOauthorization();\r
 -        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) { \r
 +        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) { \r
              startSamlBasedFederatedSingleSignOnAuthorization();\r
          } else {\r
              checkBasicAuthorization();\r
  \r
          /// test credentials accessing the root folder\r
          mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
 -        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
 +        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
          client.setBasicCredentials(username, password);\r
          mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
      }\r
  \r
          /// test credentials accessing the root folder\r
          mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
 -        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
 +        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
          mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
        \r
      }\r
              onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);\r
  \r
          } else if (operation instanceof ExistenceCheckOperation)  {\r
 -            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
 +            if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                  onSamlBasedFederatedSingleSignOnAuthorizationStart(operation, result);\r
                  \r
              } else {\r
              mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
              Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);\r
              mAuthCheckOperation = new ExistenceCheckOperation("", this, false);\r
 -            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
 +            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
              client.setBearerCredentials(mAuthToken);\r
              mAuthCheckOperation.execute(client, this, mHandler);\r
  \r
          response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);\r
          response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);\r
          \r
 -        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) { \r
 +        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) { \r
              response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);\r
              // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention\r
              mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
              \r
 -        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
 +        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
              String username = getUserNameForSamlSso();\r
              if (!mUsernameInput.getText().toString().equals(username)) {\r
                  // fail - not a new account, but an existing one; disallow\r
       */\r
      private boolean createAccount() {\r
          /// create and save new ownCloud account\r
 -        boolean isOAuth = MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType);\r
 -        boolean isSaml =  MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType);\r
 +        boolean isOAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType);\r
 +        boolean isSaml =  AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType);\r
  \r
          Uri uri = Uri.parse(mHostBaseUrl);\r
          String username = mUsernameInput.getText().toString().trim();\r
                  mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
              }\r
              /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA\r
 -            mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION,    mDiscoveredVersion.toString());\r
 -            mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL,   mHostBaseUrl);\r
 +            mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION,    mDiscoveredVersion.toString());\r
 +            mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL,   mHostBaseUrl);\r
              if (isSaml) {\r
 -                mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
 +                mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
              } else if (isOAuth) {\r
 -                mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE");  \r
 +                mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2, "TRUE");  \r
              }\r
      \r
              setAccountAuthenticatorResult(intent.getExtras());\r
              setResult(RESULT_OK, intent);\r
      \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
-             syncAccount();\r
- //          Bundle bundle = new Bundle();\r
- //          bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);\r
- //          ContentResolver.requestSync(mAccount, MainApp.getAuthTokenType(), bundle);\r
              return true;\r
          }\r
      }\r
       * @param view      'Account register' button\r
       */\r
      public void onRegisterClick(View view) {\r
-         Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_account_register)));\r
+         Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.welcome_link_url)));\r
          setResult(RESULT_CANCELED);\r
          startActivity(register);\r
      }\r
      public void onCheckClick(View view) {\r
          CheckBox oAuth2Check = (CheckBox)view;\r
          if (oAuth2Check.isChecked()) {\r
 -            mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();\r
 +            mAuthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
          } else {\r
 -            mAuthTokenType = MainApp.getAuthTokenTypePass();\r
 +            mAuthTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
          }\r
          adaptViewAccordingToAuthenticationMethod();\r
      }\r
       * the current authorization method.\r
       */\r
      private void adaptViewAccordingToAuthenticationMethod () {\r
 -        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
 +        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
              // OAuth 2 authorization\r
              mOAuthAuthEndpointText.setVisibility(View.VISIBLE);\r
              mOAuthTokenEndpointText.setVisibility(View.VISIBLE);\r
              mUsernameInput.setVisibility(View.GONE);\r
              mPasswordInput.setVisibility(View.GONE);\r
              \r
 -        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
 +        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
              // SAML-based web Single Sign On\r
              mOAuthAuthEndpointText.setVisibility(View.GONE);\r
              mOAuthTokenEndpointText.setVisibility(View.GONE);\r
              }\r
              \r
          } else if (actionId == EditorInfo.IME_ACTION_NEXT && inputField != null && inputField.equals(mHostUrlInput)) {\r
 -            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
 +            if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                  checkOcServer();\r
              }\r
          }\r
          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
@@@ -23,12 -23,13 +23,13 @@@ import java.io.File
  import com.owncloud.android.Log_OC;
  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.SynchronizeFileOperation;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.ui.activity.ConflictsResolveActivity;
  
  
  import android.accounts.Account;
  import android.content.Context;
  import android.content.Intent;
@@@ -28,21 -28,24 +28,23 @@@ 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;
 -import com.owncloud.android.network.OwnCloudClientUtils;
 +
 +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
 +import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
 +import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
  import com.owncloud.android.operations.DownloadFileOperation;
 -import com.owncloud.android.operations.RemoteOperationResult;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.ui.activity.FileActivity;
  import com.owncloud.android.ui.activity.FileDisplayActivity;
  import com.owncloud.android.ui.preview.PreviewImageActivity;
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  
 -import eu.alefzero.webdav.OnDatatransferProgressListener;
 -
 -
  import android.accounts.Account;
  import android.accounts.AccountsException;
  import android.app.Notification;
@@@ -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";
                  if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
                      mLastAccount = mCurrentDownload.getAccount();
                      mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
 -                    mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
 +                    mDownloadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
                  }
  
                  /// perform the download
              boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
                                                  // (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
                                                    (downloadResult.isIdPRedirection()
 -                                                        && MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
 +                                                        && mDownloadClient.getCredentials() == null));
 +                                                        //&& MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
              if (needsToUpdateCredentials) {
                  // let the user update credentials with one click
                  Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
@@@ -33,25 -33,35 +33,34 @@@ import org.apache.jackrabbit.webdav.Dav
  import org.apache.jackrabbit.webdav.MultiStatus;
  import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
  
+ 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.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 {
  
              }
          }
  
 -        OwnCloudVersion ocv = new OwnCloudVersion(AccountManager.get(this).getUserData(account,
 -                AccountAuthenticator.KEY_OC_VERSION));
 +        OwnCloudVersion ocv = new OwnCloudVersion(AccountManager.get(this).getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION));
          boolean chunked = FileUploader.chunkedUploadIsSupported(ocv);
          AbstractList<String> requestedUploads = new Vector<String>();
          String uploadKey = null;
                  if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
                      mLastAccount = mCurrentUpload.getAccount();
                      mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
 -                    mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
 +                    mUploadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
                  }
                  
                  /// check the existence of the parent folder for the file to upload
              boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
                      //(uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() && 
                      (uploadResult.isIdPRedirection() &&
 -                            MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
 +                            mUploadClient.getCredentials() == null));
 +                            //MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
              if (needsToUpdateCredentials) {
                  // let the user update credentials with one click
                  Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
@@@ -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 {
      
@@@ -21,20 -21,19 +21,21 @@@ import java.io.File
  import java.io.IOException;
  
  import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
- //import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
- import android.accounts.Account;
  
  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.
@@@ -23,23 -23,22 +23,23 @@@ import org.apache.jackrabbit.webdav.Dav
  import org.apache.jackrabbit.webdav.MultiStatus;
  import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
  
- import android.accounts.Account;
- import android.content.Context;
- import android.content.Intent;
  import com.owncloud.android.Log_OC;
  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.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
   * 
@@@ -59,7 -57,7 +58,7 @@@ public class UpdateOCVersionOperation e
      @Override
      protected RemoteOperationResult run(WebdavClient client) {
          AccountManager accountMngr = AccountManager.get(mContext); 
 -        String statUrl = accountMngr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL);
 +        String statUrl = accountMngr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL);
          statUrl += AccountUtils.STATUS_PATH;
          RemoteOperationResult result = null;
          GetMethod get = null;
@@@ -77,7 -75,7 +76,7 @@@
                      if (json != null && json.getString("version") != null) {
                          OwnCloudVersion ocver = new OwnCloudVersion(json.getString("version"));
                          if (ocver.isVersionValid()) {
 -                            accountMngr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, ocver.toString());
 +                            accountMngr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION, ocver.toString());
                              Log_OC.d(TAG, "Got new OC version " + ocver.toString());
                              result = new RemoteOperationResult(ResultCode.OK);
                              
@@@ -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
@@@ -37,6 -37,7 +38,6 @@@ import android.accounts.OperationCancel
  import android.content.AbstractThreadedSyncAdapter;\r
  import android.content.ContentProviderClient;\r
  import android.content.Context;\r
 -import eu.alefzero.webdav.WebdavClient;\r
  \r
  /**\r
   * Base synchronization adapter for ownCloud designed to be subclassed for different\r
@@@ -52,7 -53,7 +53,7 @@@ public abstract class AbstractOwnCloudS
  \r
      private AccountManager accountManager;\r
      private Account account;\r
-     private ContentProviderClient contentProvider;\r
+     private ContentProviderClient mContentProviderClient;\r
      private FileDataStorageManager mStoreManager;\r
  \r
      private WebdavClient mClient = null;\r
          this.setAccountManager(AccountManager.get(context));\r
      }\r
  \r
+     public AbstractOwnCloudSyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {\r
+         super(context, autoInitialize, allowParallelSyncs);\r
+         this.setAccountManager(AccountManager.get(context));\r
+     }\r
\r
      public AccountManager getAccountManager() {\r
          return accountManager;\r
      }\r
          this.account = account;\r
      }\r
  \r
-     public ContentProviderClient getContentProvider() {\r
-         return contentProvider;\r
+     public ContentProviderClient getContentProviderClient() {\r
+         return mContentProviderClient;\r
      }\r
  \r
-     public void setContentProvider(ContentProviderClient contentProvider) {\r
-         this.contentProvider = contentProvider;\r
+     public void setContentProviderClient(ContentProviderClient contentProvider) {\r
+         this.mContentProviderClient = contentProvider;\r
      }\r
  \r
      public void setStorageManager(FileDataStorageManager storage_manager) {\r
  \r
      protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {\r
          AccountUtils.constructFullURLForAccount(getContext(), account);\r
 -        mClient = OwnCloudClientUtils.createOwnCloudClient(account, getContext());\r
 +        mClient = OwnCloudClientFactory.createOwnCloudClient(account, getContext());\r
      }\r
      \r
      protected WebdavClient getClient() {\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;
@@@ -53,7 -53,7 +54,7 @@@ public class ContactSyncAdapter extend
      public void onPerformSync(Account account, Bundle extras, String authority,
              ContentProviderClient provider, SyncResult syncResult) {
          setAccount(account);
-         setContentProvider(provider);
+         setContentProviderClient(provider);
          Cursor c = getLocalContacts(false);
          if (c.moveToFirst()) {
              do {
@@@ -92,7 -92,7 +93,7 @@@
          AccountManager am = getAccountManager();
          @SuppressWarnings("deprecation")
          String uri = am.getUserData(getAccount(),
 -                AccountAuthenticator.KEY_OC_URL).replace(
 +                OwnCloudAccount.Constants.KEY_OC_URL).replace(
                  AccountUtils.WEBDAV_PATH_2_0, AccountUtils.CARDDAV_PATH_2_0);
          uri += "/addressbooks/"
                  + getAccount().name.substring(0,
@@@ -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;
@@@ -97,7 -98,7 +98,7 @@@ public class FileSyncAdapter extends Ab
      
      
      /**
-      * Creates an {@link FileSyncAdapter}
+      * Creates a {@link FileSyncAdapter}
       *
       * {@inheritDoc}
       */
  
      
      /**
+      * Creates a {@link FileSyncAdapter}
+      *
+      * {@inheritDoc}
+      */
+     public FileSyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
+         super(context, autoInitialize, allowParallelSyncs);
+     }
+     
+     /**
       * {@inheritDoc}
       */
      @Override
      public synchronized void onPerformSync(Account account, Bundle extras,
-             String authority, ContentProviderClient provider,
+             String authority, ContentProviderClient providerClient,
              SyncResult syncResult) {
  
          mCancellation = false;
          mSyncResult.delayUntil = 60*60*24; // avoid too many automatic synchronizations
  
          this.setAccount(account);
-         this.setContentProvider(provider);
-         this.setStorageManager(new FileDataStorageManager(account, provider));
+         this.setContentProviderClient(providerClient);
+         this.setStorageManager(new FileDataStorageManager(account, providerClient));
          try {
              this.initClientForCurrentAccount();
          } catch (IOException e) {
          } else {
              // in failures, the statistics for the global result are updated
              if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
 -                    ( result.isIdPRedirection() && 
 -                            MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
 +                    ( result.isIdPRedirection() &&
 +                            getClient().getCredentials() == null      )) {
 +                            //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
                  mSyncResult.stats.numAuthExceptions++;
                  
              } else if (result.getException() instanceof DavException) {
          notification.flags |= Notification.FLAG_AUTO_CANCEL;
          boolean needsToUpdateCredentials = (mLastFailedResult != null && 
                                               (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
 -                                                // (mLastFailedResult.isTemporalRedirection() && mLastFailedResult.isIdPRedirection() && 
                                                  ( mLastFailedResult.isIdPRedirection() && 
 -                                                 MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
 +                                                  getClient().getCredentials() == null      )
 +                                                 //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
                                               )
                                             );
          // TODO put something smart in the contentIntent below for all the possible errors
@@@ -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> {
  
                  (mPreviousAccount != null && !mPreviousAccount.equals(current))) {
                  /// the account set as default changed since this activity was created 
              
-                 // trigger synchronization
-                 ContentResolver.cancelSync(null, MainApp.getAuthTokenType());
-                 Bundle bundle = new Bundle();
-                 bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-                 ContentResolver.requestSync(AccountUtils.getCurrentOwnCloudAccount(this), MainApp.getAuthTokenType(), bundle);
-                 
                  // restart the main activity
                  Intent i = new Intent(this, FileDisplayActivity.class);
                  i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                  h.put("VER",
                          "ownCloud version: "
                                  + am.getUserData(a,
 -                                        AccountAuthenticator.KEY_OC_VERSION));
 +                                        OwnCloudAccount.Constants.KEY_OC_VERSION));
                  ll.add(h);
              }
  
@@@ -31,8 -31,10 +31,10 @@@ import android.content.Context
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.content.IntentFilter;
+ import android.content.IntentFilter.AuthorityEntry;
  import android.content.ServiceConnection;
  import android.content.SharedPreferences;
+ import android.content.SyncRequest;
  import android.content.res.Resources.NotFoundException;
  import android.database.Cursor;
  import android.net.Uri;
@@@ -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;
@@@ -89,6 -91,7 +91,7 @@@ import com.owncloud.android.ui.preview.
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
  import com.owncloud.android.ui.preview.PreviewVideoActivity;
  
  /**
   * Displays, what files the user has available in his ownCloud.
   * 
@@@ -493,12 -496,27 +496,27 @@@ OCFileListFragment.ContainerActivity, F
      }
  
      private void startSynchronization() {
-         ContentResolver.cancelSync(null, MainApp.getAuthTokenType());   // cancel the current synchronizations of any ownCloud account
-         Bundle bundle = new Bundle();
-         bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-         ContentResolver.requestSync(
-                 getAccount(),
-                 MainApp.getAuthTokenType(), bundle);
+         Log_OC.e(TAG, "Got to start sync");
+         if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
+             Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority());
+             ContentResolver.cancelSync(null, MainApp.getAuthority());   // cancel the current synchronizations of any ownCloud account
+             Bundle bundle = new Bundle();
+             bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+             bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
+             ContentResolver.requestSync(
+                     getAccount(),
+                     MainApp.getAuthority(), bundle);
+         } else {
+             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
+             SyncRequest.Builder builder = new SyncRequest.Builder();
+             builder.setSyncAdapter(getAccount(), MainApp.getAuthority());
+             builder.setExpedited(true);
+             builder.setManual(true);
+             builder.syncOnce();
+             SyncRequest request = builder.build();
+             ContentResolver.requestSync(request);
+         }
      }
  
  
  
      @Override
      public void onSavedCertificate() {
-         startSynchronization();                
+         startSyncFolderOperation(getCurrentDir());                
      }
  
  
@@@ -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.
@@@ -142,11 -143,11 +143,11 @@@ public class SslValidatorDialog extend
                         View detailsScroll = findViewById(R.id.details_scroll);
                         if (detailsScroll.getVisibility() == View.VISIBLE) {
                             detailsScroll.setVisibility(View.GONE);
-                            ((Button)v).setText(R.string.ssl_validator_btn_details_see);
+                            ((Button) v).setText(R.string.ssl_validator_btn_details_see);
                             
                         } else {
                             detailsScroll.setVisibility(View.VISIBLE);
-                            ((Button)v).setText(R.string.ssl_validator_btn_details_hide);
+                            ((Button) v).setText(R.string.ssl_validator_btn_details_hide);
                         }
                      }
                  });
      private void saveServerCert() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
          if (mException.getServerCertificate() != null) {
              // TODO make this asynchronously, it can take some time
 -            OwnCloudClientUtils.addCertToKnownServersStore(mException.getServerCertificate(), getContext());
 +            NetworkUtils.addCertToKnownServersStore(mException.getServerCertificate(), getContext());
          }
      }
  
@@@ -48,18 -48,17 +48,18 @@@ 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;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.ui.activity.ConflictsResolveActivity;
  import com.owncloud.android.ui.activity.FileActivity;
  import com.owncloud.android.ui.activity.FileDisplayActivity;
@@@ -68,6 -67,8 +68,6 @@@ import com.owncloud.android.ui.dialog.E
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  
  
 -import eu.alefzero.webdav.OnDatatransferProgressListener;
 -
  /**
   * This Fragment is used to display the details about a file.
   * 
@@@ -29,8 -29,8 +29,8 @@@ import com.owncloud.android.datamodel.O
  import com.owncloud.android.files.FileHandler;
  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.oc_framework.operations.OnRemoteOperationListener;
 +import com.owncloud.android.oc_framework.operations.RemoteOperation;
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
@@@ -43,6 -43,7 +43,7 @@@ import com.owncloud.android.ui.fragment
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
  
  import android.accounts.Account;
  import android.app.Activity;
  import android.os.Bundle;
@@@ -19,6 -19,12 +19,12 @@@ package com.owncloud.android.ui.preview
  
  import java.lang.ref.WeakReference;
  
+ import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
+ import com.owncloud.android.ui.fragment.FileFragment;
  import android.accounts.Account;
  import android.app.Activity;
  import android.os.Bundle;
@@@ -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.
@@@ -52,23 -52,23 +52,23 @@@ import android.widget.VideoView
  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.media.MediaControlView;
  import com.owncloud.android.media.MediaService;
  import com.owncloud.android.media.MediaServiceBinder;
 -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.activity.FileActivity;
  import com.owncloud.android.ui.activity.FileDisplayActivity;
  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.
   * 
@@@ -19,15 -19,16 +19,16 @@@ package com.owncloud.android.utils
  
  import java.io.File;
  
+ import com.owncloud.android.MainApp;
+ import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.OCFile;
  import android.annotation.SuppressLint;
  import android.content.Context;
  import android.net.Uri;
  import android.os.Environment;
  import android.os.StatFs;
  
- import com.owncloud.android.MainApp;
- import com.owncloud.android.R;
- import com.owncloud.android.datamodel.OCFile;
  
  /**
   * Static methods to help in access to local file system.
@@@ -75,11 -76,5 +76,11 @@@ public class FileStorageUtils 
          String value = uploadPath + OCFile.PATH_SEPARATOR +  (fileName == null ? "" : fileName);
          return value;
      }
 +    
 +    public static String getParentPath(String remotePath) {
 +        String parentPath = new File(remotePath).getParent();
 +        parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
 +        return parentPath;
 +    }
    
  }
diff --combined tests/.classpath
@@@ -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>