Merge branch 'saml_based_federated_single_sign_on' into saml_based_federated_single_s...
authormasensio <masensio@solidgear.es>
Thu, 22 Aug 2013 10:59:56 +0000 (12:59 +0200)
committermasensio <masensio@solidgear.es>
Thu, 22 Aug 2013 10:59:56 +0000 (12:59 +0200)
Conflicts:
res/values-es/strings.xml
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

23 files changed:
res/layout-land/account_setup.xml
res/layout/account_setup.xml
res/values-es/strings.xml
res/values/strings.xml
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/network/OwnCloudClientUtils.java
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
src/com/owncloud/android/operations/CreateFolderOperation.java
src/com/owncloud/android/operations/DownloadFileOperation.java
src/com/owncloud/android/operations/OAuth2GetAccessToken.java
src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java
src/com/owncloud/android/operations/RemoteOperation.java
src/com/owncloud/android/operations/RemoteOperationResult.java
src/com/owncloud/android/operations/RemoveFileOperation.java
src/com/owncloud/android/operations/RenameFileOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/SynchronizeFolderOperation.java
src/com/owncloud/android/operations/UpdateOCVersionOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/eu/alefzero/webdav/WebdavClient.java

index 5b3ec5d..e00ade8 100644 (file)
                        android:onClick="onRefreshClick"\r
                                    android:text="@string/auth_check_server"\r
                                    android:visibility="gone" />\r
-               \r
+                               <TextView\r
+                                   android:id="@+id/auth_message"\r
+                                   android:layout_width="wrap_content"\r
+                                   android:layout_height="wrap_content"\r
+                                   android:layout_gravity="fill_horizontal"\r
+                                   android:text="@string/auth_expired_basic_auth_toast" \r
+                                   android:visibility="gone"\r
+                                   android:layout_marginBottom="10dp"/>\r
                            <FrameLayout \r
                                android:id="@+id/hostUrlFrame"\r
                                        android:layout_width="match_parent"\r
index 9a325ee..cab3d8b 100644 (file)
             android:onClick="onRefreshClick"\r
             android:text="@string/auth_check_server"\r
             android:visibility="gone" />\r
+        \r
+        <TextView\r
+            android:id="@+id/auth_message"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="fill_horizontal"\r
+            android:text="@string/auth_expired_basic_auth_toast"\r
+            android:visibility="gone"\r
+            android:layout_marginBottom="10dp" />\r
 \r
            <FrameLayout \r
                android:id="@+id/hostUrlFrame"\r
index 065e95b..8e6ad5e 100644 (file)
   <string name="auth_not_found">Ruta errónea</string>
   <string name="auth_internal">Error interno en el servidor, código %1$d</string>
   <string name="auth_wtf_reenter_URL">Estado inesperado; por favor, introduzca la URL del servidor de nuevo</string>
-  <string name="auth_expired_oauth_token_toast">Su autorización ha expirado.\nPor favor, autorice de nuevo</string>
+  <string name="auth_expired_oauth_token_toast">Su autorización ha expirado. Por favor, autorice de nuevo</string>
   <string name="auth_expired_basic_auth_toast">Por favor, introduzca la contraseña actual.</string>
   <string name="crashlog_message">La aplicación finalizó inesperadamente. ¿Desea enviar un reporte de error?</string>
   <string name="crashlog_send_report">Enviar reporte</string>
index f071982..b9d0dfd 100644 (file)
     <string name="auth_not_found">Wrong path given</string>
     <string name="auth_internal">Internal server error, code %1$d</string>
     <string name="auth_wtf_reenter_URL">Unexpected state; please, enter the server URL again</string>
-    <string name="auth_expired_oauth_token_toast">Your authorization expired.\nPlease, authorize again</string>
+    <string name="auth_expired_oauth_token_toast">Your authorization expired. Please, authorize again</string>
     <string name="auth_expired_basic_auth_toast">Please, enter the current password</string>
+    <string name="auth_expired_saml_sso_token_toast">Your session expired. Please connect again</string>
        <string name="auth_connecting_auth_server">Connecting to authentication server…</string>
        <string name="auth_follow_auth_server">Follow instructions above to get authenticated</string>
        <string name="auth_unsupported_auth_method">The server does not support this authentication method</string>    
index 138c860..bab98de 100644 (file)
@@ -85,6 +85,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     public static final String EXTRA_ACTION = "ACTION";\r
     public static final String EXTRA_ENFORCED_UPDATE = "ENFORCE_UPDATE";\r
 \r
+    private static final String KEY_AUTH_MESSAGE_VISIBILITY = "AUTH_MESSAGE_VISIBILITY";\r
+    private static final String KEY_AUTH_MESSAGE_TEXT = "AUTH_MESSAGE_TEXT";\r
     private static final String KEY_HOST_URL_TEXT = "HOST_URL_TEXT";\r
     private static final String KEY_OC_VERSION = "OC_VERSION";\r
     private static final String KEY_ACCOUNT = "ACCOUNT";\r
@@ -116,7 +118,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     private String mHostBaseUrl;\r
     private OwnCloudVersion mDiscoveredVersion;\r
 \r
-    private int mServerStatusText, mServerStatusIcon;\r
+    private String mAuthMessageText;\r
+    private int mAuthMessageVisibility, mServerStatusText, mServerStatusIcon;\r
     private boolean mServerIsChecked, mServerIsValid, mIsSslConn;\r
     private int mAuthStatusText, mAuthStatusIcon;    \r
     private TextView mAuthStatusLayout;\r
@@ -134,6 +137,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     private byte mAction;\r
     private Account mAccount;\r
 \r
+    private TextView mAuthMessage;\r
+    \r
     private EditText mHostUrlInput;\r
     private boolean mHostUrlInputEnabled;\r
     private View mRefreshButton;\r
@@ -168,6 +173,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         /// set view and get references to view elements\r
         setContentView(R.layout.account_setup);\r
+        mAuthMessage = (TextView) findViewById(R.id.auth_message);\r
         mHostUrlInput = (EditText) findViewById(R.id.hostUrlInput);\r
         mHostUrlInput.setText(getString(R.string.server_url));  // valid although R.string.server_url is an empty string\r
         mUsernameInput = (EditText) findViewById(R.id.account_username);\r
@@ -209,6 +215,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         if (savedInstanceState == null) {\r
             /// connection state and info\r
+            mAuthMessageVisibility = View.GONE;\r
             mServerStatusText = mServerStatusIcon = 0;\r
             mServerIsValid = false;\r
             mServerIsChecked = false;\r
@@ -224,6 +231,9 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 }\r
                 mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL));\r
                 mHostUrlInput.setText(mHostBaseUrl);\r
+                String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));\r
+                mUsernameInput.setText(userName);\r
+                mAccountNameInput.setText(userName);\r
             }\r
             initAuthorizationMethod();  // checks intent and setup.xml to determine mCurrentAuthorizationMethod\r
             mJustCreated = true;\r
@@ -234,6 +244,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             \r
         } else {\r
             /// connection state and info\r
+            mAuthMessageVisibility = savedInstanceState.getInt(KEY_AUTH_MESSAGE_VISIBILITY);\r
+            mAuthMessageText = savedInstanceState.getString(KEY_AUTH_MESSAGE_TEXT);\r
             mServerIsValid = savedInstanceState.getBoolean(KEY_SERVER_VALID);\r
             mServerIsChecked = savedInstanceState.getBoolean(KEY_SERVER_CHECKED);\r
             mServerStatusText = savedInstanceState.getInt(KEY_SERVER_STATUS_TEXT);\r
@@ -271,6 +283,12 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         }\r
 \r
+        if (mAuthMessageVisibility== View.VISIBLE) {\r
+            showAuthMessage(mAuthMessageText);\r
+        }\r
+        else {\r
+            hideAuthMessage();\r
+        }\r
         adaptViewAccordingToAuthenticationMethod();\r
         showServerStatus();\r
         showAuthStatus();\r
@@ -282,6 +300,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mUsernameInput.setEnabled(false);\r
             mUsernameInput.setFocusable(false);\r
             mOAuth2Check.setVisibility(View.GONE);\r
+            mAccountNameInput.setEnabled(false);\r
+            mAccountNameInput.setFocusable(false);\r
         }\r
         \r
         //if (mServerIsChecked && !mServerIsValid && mRefreshButtonEnabled) showRefreshButton();\r
@@ -381,6 +401,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         super.onSaveInstanceState(outState);\r
 \r
         /// connection state and info\r
+        outState.putInt(KEY_AUTH_MESSAGE_VISIBILITY, mAuthMessage.getVisibility());\r
+        outState.putString(KEY_AUTH_MESSAGE_TEXT, mAuthMessage.getText().toString());\r
         outState.putInt(KEY_SERVER_STATUS_TEXT, mServerStatusText);\r
         outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon);\r
         outState.putBoolean(KEY_SERVER_VALID, mServerIsValid);\r
@@ -435,10 +457,16 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     protected void onResume() {\r
         super.onResume();\r
         if (mAction == ACTION_UPDATE_TOKEN && mJustCreated && getIntent().getBooleanExtra(EXTRA_ENFORCED_UPDATE, false)) {\r
-            if (mOAuth2Check.isChecked())\r
-                Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show();\r
-            else\r
-                Toast.makeText(this, R.string.auth_expired_basic_auth_toast, Toast.LENGTH_LONG).show();\r
+            if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(mCurrentAuthTokenType)) {\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 (AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType)) {\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
+                //Toast.makeText(this, R.string.auth_expired_basic_auth_toast, Toast.LENGTH_LONG).show();\r
+                showAuthMessage(getString(R.string.auth_expired_basic_auth_toast));\r
+            }\r
         }\r
 \r
         if (mNewCapturedUriFromOAuth2Redirection != null) {\r
@@ -632,6 +660,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             return;\r
         }\r
 \r
+        hideAuthMessage();\r
         if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(mCurrentAuthTokenType)) {\r
             startOauthorization();\r
         } else if (AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mCurrentAuthTokenType)) { \r
@@ -1117,6 +1146,9 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString());\r
         }\r
         setAccountAuthenticatorResult(response);\r
+        \r
+        // Sync Account\r
+        syncAccount();\r
     }\r
 \r
 \r
@@ -1184,9 +1216,10 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         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, AccountAuthenticator.AUTHORITY, bundle);\r
+        syncAccount();\r
+//        Bundle bundle = new Bundle();\r
+//        bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);\r
+//        ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle);\r
     }\r
 \r
 \r
@@ -1518,5 +1551,24 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     }\r
     \r
     \r
+    /** Show auth_message \r
+     * \r
+     * @param message\r
+     */\r
+    private void showAuthMessage(String message) {\r
+       mAuthMessage.setVisibility(View.VISIBLE);\r
+       mAuthMessage.setText(message);\r
+    }\r
+    \r
+    private void hideAuthMessage() {\r
+        mAuthMessage.setVisibility(View.GONE);\r
+    }\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, AccountAuthenticator.AUTHORITY, bundle);\r
+    }\r
 }\r
index 02a8a45..0afcf6a 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
@@ -463,7 +464,9 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
             Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
-            boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED);
+            boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
+                                                ((downloadResult.isTemporalRedirection() || downloadResult.isIdPRedirection())
+                                                        && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mDownloadClient.getAuthTokenType())));
             if (needsToUpdateCredentials) {
                 // let the user update credentials with one click
                 Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
index e9f445a..4863840 100644 (file)
@@ -579,7 +579,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream());
             }
 
-            result = new RemoteOperationResult(isMultiStatus, status);
+            result = new RemoteOperationResult(isMultiStatus, status, propfind.getResponseHeaders());
             Log_OC.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
                     + result.getLogMessage());
 
@@ -791,7 +791,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             Notification finalNotification = new Notification(R.drawable.icon,
                     getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
-            if (uploadResult.getCode() == ResultCode.UNAUTHORIZED) {
+            String content = null;
+            
+            boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
+                    ((uploadResult.isTemporalRedirection() || uploadResult.isIdPRedirection())
+                            && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mUploadClient.getAuthTokenType())));
+            if (needsToUpdateCredentials) {
                 // let the user update credentials with one click
                 Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
                 updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount());
@@ -801,62 +806,65 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                 updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
                 finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
+                content =  String.format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
+                finalNotification.setLatestEventInfo(getApplicationContext(),
+                        getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
                 mUploadClient = null;   // grant that future retries on the same account will get the fresh credentials
             } else {
                 // TODO put something smart in the contentIntent below
-                finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
-            }
+            //    finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+            //}
             
-            String content = null;
-            if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
-                    || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
-                // TODO we need a class to provide error messages for the users
-                // from a RemoteOperationResult and a RemoteOperation
-                content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(),
-                        getString(R.string.app_name));
-            } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
-                content = getString(R.string.failed_upload_quota_exceeded_text);
-            } else {
-                content = String
-                        .format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
-            }
+                if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
+                        || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
+                    // TODO we need a class to provide error messages for the users
+                    // from a RemoteOperationResult and a RemoteOperation
+                    content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(),
+                            getString(R.string.app_name));
+                } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+                    content = getString(R.string.failed_upload_quota_exceeded_text);
+                } else {
+                    content = String
+                            .format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
+                }
 
-            // we add only for instant-uploads the InstantUploadActivity and the
-            // db entry
-            Intent detailUploadIntent = null;
-            if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) {
-                detailUploadIntent = new Intent(this, InstantUploadActivity.class);
-                detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
-            } else {
-                detailUploadIntent = new Intent(this, FailedUploadActivity.class);
-                detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
-            }
-            finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
-                    (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT
-                            | PendingIntent.FLAG_ONE_SHOT);
-
-            if (upload.isInstant()) {
-                DbHandler db = null;
-                try {
-                    db = new DbHandler(this.getBaseContext());
-                    String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
-                    Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
-                    if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
-                        message = getString(R.string.failed_upload_quota_exceeded_text);
-                    }
-                    if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
-                            message) == 0) {
-                        db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
-                    }
-                } finally {
-                    if (db != null) {
-                        db.close();
+                // we add only for instant-uploads the InstantUploadActivity and the
+                // db entry
+                Intent detailUploadIntent = null;
+                if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) {
+                    detailUploadIntent = new Intent(this, InstantUploadActivity.class);
+                    detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
+                } else {
+                    detailUploadIntent = new Intent(this, FailedUploadActivity.class);
+                    detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
+                }
+                finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
+                        (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT
+                        | PendingIntent.FLAG_ONE_SHOT);
+
+                if (upload.isInstant()) {
+                    DbHandler db = null;
+                    try {
+                        db = new DbHandler(this.getBaseContext());
+                        String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
+                        Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
+                        if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+                            message = getString(R.string.failed_upload_quota_exceeded_text);
+                        }
+                        if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
+                                message) == 0) {
+                            db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
+                        }
+                    } finally {
+                        if (db != null) {
+                            db.close();
+                        }
                     }
                 }
             }
             finalNotification.setLatestEventInfo(getApplicationContext(),
                     getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
-
+            
             mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
         }
 
index 17abf6f..75aed4a 100644 (file)
@@ -32,6 +32,7 @@ import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 
 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.protocol.Protocol;
 import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
@@ -90,13 +91,15 @@ public class OwnCloudClientUtils {
         //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
        
         Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        WebdavClient client = createOwnCloudClient(uri, appContext, true);
         AccountManager am = AccountManager.get(appContext);
-        if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) {    // TODO avoid a call to getUserData here
+        boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
+        boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null;
+        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
+        if (isOauth2) {    
             String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
             client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
         
-        } else if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null) {    // TODO avoid a call to getUserData here
+        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
             String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE, false);
             client.setSsoSessionCookie(accessToken);
             
@@ -113,16 +116,19 @@ public class OwnCloudClientUtils {
     
     public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
         Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        WebdavClient client = createOwnCloudClient(uri, appContext, true);
         AccountManager am = AccountManager.get(appContext);
-        if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) {    // TODO avoid a call to getUserData here
+        boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
+        boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null;
+        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
+        
+        if (isOauth2) {    // TODO avoid a call to getUserData here
             AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null);
             Bundle result = future.getResult();
             String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
             if (accessToken == null) throw new AuthenticatorException("WTF!");
             client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
 
-        } else if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null) {    // TODO avoid a call to getUserData here
+        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
             AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE, null, currentActivity, null, null);
             Bundle result = future.getResult();
             String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
index 697c154..02e1ad0 100644 (file)
@@ -68,6 +68,9 @@ public class ChunkedUploadFileOperation extends UploadFileOperation {
             String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
             long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
             for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
+                if (mPutMethod != null) {
+                    mPutMethod.releaseConnection();    // let the connection available for other methods
+                }
                 mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
                 mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
                 ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
index 03c6868..1a38cdb 100644 (file)
@@ -77,7 +77,7 @@ public class CreateFolderOperation extends RemoteOperation {
                 mStorageManager.saveFile(newDir);
             }
 
-            result = new RemoteOperationResult(mkcol.succeeded(), status);
+            result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders());
             Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
             client.exhaustResponse(mkcol.getResponseBodyAsStream());
                 
index 5745b97..02098b8 100644 (file)
@@ -58,6 +58,7 @@ public class DownloadFileOperation extends RemoteOperation {
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     private long mModificationTimestamp = 0;
+    private GetMethod mGet;
 
     
     public DownloadFileOperation(Account account, OCFile file) {
@@ -154,7 +155,7 @@ public class DownloadFileOperation extends RemoteOperation {
             if (!moved)
                 result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
             else
-                result = new RemoteOperationResult(isSuccess(status), status);
+                result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null));
             Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
             
         } catch (Exception e) {
@@ -174,15 +175,15 @@ public class DownloadFileOperation extends RemoteOperation {
     protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException {
         int status = -1;
         boolean savedFile = false;
-        GetMethod get = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()));
+        mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()));
         Iterator<OnDatatransferProgressListener> it = null;
         
         FileOutputStream fos = null;
         try {
-            status = client.executeMethod(get);
+            status = client.executeMethod(mGet);
             if (isSuccess(status)) {
                 targetFile.createNewFile();
-                BufferedInputStream bis = new BufferedInputStream(get.getResponseBodyAsStream());
+                BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
                 fos = new FileOutputStream(targetFile);
                 long transferred = 0;
 
@@ -191,7 +192,7 @@ public class DownloadFileOperation extends RemoteOperation {
                 while ((readResult = bis.read(bytes)) != -1) {
                     synchronized(mCancellationRequested) {
                         if (mCancellationRequested.get()) {
-                            get.abort();
+                            mGet.abort();
                             throw new OperationCancelledException();
                         }
                     }
@@ -205,14 +206,14 @@ public class DownloadFileOperation extends RemoteOperation {
                     }
                 }
                 savedFile = true;
-                Header modificationTime = get.getResponseHeader("Last-Modified");
+                Header modificationTime = mGet.getResponseHeader("Last-Modified");
                 if (modificationTime != null) {
                     Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue());
                     mModificationTimestamp = (d != null) ? d.getTime() : 0;
                 }
                 
             } else {
-                client.exhaustResponse(get.getResponseBodyAsStream());
+                client.exhaustResponse(mGet.getResponseBodyAsStream());
             }
                 
         } finally {
@@ -220,7 +221,7 @@ public class DownloadFileOperation extends RemoteOperation {
             if (!savedFile && targetFile.exists()) {
                 targetFile.delete();
             }
-            get.releaseConnection();    // let the connection available for other methods
+            mGet.releaseConnection();    // let the connection available for other methods
         }
         return status;
     }
index 6d43caf..5d46804 100644 (file)
@@ -80,12 +80,12 @@ public class OAuth2GetAccessToken extends RemoteOperation {
                         result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
                     
                     } else {
-                        result = new RemoteOperationResult(true, status);
+                        result = new RemoteOperationResult(true, status, postMethod.getResponseHeaders());
                     }
                     
                 } else {
                     client.exhaustResponse(postMethod.getResponseBodyAsStream());
-                    result = new RemoteOperationResult(false, status);
+                    result = new RemoteOperationResult(false, status, postMethod.getResponseHeaders());
                 }
             }
             
index 4982c66..d95b305 100644 (file)
@@ -80,7 +80,7 @@ public class OwnCloudServerCheckOperation extends RemoteOperation {
                 }
                 
             } else {
-                mLatestResult = new RemoteOperationResult(false, status);
+                mLatestResult = new RemoteOperationResult(false, status, get.getResponseHeaders());
             }
 
         } catch (JSONException e) {
index 9afb856..0d7e6ec 100644 (file)
@@ -242,18 +242,27 @@ public abstract class RemoteOperation implements Runnable {
                 result = run(mClient);
         
             repeat = false;
-            if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {
-                /// fail due to lack of authorization in an operation performed in foreground
-                AccountManager am = AccountManager.get(mContext);
+            if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() &&
+                    (result.getCode() == ResultCode.UNAUTHORIZED || result.isTemporalRedirection() || result.isIdPRedirection())) {
+                /// possible fail due to lack of authorization in an operation performed in foreground
                 Credentials cred = mClient.getCredentials();
-                if (cred instanceof BearerCredentials) {
-                    am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
-                } else {
-                    am.clearPassword(mAccount);
+                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(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
+                    } else if (samlBasedSsoAuthorization ) {
+                        am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_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;
                 }
-                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);
         
index 5701476..ef46c96 100644 (file)
@@ -99,7 +99,7 @@ public class RemoteOperationResult implements Serializable {
         mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
     }
 
-    public RemoteOperationResult(boolean success, int httpCode) {
+    private RemoteOperationResult(boolean success, int httpCode) {
         mSuccess = success;
         mHttpCode = httpCode;
 
index 8348b72..9dabfaf 100644 (file)
@@ -88,7 +88,7 @@ public class RemoveFileOperation extends RemoteOperation {
                 }
             }
             delete.getResponseBodyAsString();   // exhaust the response, although not interesting
-            result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status);
+            result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
             Log_OC.i(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage());
             
         } catch (Exception e) {
index 1c636fb..fddb849 100644 (file)
@@ -136,7 +136,7 @@ public class RenameFileOperation extends RemoteOperation {
             }
             
             move.getResponseBodyAsString(); // exhaust response, although not interesting
-            result = new RemoteOperationResult(move.succeeded(), status);
+            result = new RemoteOperationResult(move.succeeded(), status, move.getResponseHeaders());
             Log_OC.i(TAG, "Rename " + mFile.getRemotePath() + " to " + mNewRemotePath + ": " + result.getLogMessage());
             
         } catch (Exception e) {
index b0f2ce2..5be116b 100644 (file)
@@ -101,7 +101,7 @@ public class SynchronizeFileOperation extends RemoteOperation {
                         
                     } else {
                         client.exhaustResponse(propfind.getResponseBodyAsStream());
-                        result = new RemoteOperationResult(false, status);
+                        result = new RemoteOperationResult(false, status, propfind.getResponseHeaders());
                     }
                 }
                 
index aaca935..67c7389 100644 (file)
@@ -243,14 +243,10 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                     result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);   // should be different result, but will do the job
                             
                 } else {
-                    result = new RemoteOperationResult(true, status);
-                    Header hCookie = query.getResponseHeader("Cookie");
-                    if (hCookie != null) {
-                        Log_OC.d(TAG, "PROPFIND cookie: " + hCookie.getValue());
-                    }
+                    result = new RemoteOperationResult(true, status, query.getResponseHeaders());
                 }
             } else {
-                result = new RemoteOperationResult(false, status);
+                result = new RemoteOperationResult(false, status, query.getResponseHeaders());
             }
             
             
index 1b56bfb..1643377 100644 (file)
@@ -65,7 +65,7 @@ public class UpdateOCVersionOperation extends RemoteOperation {
             int status = client.executeMethod(get);
             if (status != HttpStatus.SC_OK) {
                 client.exhaustResponse(get.getResponseBodyAsStream());
-                result = new RemoteOperationResult(false, status);
+                result = new RemoteOperationResult(false, status, get.getResponseHeaders());
                 
             } else {
                 String response = get.getResponseBodyAsString();
index 2c891be..cae1f17 100644 (file)
@@ -304,7 +304,7 @@ public class UploadFileOperation extends RemoteOperation {
                 }
             }
 
-            result = new RemoteOperationResult(isSuccess(status), status);
+            result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
 
         } catch (Exception e) {
             // TODO something cleaner with cancellations
index 8653fe7..4103dbf 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.jackrabbit.webdav.DavException;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -223,7 +224,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             sendStickyBroadcast(true, remotePath, null);
             
         } else {
-            if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED) {
+            if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
+                    ((result.isTemporalRedirection() || result.isIdPRedirection()) && getClient().getSsoSessionCookie() != null)) {
                 mSyncResult.stats.numAuthExceptions++;
                 
             } else if (result.getException() instanceof DavException) {
@@ -304,7 +306,12 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private void notifyFailedSynchronization() {
         Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
-        boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED);
+        boolean needsToUpdateCredentials = (mLastFailedResult != null && 
+                                             (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
+                                                ((mLastFailedResult.isTemporalRedirection() || mLastFailedResult.isIdPRedirection())
+                                                        && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))
+                                             )
+                                           );
         // TODO put something smart in the contentIntent below for all the possible errors
         notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
         if (needsToUpdateCredentials) {
index 570ebb8..dd48408 100644 (file)
@@ -41,9 +41,11 @@ import org.apache.http.params.CoreProtocolPNames;
 
 import com.owncloud.android.Log_OC;
 
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.network.BearerAuthScheme;
 import com.owncloud.android.network.BearerCredentials;
 
+import android.accounts.AccountAuthenticatorActivity;
 import android.net.Uri;
 
 public class WebdavClient extends HttpClient {
@@ -51,6 +53,7 @@ public class WebdavClient extends HttpClient {
     private Credentials mCredentials;
     private boolean mFollowRedirects;
     private String mSsoSessionCookie;
+    private String mAuthTokenType;
     final private static String TAG = "WebdavClient";
     public static final String USER_AGENT = "Android-ownCloud";
     
@@ -66,6 +69,7 @@ public class WebdavClient extends HttpClient {
         getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
         mFollowRedirects = true;
         mSsoSessionCookie = null;
+        mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
     }
 
     public void setBearerCredentials(String accessToken) {
@@ -78,6 +82,7 @@ public class WebdavClient extends HttpClient {
         mCredentials = new BearerCredentials(accessToken);
         getState().setCredentials(AuthScope.ANY, mCredentials);
         mSsoSessionCookie = null;
+        mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN;
     }
 
     public void setBasicCredentials(String username, String password) {
@@ -89,6 +94,7 @@ public class WebdavClient extends HttpClient {
         mCredentials = new UsernamePasswordCredentials(username, password);
         getState().setCredentials(AuthScope.ANY, mCredentials);
         mSsoSessionCookie = null;
+        mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
     }
     
     public void setSsoSessionCookie(String accessToken) {
@@ -96,6 +102,7 @@ public class WebdavClient extends HttpClient {
         getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
         mSsoSessionCookie = accessToken;
         mCredentials = null;
+        mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE;
     }
     
     
@@ -206,9 +213,17 @@ public class WebdavClient extends HttpClient {
     public final Credentials getCredentials() {\r
         return mCredentials;\r
     }
+    
+    public final String getSsoSessionCookie() {
+        return mSsoSessionCookie;
+    }
 
     public void setFollowRedirects(boolean followRedirects) {
         mFollowRedirects = followRedirects;
     }
 
+    public String getAuthTokenType() {
+        return mAuthTokenType;
+    }
+
 }