--- /dev/null
+/* 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;
+ }
+ }
+
+}
--- /dev/null
+/* 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;
+ }
+ }
+
+}
--- /dev/null
+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");
+ }
+
+}
--- /dev/null
-
+/* 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);
+
+ }
+ }
+
+}
--- /dev/null
-
-
+/* 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();
+ }
+ }
+
+}
--- /dev/null
-
+/* 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;
+ }
+
+}
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+/* 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;
+ }
+
+
+}
# 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;
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;
/**
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
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
/// 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
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;
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;
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);
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;
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);
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 {
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.
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();
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
*
@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;
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);
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
*
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
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
\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
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;
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 {
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,
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;
/**
- * 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
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);
}
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;
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;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
import com.owncloud.android.ui.preview.PreviewVideoActivity;
+
/**
* Displays, what files the user has available in his ownCloud.
*
}
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());
}
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;
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.
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());
}
}
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;
import com.owncloud.android.ui.preview.PreviewImageFragment;
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
/**
* This Fragment is used to display the details about a file.
*
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;
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;
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;
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.
*
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.
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;
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.
*
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.
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;
+ }
}
<?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>