2  *   ownCloud Android client application 
   4  *   Copyright (C) 2012  Bartek Przybylski 
   5  *   Copyright (C) 2015 ownCloud Inc. 
   7  *   This program is free software: you can redistribute it and/or modify 
   8  *   it under the terms of the GNU General Public License version 2, 
   9  *   as published by the Free Software Foundation. 
  11  *   This program is distributed in the hope that it will be useful, 
  12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  14  *   GNU General Public License for more details. 
  16  *   You should have received a copy of the GNU General Public License 
  17  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  21 package com
.owncloud
.android
.authentication
; 
  23 import java
.util
.Locale
; 
  25 import com
.owncloud
.android
.MainApp
; 
  26 import com
.owncloud
.android
.lib
.common
.accounts
.AccountTypeUtils
; 
  27 import com
.owncloud
.android
.lib
.common
.accounts
.AccountUtils
.Constants
; 
  28 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
; 
  29 import com
.owncloud
.android
.lib
.resources
.status
.OwnCloudVersion
; 
  31 import android
.accounts
.Account
; 
  32 import android
.accounts
.AccountManager
; 
  33 import android
.content
.Context
; 
  34 import android
.content
.SharedPreferences
; 
  35 import android
.net
.Uri
; 
  36 import android
.preference
.PreferenceManager
; 
  38 public class AccountUtils 
{ 
  40     private static final String TAG 
= AccountUtils
.class.getSimpleName(); 
  42     public static final String WEBDAV_PATH_4_0_AND_LATER 
= "/remote.php/webdav"; 
  43     private static final String ODAV_PATH 
= "/remote.php/odav"; 
  44     private static final String SAML_SSO_PATH 
= "/remote.php/webdav"; 
  45     public static final String STATUS_PATH 
= "/status.php"; 
  47     public static final int ACCOUNT_VERSION 
= 1; 
  50      * Can be used to get the currently selected ownCloud {@link Account} in the 
  51      * application preferences. 
  53      * @param   context     The current application {@link Context} 
  54      * @return              The ownCloud {@link Account} currently saved in preferences, or the first  
  55      *                      {@link Account} available, if valid (still registered in the system as ownCloud  
  56      *                      account). If none is available and valid, returns null. 
  58     public static Account 
getCurrentOwnCloudAccount(Context context
) { 
  59         Account
[] ocAccounts 
= AccountManager
.get(context
).getAccountsByType( 
  60                 MainApp
.getAccountType()); 
  61         Account defaultAccount 
= null
; 
  63         SharedPreferences appPreferences 
= PreferenceManager
 
  64                 .getDefaultSharedPreferences(context
); 
  65         String accountName 
= appPreferences
 
  66                 .getString("select_oc_account", null
); 
  68         // account validation: the saved account MUST be in the list of ownCloud Accounts known by the AccountManager 
  69         if (accountName 
!= null
) { 
  70             for (Account account 
: ocAccounts
) { 
  71                 if (account
.name
.equals(accountName
)) { 
  72                     defaultAccount 
= account
; 
  78         if (defaultAccount 
== null 
&& ocAccounts
.length 
!= 0) { 
  79             // take first account as fallback 
  80             defaultAccount 
= ocAccounts
[0]; 
  83         return defaultAccount
; 
  87     public static boolean exists(Account account
, Context context
) { 
  88         Account
[] ocAccounts 
= AccountManager
.get(context
).getAccountsByType( 
  89                 MainApp
.getAccountType()); 
  91         if (account 
!= null 
&& account
.name 
!= null
) { 
  92             int lastAtPos 
= account
.name
.lastIndexOf("@"); 
  93             String hostAndPort 
= account
.name
.substring(lastAtPos 
+ 1); 
  94             String username 
= account
.name
.substring(0, lastAtPos
); 
  95             String otherHostAndPort
, otherUsername
; 
  96             Locale currentLocale 
= context
.getResources().getConfiguration().locale
; 
  97             for (Account otherAccount 
: ocAccounts
) { 
  98                 lastAtPos 
= otherAccount
.name
.lastIndexOf("@"); 
  99                 otherHostAndPort 
= otherAccount
.name
.substring(lastAtPos 
+ 1); 
 100                 otherUsername 
= otherAccount
.name
.substring(0, lastAtPos
); 
 101                 if (otherHostAndPort
.equals(hostAndPort
) && 
 102                         otherUsername
.toLowerCase(currentLocale
). 
 103                             equals(username
.toLowerCase(currentLocale
))) { 
 112     public static boolean setCurrentOwnCloudAccount(Context context
, String accountName
) { 
 113         boolean result 
= false
; 
 114         if (accountName 
!= null
) { 
 115             Account
[] ocAccounts 
= AccountManager
.get(context
).getAccountsByType( 
 116                     MainApp
.getAccountType()); 
 118             for (Account account 
: ocAccounts
) { 
 119                 found 
= (account
.name
.equals(accountName
)); 
 121                     SharedPreferences
.Editor appPrefs 
= PreferenceManager
 
 122                             .getDefaultSharedPreferences(context
).edit(); 
 123                     appPrefs
.putString("select_oc_account", accountName
); 
 135      * Returns the proper URL path to access the WebDAV interface of an ownCloud server, 
 136      * according to its version and the authorization method used. 
 138      * @param   version         Version of ownCloud server. 
 139      * @param   authTokenType   Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in 
 140      *                          {@link AccountAuthenticator}. 
 141      * @return                  WebDAV path for given OC version and authorization method, null if OC version 
 142      *                          is unknown; versions prior to ownCloud 4 are not supported anymore 
 144     public static String 
getWebdavPath(OwnCloudVersion version
, String authTokenType
) { 
 145         if (version 
!= null
) { 
 146             if (AccountTypeUtils
.getAuthTokenTypeAccessToken(MainApp
.getAccountType()).equals(authTokenType
)) { 
 149             if (AccountTypeUtils
.getAuthTokenTypeSamlSessionCookie(MainApp
.getAccountType()).equals(authTokenType
)) { 
 150                 return SAML_SSO_PATH
; 
 152             return WEBDAV_PATH_4_0_AND_LATER
; 
 159      * Update the accounts in AccountManager to meet the current version of accounts expected by the app, if needed. 
 161      * Introduced to handle a change in the structure of stored account names needed to allow different OC servers 
 162      * in the same domain, but not in the same path. 
 164      * @param   context     Used to access the AccountManager. 
 166     public static void updateAccountVersion(Context context
) { 
 167         Account currentAccount 
= AccountUtils
.getCurrentOwnCloudAccount(context
); 
 168         AccountManager accountMgr 
= AccountManager
.get(context
); 
 170         if ( currentAccount 
!= null 
) { 
 171             String currentAccountVersion 
= accountMgr
.getUserData(currentAccount
, Constants
.KEY_OC_ACCOUNT_VERSION
); 
 173             if (currentAccountVersion 
== null
) { 
 174                 Log_OC
.i(TAG
, "Upgrading accounts to account version #" + ACCOUNT_VERSION
); 
 175                 Account
[] ocAccounts 
= accountMgr
.getAccountsByType(MainApp
.getAccountType()); 
 176                 String serverUrl
, username
, newAccountName
, password
; 
 178                 for (Account account 
: ocAccounts
) { 
 179                     // build new account name 
 180                     serverUrl 
= accountMgr
.getUserData(account
, Constants
.KEY_OC_BASE_URL
); 
 181                     username 
= account
.name
.substring(0, account
.name
.lastIndexOf('@')); 
 182                     newAccountName 
= com
.owncloud
.android
.lib
.common
.accounts
.AccountUtils
. 
 183                             buildAccountName(Uri
.parse(serverUrl
), username
); 
 185                     // migrate to a new account, if needed 
 186                     if (!newAccountName
.equals(account
.name
)) { 
 187                         Log_OC
.d(TAG
, "Upgrading " + account
.name 
+ " to " + newAccountName
); 
 189                         // create the new account 
 190                         newAccount 
= new Account(newAccountName
, MainApp
.getAccountType()); 
 191                         password 
= accountMgr
.getPassword(account
); 
 192                         accountMgr
.addAccountExplicitly(newAccount
, (password 
!= null
) ? password 
: "", null
); 
 195                         accountMgr
.setUserData(newAccount
, Constants
.KEY_OC_BASE_URL
, serverUrl
); 
 197                         // copy server version 
 198                         accountMgr
.setUserData( 
 200                                 Constants
.KEY_OC_VERSION
, 
 201                                 accountMgr
.getUserData(account
, Constants
.KEY_OC_VERSION
) 
 205                         accountMgr
.setUserData( 
 207                                 Constants
.KEY_COOKIES
, 
 208                                 accountMgr
.getUserData(account
, Constants
.KEY_COOKIES
) 
 211                         // copy type of authentication 
 212                         String isSamlStr 
= accountMgr
.getUserData(account
, Constants
.KEY_SUPPORTS_SAML_WEB_SSO
); 
 213                         boolean isSaml 
= "TRUE".equals(isSamlStr
); 
 215                             accountMgr
.setUserData(newAccount
, Constants
.KEY_SUPPORTS_SAML_WEB_SSO
, "TRUE"); 
 218                         String isOauthStr 
= accountMgr
.getUserData(account
, Constants
.KEY_SUPPORTS_OAUTH2
); 
 219                         boolean isOAuth 
= "TRUE".equals(isOauthStr
); 
 221                             accountMgr
.setUserData(newAccount
, Constants
.KEY_SUPPORTS_OAUTH2
, "TRUE"); 
 223                         /* TODO - study if it's possible to run this method in a background thread to copy the authToken 
 224                         if (isOAuth || isSaml) { 
 225                             accountMgr.setAuthToken(newAccount, mAuthTokenType, mAuthToken); 
 229                         // don't forget the account saved in preferences as the current one 
 230                         if (currentAccount
.name
.equals(account
.name
)) { 
 231                             AccountUtils
.setCurrentOwnCloudAccount(context
, newAccountName
); 
 234                         // remove the old account 
 235                         accountMgr
.removeAccount(account
, null
, null
); 
 236                             // will assume it succeeds, not a big deal otherwise 
 239                         // servers which base URL is in the root of their domain need no change 
 240                         Log_OC
.d(TAG
, account
.name 
+ " needs no upgrade "); 
 241                         newAccount 
= account
; 
 244                     // at least, upgrade account version 
 245                     Log_OC
.d(TAG
, "Setting version " + ACCOUNT_VERSION 
+ " to " + newAccountName
); 
 246                     accountMgr
.setUserData( 
 247                             newAccount
, Constants
.KEY_OC_ACCOUNT_VERSION
, Integer
.toString(ACCOUNT_VERSION
) 
 256     public static String 
trimWebdavSuffix(String url
) { 
 257         while(url
.endsWith("/")) { 
 258             url 
= url
.substring(0, url
.length() - 1); 
 260         int pos 
= url
.lastIndexOf(WEBDAV_PATH_4_0_AND_LATER
); 
 262             url 
= url
.substring(0, pos
); 
 265             pos 
= url
.lastIndexOf(ODAV_PATH
); 
 267                 url 
= url
.substring(0, pos
); 
 274      * Access the version of the OC server corresponding to an account SAVED IN THE ACCOUNTMANAGER 
 276      * @param   account     ownCloud account 
 277      * @return              Version of the OC server corresponding to account, according to the data saved 
 278      *                      in the system AccountManager 
 280     public static OwnCloudVersion 
getServerVersion(Account account
) { 
 281         OwnCloudVersion serverVersion 
= null
; 
 282         if (account 
!= null
) { 
 283             AccountManager accountMgr 
= AccountManager
.get(MainApp
.getAppContext()); 
 284             String serverVersionStr 
= accountMgr
.getUserData(account
, Constants
.KEY_OC_VERSION
); 
 285             if (serverVersionStr 
!= null
) { 
 286                 serverVersion 
= new OwnCloudVersion(serverVersionStr
); 
 289         return serverVersion
;