--- /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
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;
/**
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
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 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 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";
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 {
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 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 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
*
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 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;
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;
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> {
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 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.
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 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.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.
*
<?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>