Merge branch 'develop' into refresh_folder_contents_when_browsed_into
authorDavid A. Velasco <dvelasco@solidgear.es>
Wed, 23 Oct 2013 15:35:07 +0000 (17:35 +0200)
committerDavid A. Velasco <dvelasco@solidgear.es>
Wed, 23 Oct 2013 15:35:07 +0000 (17:35 +0200)
15 files changed:
1  2 
res/values/strings.xml
src/com/owncloud/android/Uploader.java
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/db/ProviderMeta.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/operations/RemoteOperation.java
src/com/owncloud/android/providers/FileContentProvider.java
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncService.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/eu/alefzero/webdav/WebdavClient.java

diff --combined res/values/strings.xml
@@@ -1,7 -1,6 +1,6 @@@
  <?xml version="1.0" encoding="utf-8"?>
  <resources>
  
-     <string name="app_name">ownCloud</string>
      <string name="main_password">Password:</string>
      <string name="main_login">Username:</string>
      <string name="main_button_login">Login</string>
@@@ -27,6 -26,7 +26,7 @@@
      <string name="actionbar_see_details">Details</string>
      
      <string name="prefs_category_general">General</string>
+     <string name="prefs_category_more">More</string>
      <string name="prefs_add_session">Add new session</string>
      <string name="prefs_create_img_thumbnails">Create image thumbnails</string>
      <string name="prefs_select_oc_account">Select an account</string>
      <string name="prefs_log_title_history">Logging History</string>
      <string name="prefs_log_summary_history">This shows the recorded logs</string>
      <string name="prefs_log_delete_history_button">Delete History</string>
+     <string name="prefs_help">Help</string>
+     <string name="prefs_recommend">Recommend to a friend</string>
+     <string name="prefs_feedback">Feedback</string>
+     <string name="prefs_imprint">Imprint</string>
      
+       <string name="recommend_subject">"Try %1$s on your smartphone!"</string>
+       <string name="recommend_text">"I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s"</string>  
      <string name="auth_check_server">Check Server</string>
      <string name="auth_account_name">Account name</string>
      <string name="auth_host_url">Server address</string>
      <string name="sync_foreign_files_forgotten_ticker">Some local files were forgotten</string>
      <string name="sync_foreign_files_forgotten_content">%1$d files out of the %2$s directory could not be copied into</string>
      <string name="sync_foreign_files_forgotten_explanation">As of version 1.3.16, files uploaded from this device are copied into the local %1$s folder to prevent data loss when a single file is synced with multiple accounts.\n\nDue to this change, all files uploaded in previous versions of this app were copied into the %2$s folder. However, an error prevented the completion of this operation during account synchronization. You may either leave the file(s) as is and remove the link to %3$s, or move the file(s) into the %1$s directory and retain the link to %4$s.\n\nListed below are the local file(s), and the the remote file(s) in %5$s they were linked to.</string>
 +      <string name="sync_current_folder_was_removed">Folder %1$s does not exist anymore</string>    
      <string name="foreign_files_move">"Move all"</string>
      <string name="foreign_files_success">"All files were moved"</string>
      <string name="foreign_files_fail">"Some files could not be moved"</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>    
+       <string name="auth_unsupported_multiaccount">%1$s does not support multiple accounts</string>
      
      <string name="crashlog_message">Application terminated unexpectedly. Would you like to submit a crash report?</string>
      <string name="crashlog_send_report">Send report</string>
@@@ -55,6 -55,7 +55,6 @@@ import android.widget.SimpleAdapter
  import android.widget.Toast;
  
  import com.owncloud.android.authentication.AccountAuthenticator;
 -import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileUploader;
@@@ -76,7 -77,7 +76,7 @@@ public class Uploader extends ListActiv
      private ArrayList<Parcelable> mStreamsToUpload;
      private boolean mCreateDir;
      private String mUploadPath;
 -    private DataStorageManager mStorageManager;
 +    private FileDataStorageManager mStorageManager;
      private OCFile mFile;
  
      private final static int DIALOG_NO_ACCOUNT = 0;
@@@ -94,7 -95,7 +94,7 @@@
          mParents.add("");
          if (prepareStreamsToUpload()) {
              mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
-             Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE);
+             Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
              if (accounts.length == 0) {
                  Log_OC.i(TAG, "No ownCloud account is available");
                  showDialog(DIALOG_NO_ACCOUNT);
                          // Settings.ADD_ACCOUNT_SETTINGS
                          // and Settings.EXTRA_AUTHORITIES
                          Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
-                         intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTHORITY });
+                         intent.putExtra("authorities", new String[] { MainApp.getAuthTokenType() });
                          startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
                      } else {
                          // since in API7 there is no direct call for
              });
              return builder.create();
          case DIALOG_MULTIPLE_ACCOUNT:
-             CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE).length];
+             CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
              for (int i = 0; i < ac.length; ++i) {
-                 ac[i] = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[i].name;
+                 ac[i] = mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name;
              }
              builder.setTitle(R.string.common_choose_account);
              builder.setItems(ac, new OnClickListener() {
                  @Override
                  public void onClick(DialogInterface dialog, int which) {
-                     mAccount = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[which];
+                     mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
                      mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
                      populateDirectoryList();
                  }
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          // click on folder in the list
          Log_OC.d(TAG, "on item click");
 -        Vector<OCFile> tmpfiles = mStorageManager.getDirectoryContent(mFile);
 +        Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
          if (tmpfiles.size() <= 0) return;
          // filter on dirtype
          Vector<OCFile> files = new Vector<OCFile>();
          for (OCFile f : tmpfiles)
 -            if (f.isDirectory())
 +            if (f.isFolder())
                  files.add(f);
          if (files.size() < position) {
              throw new IndexOutOfBoundsException("Incorrect item selected");
              if (resultCode == RESULT_CANCELED) {
                  finish();
              }
-             Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.AUTH_TOKEN_TYPE);
+             Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAuthTokenType());
              if (accounts.length == 0) {
                  showDialog(DIALOG_NO_ACCOUNT);
              } else {
          
          mFile = mStorageManager.getFileByPath(full_path);
          if (mFile != null) {
 -            Vector<OCFile> files = mStorageManager.getDirectoryContent(mFile);
 +            Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
              List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
              for (OCFile f : files) {
                  HashMap<String, Object> h = new HashMap<String, Object>();
 -                if (f.isDirectory()) {
 +                if (f.isFolder()) {
                      h.put("dirname", f.getFileName());
                      data.add(h);
                  }
@@@ -20,13 -20,13 +20,13 @@@ package com.owncloud.android.datamodel
  
  import java.io.File;
  import java.util.ArrayList;
 +import java.util.Collection;
  import java.util.Collections;
  import java.util.Iterator;
 -import java.util.List;
  import java.util.Vector;
  
  import com.owncloud.android.Log_OC;
- import com.owncloud.android.db.ProviderMeta;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
  import com.owncloud.android.utils.FileStorageUtils;
  
@@@ -35,62 -35,33 +35,62 @@@ import android.content.ContentProviderC
  import android.content.ContentProviderOperation;
  import android.content.ContentProviderResult;
  import android.content.ContentResolver;
 +import android.content.ContentUris;
  import android.content.ContentValues;
  import android.content.OperationApplicationException;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.RemoteException;
  
 -public class FileDataStorageManager implements DataStorageManager {
 +public class FileDataStorageManager {
 +
 +    public static final int ROOT_PARENT_ID = 0;
  
      private ContentResolver mContentResolver;
 -    private ContentProviderClient mContentProvider;
 +    private ContentProviderClient mContentProviderClient;
      private Account mAccount;
  
 -    private static String TAG = "FileDataStorageManager";
 +    private static String TAG = FileDataStorageManager.class.getSimpleName();
  
 +    
      public FileDataStorageManager(Account account, ContentResolver cr) {
 -        mContentProvider = null;
 +        mContentProviderClient = null;
          mContentResolver = cr;
          mAccount = account;
      }
  
      public FileDataStorageManager(Account account, ContentProviderClient cp) {
 -        mContentProvider = cp;
 +        mContentProviderClient = cp;
          mContentResolver = null;
          mAccount = account;
      }
  
 -    @Override
 +    
 +    public void setAccount(Account account) {
 +        mAccount = account;
 +    }
 +
 +    public Account getAccount() {
 +        return mAccount;
 +    }
 +
 +    public void setContentResolver(ContentResolver cr) {
 +        mContentResolver = cr;
 +    }
 +
 +    public ContentResolver getContentResolver() {
 +        return mContentResolver;
 +    }
 +
 +    public void setContentProviderClient(ContentProviderClient cp) {
 +        mContentProviderClient = cp;
 +    }
 +
 +    public ContentProviderClient getContentProviderClient() {
 +        return mContentProviderClient;
 +    }
 +    
 +
      public OCFile getFileByPath(String path) {
          Cursor c = getCursorForValue(ProviderTableMeta.FILE_PATH, path);
          OCFile file = null;
              file = createFileInstance(c);
          }
          c.close();
 -        if (file == null && OCFile.PATH_SEPARATOR.equals(path)) {
 +        if (file == null && OCFile.ROOT_PATH.equals(path)) {
              return createRootDir(); // root should always exist
          }
          return file;
      }
  
  
 -    private OCFile createRootDir() {
 -        OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
 -        file.setMimetype("DIR");
 -        file.setParentId(DataStorageManager.ROOT_PARENT_ID);
 -        saveFile(file);
 -        return file;
 -    }
 -
 -    @Override
      public OCFile getFileById(long id) {
          Cursor c = getCursorForValue(ProviderTableMeta._ID, String.valueOf(id));
          OCFile file = null;
          return file;
      }
  
 -    @Override
      public boolean fileExists(long id) {
          return fileExists(ProviderTableMeta._ID, String.valueOf(id));
      }
  
 -    @Override
      public boolean fileExists(String path) {
          return fileExists(ProviderTableMeta.FILE_PATH, path);
      }
  
 -    @Override
 +    
 +    public Vector<OCFile> getFolderContent(OCFile f) {
 +        if (f != null && f.isFolder() && f.getFileId() != -1) {
 +            return getFolderContent(f.getFileId());
 +
 +        } else {
 +            return new Vector<OCFile>();
 +        }
 +    }
 +    
 +    
 +    public Vector<OCFile> getFolderImages(OCFile folder) {
 +        Vector<OCFile> ret = new Vector<OCFile>(); 
 +        if (folder != null) {
 +            // TODO better implementation, filtering in the access to database (if possible) instead of here 
 +            Vector<OCFile> tmp = getFolderContent(folder);
 +            OCFile current = null; 
 +            for (int i=0; i<tmp.size(); i++) {
 +                current = tmp.get(i);
 +                if (current.isImage()) {
 +                    ret.add(current);
 +                }
 +            }
 +        }
 +        return ret;
 +    }
 +
 +    
      public boolean saveFile(OCFile file) {
          boolean overriden = false;
          ContentValues cv = new ContentValues();
          cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
          cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
          cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
 -        if (file.getParentId() != 0)
 +        //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
              cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
          cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
 -        if (!file.isDirectory())
 +        if (!file.isFolder())
              cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
          cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
          cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
          cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
          cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
 +        cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  
          boolean sameRemotePath = fileExists(file.getRemotePath());
 -        boolean changesSizeOfAncestors = false;
          if (sameRemotePath ||
                  fileExists(file.getFileId())        ) {           // for renamed files; no more delete and create
  
              } else {
                  oldFile = getFileById(file.getFileId());
              }
 -            changesSizeOfAncestors = (oldFile.getFileLength() != file.getFileLength());
  
              overriden = true;
              if (getContentResolver() != null) {
                          new String[] { String.valueOf(file.getFileId()) });
              } else {
                  try {
 -                    getContentProvider().update(ProviderTableMeta.CONTENT_URI,
 +                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI,
                              cv, ProviderTableMeta._ID + "=?",
                              new String[] { String.valueOf(file.getFileId()) });
                  } catch (RemoteException e) {
                  }
              }
          } else {
 -            changesSizeOfAncestors = true;
              Uri result_uri = null;
              if (getContentResolver() != null) {
                  result_uri = getContentResolver().insert(
                          ProviderTableMeta.CONTENT_URI_FILE, cv);
              } else {
                  try {
 -                    result_uri = getContentProvider().insert(
 +                    result_uri = getContentProviderClient().insert(
                              ProviderTableMeta.CONTENT_URI_FILE, cv);
                  } catch (RemoteException e) {
                      Log_OC.e(TAG,
              }            
          }
  
 -        if (file.isDirectory()) {
 -            calculateFolderSize(file.getFileId());
 -            if (file.needsUpdatingWhileSaving()) {
 -                for (OCFile f : getDirectoryContent(file))
 -                    saveFile(f);
 -            }
 -        }
 -        
 -        if (changesSizeOfAncestors || file.isDirectory()) {
 -            updateSizesToTheRoot(file.getParentId());
 +        if (file.isFolder()) {
 +            updateFolderSize(file.getFileId());
 +        } else {
 +            updateFolderSize(file.getParentId());
          }
          
          return overriden;
      }
  
  
 -    @Override
 -    public void saveFiles(List<OCFile> files) {
 +    /**
 +     * Inserts or updates the list of files contained in a given folder.
 +     * 
++     * CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
++     * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
++     *  
 +     * @param folder
 +     * @param files
 +     * @param removeNotUpdated
 +     */
 +    public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
 +        
 +        Log_OC.d(TAG,  "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
  
 -        Iterator<OCFile> filesIt = files.iterator();
 -        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
 -        OCFile file = null;
 +        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
  
 -        // prepare operations to perform
 -        while (filesIt.hasNext()) {
 -            file = filesIt.next();
 +        // prepare operations to insert or update files to save in the given folder
 +        for (OCFile file : updatedFiles) {
              ContentValues cv = new ContentValues();
              cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
              cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
              cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
              cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
              cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
 -            if (file.getParentId() != 0)
 -                cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
 +            //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
 +            cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
              cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
 -            if (!file.isDirectory())
 +            if (!file.isFolder()) {
                  cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
 +            }
              cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
              cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
              cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
              cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
 +            cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
  
 -            if (fileExists(file.getRemotePath())) {
 -                OCFile oldFile = getFileByPath(file.getRemotePath());
 -                file.setFileId(oldFile.getFileId());
 -               
 -                if (file.isDirectory()) {
 -                    cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
 -                    file.setFileLength(oldFile.getFileLength());
 -                }
 -                
 -                operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
 -                        withValues(cv).
 -                        withSelection(  ProviderTableMeta._ID + "=?", 
 -                                new String[] { String.valueOf(file.getFileId()) })
 -                                .build());
 -
 -            } else if (fileExists(file.getFileId())) {
 -                OCFile oldFile = getFileById(file.getFileId());
 -                if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
 -                    file.setStoragePath(oldFile.getStoragePath());
 -                
 -                if (!file.isDirectory())
 -                    cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
 -                else {
 -                    cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
 -                    file.setFileLength(oldFile.getFileLength());
 -                }
 -                
 +            boolean existsByPath = fileExists(file.getRemotePath());
 +            if (existsByPath || fileExists(file.getFileId())) {
 +                // updating an existing file
-                 
-                 /* CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
-                  * 
-                  * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED 
-                  */
-                 /*
-                 OCFile oldFile = null;
-                 if (existsByPath) {
-                     // grant same id
-                     oldFile = getFileByPath(file.getRemotePath());
-                     file.setFileId(oldFile.getFileId());
-                 } else {
-                     oldFile = getFileById(file.getFileId());
-                 }
-                 
-                 if (file.isFolder()) {
-                     // folders keep size information, since it's calculated
-                     file.setFileLength(oldFile.getFileLength());
-                     cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
-                     
-                 } else if (file.getStoragePath() == null && oldFile.getStoragePath() != null) {
-                     // regular files keep access to local contents, although it's lost in the new OCFile
-                     file.setStoragePath(oldFile.getStoragePath());
-                     cv.put(ProviderTableMeta.FILE_STORAGE_PATH, oldFile.getStoragePath());
-                 }
-                 */
-                 
                  operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                          withValues(cv).
                          withSelection(  ProviderTableMeta._ID + "=?", 
                                  .build());
  
              } else {
 +                // adding a new file
                  operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
              }
          }
 +        
 +        // prepare operations to remove files in the given folder
 +        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
 +        String [] whereArgs = null;
 +        for (OCFile file : filesToRemove) {
 +            if (file.getParentId() == folder.getFileId()) {
 +                whereArgs = new String[]{mAccount.name, file.getRemotePath()};
 +                //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
 +                if (file.isFolder()) {
 +                    operations.add(ContentProviderOperation
 +                                    .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
 +                                        .build());
 +                    // TODO remove local folder
 +                } else {
 +                    operations.add(ContentProviderOperation
 +                                    .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
 +                                        .build());
 +                    if (file.isDown()) {
 +                        new File(file.getStoragePath()).delete();
 +                        // TODO move the deletion of local contents after success of deletions
 +                    }
 +                }
 +            }
 +        }
 +        
 +        // update metadata of folder
 +        ContentValues cv = new ContentValues();
 +        cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
 +        cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
 +        cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
 +        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);   // FileContentProvider calculates the right size
 +        cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
 +        cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
 +        cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
 +        cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
 +        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
 +        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
 +        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
 +        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
 +        cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
 +        operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
 +                withValues(cv).
 +                withSelection(  ProviderTableMeta._ID + "=?", 
 +                        new String[] { String.valueOf(folder.getFileId()) })
 +                        .build());
  
          // apply operations in batch
          ContentProviderResult[] results = null;
 +        Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
          try {
              if (getContentResolver() != null) {
-                 results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
+                 results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
  
              } else {
 -                results = getContentProvider().applyBatch(operations);
 +                results = getContentProviderClient().applyBatch(operations);
              }
  
          } catch (OperationApplicationException e) {
 -            Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
 +            Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
  
          } catch (RemoteException e) {
 -            Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
 +            Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
          }
  
          // update new id in file objects for insertions
          if (results != null) {
              long newId;
 +            Iterator<OCFile> filesIt = updatedFiles.iterator();
 +            OCFile file = null;
              for (int i=0; i<results.length; i++) {
 +                if (filesIt.hasNext()) {
 +                    file = filesIt.next();
 +                } else {
 +                    file = null;
 +                }
                  if (results[i].uri != null) {
                      newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
 -                    files.get(i).setFileId(newId);
 -                    //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
 +                    //updatedFiles.get(i).setFileId(newId);
 +                    if (file != null) {
 +                        file.setFileId(newId);
 +                    }
                  }
              }
          }
 +        
 +        updateFolderSize(folder.getFileId());
 +        
 +    }
  
 -        for (OCFile aFile : files) {
 -            if (aFile.isDirectory() && aFile.needsUpdatingWhileSaving())
 -                saveFiles(getDirectoryContent(aFile));
 -        }
  
 +    /**
 +     * 
 +     * @param id
 +     */
 +    private void updateFolderSize(long id) {
 +        if (id > FileDataStorageManager.ROOT_PARENT_ID) {
 +            Log_OC.d(TAG, "Updating size of " + id);
 +            if (getContentResolver() != null) {
 +                getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, null,
 +                        ProviderTableMeta._ID + "=?",
 +                        new String[] { String.valueOf(id) });
 +            } else {
 +                try {
 +                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, null,
 +                        ProviderTableMeta._ID + "=?",
 +                        new String[] { String.valueOf(id) });
 +                    
 +                } catch (RemoteException e) {
 +                    Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
 +                }
 +            }
 +        } else {
 +            Log_OC.e(TAG,  "not updating size for folder " + id);
 +        }
      }
 +    
  
 -    public void setAccount(Account account) {
 -        mAccount = account;
 +    public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
 +        if (file != null) {
 +            if (file.isFolder()) {
 +                removeFolder(file, removeDBData, removeLocalCopy);
 +                
 +            } else {
 +                if (removeDBData) {
 +                    //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
 +                    Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
 +                    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
 +                    String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
 +                    if (getContentProviderClient() != null) {
 +                        try {
 +                            getContentProviderClient().delete(file_uri, where, whereArgs);
 +                        } catch (RemoteException e) {
 +                            e.printStackTrace();
 +                        }
 +                    } else {
 +                        getContentResolver().delete(file_uri, where, whereArgs);
 +                    }
 +                    updateFolderSize(file.getParentId());
 +                }
 +                if (removeLocalCopy && file.isDown()) {
 +                    boolean success = new File(file.getStoragePath()).delete();
 +                    if (!removeDBData && success) {
 +                        // maybe unnecessary, but should be checked TODO remove if unnecessary
 +                        file.setStoragePath(null);
 +                        saveFile(file);
 +                    }
 +                }
 +            }
 +        }
      }
 +    
  
 -    public Account getAccount() {
 -        return mAccount;
 +    public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
 +        if (folder != null && folder.isFolder()) {
 +            if (removeDBData &&  folder.getFileId() != -1) {
 +                removeFolderInDb(folder);
 +            }
 +            if (removeLocalContent) {
 +                File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
 +                removeLocalFolder(localFolder);
 +            }
 +        }
      }
  
 -    public void setContentResolver(ContentResolver cr) {
 -        mContentResolver = cr;
 +    private void removeFolderInDb(OCFile folder) {
 +        Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId());   // URI for recursive deletion
 +        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
 +        String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
 +        if (getContentProviderClient() != null) {
 +            try {
 +                getContentProviderClient().delete(folder_uri, where, whereArgs);
 +            } catch (RemoteException e) {
 +                e.printStackTrace();
 +            }
 +        } else {
 +            getContentResolver().delete(folder_uri, where, whereArgs); 
 +        }
 +        updateFolderSize(folder.getParentId());
      }
  
 -    public ContentResolver getContentResolver() {
 -        return mContentResolver;
 +    private void removeLocalFolder(File folder) {
 +        if (folder.exists()) {
 +            File[] files = folder.listFiles();
 +            if (files != null) {
 +                for (File file : files) {
 +                    if (file.isDirectory()) {
 +                        removeLocalFolder(file);
 +                    } else {
 +                        file.delete();
 +                    }
 +                }
 +            }
 +            folder.delete();
 +        }
      }
  
 -    public void setContentProvider(ContentProviderClient cp) {
 -        mContentProvider = cp;
 -    }
 +    /**
 +     * Updates database for a folder that was moved to a different location.
 +     * 
 +     * TODO explore better (faster) implementations
 +     * TODO throw exceptions up !
 +     */
 +    public void moveFolder(OCFile folder, String newPath) {
 +        // TODO check newPath
  
 -    public ContentProviderClient getContentProvider() {
 -        return mContentProvider;
 -    }
 -    
 -    @Override
 -    public Vector<OCFile> getDirectoryContent(OCFile f) {
 -        if (f != null && f.isDirectory() && f.getFileId() != -1) {
 -            return getDirectoryContent(f.getFileId());
 +        if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
 +            /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
 +            Cursor c = null;
 +            if (getContentProviderClient() != null) {
 +                try {
 +                    c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI, 
 +                            null,
 +                            ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
 +                            new String[] { mAccount.name, folder.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
 +                } catch (RemoteException e) {
 +                    Log_OC.e(TAG, e.getMessage());
 +                }
 +            } else {
 +                c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
 +                        null,
 +                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
 +                        new String[] { mAccount.name, folder.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
 +            }
 +
 +            /// 2. prepare a batch of update operations to change all the descendants
 +            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
 +            int lengthOfOldPath = folder.getRemotePath().length();
 +            String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
 +            int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
 +            if (c.moveToFirst()) {
 +                do {
 +                    ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
 +                    OCFile child = createFileInstance(c);
 +                    cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
 +                    if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
 +                        cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
 +                    }
 +                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
 +                            withValues(cv).
 +                            withSelection(  ProviderTableMeta._ID + "=?", 
 +                                    new String[] { String.valueOf(child.getFileId()) })
 +                                    .build());
 +                } while (c.moveToNext());
 +            }
 +            c.close();
 +
 +            /// 3. apply updates in batch
 +            try {
 +                if (getContentResolver() != null) {
-                     getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
++                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
 +
 +                } else {
 +                    getContentProviderClient().applyBatch(operations);
 +                }
 +
 +            } catch (OperationApplicationException e) {
 +                Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
 +
 +            } catch (RemoteException e) {
 +                Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
 +            }
  
 -        } else {
 -            return new Vector<OCFile>();
          }
      }
  
 -    private Vector<OCFile> getDirectoryContent(long parentId) {
 +    
 +    private Vector<OCFile> getFolderContent(long parentId) {
  
          Vector<OCFile> ret = new Vector<OCFile>();
  
                  String.valueOf(parentId));
          Cursor c = null;
  
 -        if (getContentProvider() != null) {
 +        if (getContentProviderClient() != null) {
              try {
 -                c = getContentProvider().query(req_uri, null, 
 +                c = getContentProviderClient().query(req_uri, null, 
                          ProviderTableMeta.FILE_PARENT + "=?" ,
                          new String[] { String.valueOf(parentId)}, null);
              } catch (RemoteException e) {
      }
      
      
 +    private OCFile createRootDir() {
 +        OCFile file = new OCFile(OCFile.ROOT_PATH);
 +        file.setMimetype("DIR");
 +        file.setParentId(FileDataStorageManager.ROOT_PARENT_ID);
 +        saveFile(file);
 +        return file;
 +    }
  
      private boolean fileExists(String cmp_key, String value) {
          Cursor c;
                                      new String[] { value, mAccount.name }, null);
          } else {
              try {
 -                c = getContentProvider().query(
 +                c = getContentProviderClient().query(
                          ProviderTableMeta.CONTENT_URI,
                          null,
                          cmp_key + "=? AND "
                                      new String[] { value, mAccount.name }, null);
          } else {
              try {
 -                c = getContentProvider().query(
 +                c = getContentProviderClient().query(
                          ProviderTableMeta.CONTENT_URI,
                          null,
                          key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
                      .getColumnIndex(ProviderTableMeta.FILE_PARENT)));
              file.setMimetype(c.getString(c
                      .getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
 -            if (!file.isDirectory()) {
 +            if (!file.isFolder()) {
                  file.setStoragePath(c.getString(c
                          .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
                  if (file.getStoragePath() == null) {
                      getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
              file.setKeepInSync(c.getInt(
                      c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
 +            file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
 +                    
          }
          return file;
      }
  
-     /*
 -    @Override
 -    public void removeFile(OCFile file, boolean removeLocalCopy) {
 -        Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
 -        if (getContentProvider() != null) {
 -            try {
 -                getContentProvider().delete(file_uri,
 -                        ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
 -                        new String[]{mAccount.name});
 -            } catch (RemoteException e) {
 -                e.printStackTrace();
 -            }
 -        } else {
 -            getContentResolver().delete(file_uri,
 -                    ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
 -                    new String[]{mAccount.name});
 -        }
 -        if (file.isDown() && removeLocalCopy) {
 -            new File(file.getStoragePath()).delete();
 -        }
 -        if (file.isDirectory() && removeLocalCopy) {
 -            File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
 -            if (f.exists() && f.isDirectory() && (f.list() == null || f.list().length == 0)) {
 -                f.delete();
 -            }
 -        }
 -        
 -        if (file.getFileLength() > 0) {
 -            updateSizesToTheRoot(file.getParentId());
 -        }
 -    }
 -
 -    @Override
 -    public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent) {
 -        // TODO consider possible failures
 -        if (dir != null && dir.isDirectory() && dir.getFileId() != -1) {
 -            Vector<OCFile> children = getDirectoryContent(dir);
 -            if (children.size() > 0) {
 -                OCFile child = null;
 -                for (int i=0; i<children.size(); i++) {
 -                    child = children.get(i);
 -                    if (child.isDirectory()) {
 -                        removeDirectory(child, removeDBData, removeLocalContent);
 -                    } else {
 -                        if (removeDBData) {
 -                            removeFile(child, removeLocalContent);
 -                        } else if (removeLocalContent) {
 -                            if (child.isDown()) {
 -                                new File(child.getStoragePath()).delete();
 -                            }
 -                        }
 -                    }
 -                }
 -            }
 -            if (removeDBData) {
 -                removeFile(dir, true);
 -            }
 -            
 -            if (dir.getFileLength() > 0) {
 -                updateSizesToTheRoot(dir.getParentId());
 -            }
 -        }
 -    }
 -
 -
 -    /**
 -     * Updates database for a folder that was moved to a different location.
 -     * 
 -     * TODO explore better (faster) implementations
 -     * TODO throw exceptions up !
 -     */
 -    @Override
 -    public void moveDirectory(OCFile dir, String newPath) {
 -        // TODO check newPath
 -
 -        if (dir != null && dir.isDirectory() && dir.fileExists() && !dir.getFileName().equals(OCFile.PATH_SEPARATOR)) {
 -            /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
 -            Cursor c = null;
 -            if (getContentProvider() != null) {
 -                try {
 -                    c = getContentProvider().query(ProviderTableMeta.CONTENT_URI, 
 -                            null,
 -                            ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
 -                            new String[] { mAccount.name, dir.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
 -                } catch (RemoteException e) {
 -                    Log_OC.e(TAG, e.getMessage());
 -                }
 -            } else {
 -                c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
 -                        null,
 -                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
 -                        new String[] { mAccount.name, dir.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
 -            }
 -
 -            /// 2. prepare a batch of update operations to change all the descendants
 -            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
 -            int lengthOfOldPath = dir.getRemotePath().length();
 -            String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
 -            int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
 -            if (c.moveToFirst()) {
 -                do {
 -                    ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
 -                    OCFile child = createFileInstance(c);
 -                    cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
 -                    if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
 -                        cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
 -                    }
 -                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
 -                            withValues(cv).
 -                            withSelection(  ProviderTableMeta._ID + "=?", 
 -                                    new String[] { String.valueOf(child.getFileId()) })
 -                                    .build());
 -                } while (c.moveToNext());
 -            }
 -            c.close();
 -
 -            /// 3. apply updates in batch
 -            try {
 -                if (getContentResolver() != null) {
 -                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
 -
 -                } else {
 -                    getContentProvider().applyBatch(operations);
 -                }
 -
 -            } catch (OperationApplicationException e) {
 -                Log_OC.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
 -
 -            } catch (RemoteException e) {
 -                Log_OC.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e);
 -            }
 -
 -        }
 -    }
 -
 -    @Override
 -    public Vector<OCFile> getDirectoryImages(OCFile directory) {
 -        Vector<OCFile> ret = new Vector<OCFile>(); 
 -        if (directory != null) {
 -            // TODO better implementation, filtering in the access to database (if possible) instead of here 
 -            Vector<OCFile> tmp = getDirectoryContent(directory);
 -            OCFile current = null; 
 -            for (int i=0; i<tmp.size(); i++) {
 -                current = tmp.get(i);
 -                if (current.isImage()) {
 -                    ret.add(current);
 -                }
 -            }
 -        }
 -        return ret;
 -    }
 -
 -    /**
 -     * Calculate and save the folderSize on DB
 -     * @param id
 -     */
 -    @Override
 -    public void calculateFolderSize(long id) {
 -        long folderSize = 0;
 -        
 -        Vector<OCFile> files = getDirectoryContent(id);
 -        
 -        for (OCFile f: files)
 -        {
 -            folderSize = folderSize + f.getFileLength();
 -        }
 -        
 -        updateSize(id, folderSize);
 -    }
 -
 -    /**
--     * Update the size value of an OCFile in DB
-      *
 -     */
--    private int updateSize(long id, long size) {
--        ContentValues cv = new ContentValues();
--        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size);
--        int result = -1;
--        if (getContentResolver() != null) {
--             result = getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", 
--                     new String[] { String.valueOf(id) });
--        } else {
--            try {
-                 result = getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", 
 -                result = getContentProvider().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?", 
--                        new String[] { String.valueOf(id) });
--            } catch (RemoteException e) {
--                Log_OC.e(TAG,"Fail to update size column into database " + e.getMessage());
--            }
--        }
--        return result;
--    }
-     */
--
-     /* 
 -    /** 
--     * Update the size of a subtree of folder from a file to the root
--     * @param parentId: parent of the file
-      *
 -     */
--    private void updateSizesToTheRoot(long parentId) {
--        
--        OCFile file; 
--
-         while (parentId != FileDataStorageManager.ROOT_PARENT_ID) {
 -        while (parentId != 0) {
--            
--            // Update the size of the parent
-             updateFolderSize(parentId);
 -            calculateFolderSize(parentId);
--            
--            // search the next parent
--            file = getFileById(parentId);            
--            parentId = file.getParentId();
--            
--        }              
 -        
--    }
-     */
--    
  }
@@@ -17,6 -17,8 +17,8 @@@
   */\r
  package com.owncloud.android.db;\r
  \r
+ import com.owncloud.android.MainApp;\r
\r
  import android.net.Uri;\r
  import android.provider.BaseColumns;\r
  \r
   */\r
  public class ProviderMeta {\r
  \r
-     public static final String AUTHORITY_FILES = "org.owncloud";\r
-     public static final String DB_FILE = "owncloud.db";\r
+     /* These constants are now in MainApp\r
+         public static final String AUTHORITY_FILES = "org.owncloud";\r
+         public static final String DB_FILE = "owncloud.db";\r
+     */\r
      public static final String DB_NAME = "filelist";\r
 -    public static final int DB_VERSION = 4;\r
 +    public static final int DB_VERSION = 5;\r
  \r
      private ProviderMeta() {\r
      }\r
      static public class ProviderTableMeta implements BaseColumns {\r
          public static final String DB_NAME = "filelist";\r
          public static final Uri CONTENT_URI = Uri.parse("content://"\r
-                 + AUTHORITY_FILES + "/");\r
+                 + MainApp.getAuthority() + "/");\r
          public static final Uri CONTENT_URI_FILE = Uri.parse("content://"\r
-                 + AUTHORITY_FILES + "/file");\r
+                 + MainApp.getAuthority() + "/file");\r
          public static final Uri CONTENT_URI_DIR = Uri.parse("content://"\r
-                 + AUTHORITY_FILES + "/dir");\r
+                 + MainApp.getAuthority() + "/dir");\r
  \r
          public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.owncloud.file";\r
          public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.owncloud.file";\r
@@@ -61,7 -65,6 +65,7 @@@
          public static final String FILE_LAST_SYNC_DATE = "last_sync_date";  // _for_properties, but let's keep it as it is\r
          public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";\r
          public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";\r
 +        public static final String FILE_ETAG = "etag";\r
  \r
          public static final String DEFAULT_SORT_ORDER = FILE_NAME\r
                  + " collate nocase asc";\r
@@@ -28,7 -28,6 +28,6 @@@ 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;
@@@ -60,6 -59,7 +59,7 @@@ import android.os.Process
  import android.widget.RemoteViews;
  
  import com.owncloud.android.Log_OC;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import eu.alefzero.webdav.WebdavClient;
  
@@@ -68,8 -68,8 +68,8 @@@ public class FileDownloader extends Ser
      public static final String EXTRA_ACCOUNT = "ACCOUNT";
      public static final String EXTRA_FILE = "FILE";
      
-     public static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
-     public static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
+     private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
+     private static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
      public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";    
      public static final String EXTRA_FILE_PATH = "FILE_PATH";
      public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
      private int mLastPercent;
      
      
+     public String getDownloadAddedMessage() {
+         return getClass().getName().toString() + DOWNLOAD_ADDED_MESSAGE;
+     }
+     
+     public String getDownloadFinishMessage() {
+         return getClass().getName().toString() + DOWNLOAD_FINISH_MESSAGE;
+     }
+     
      /**
       * Builds a key for mPendingDownloads from the account and file to download
       * 
              if (account == null || file == null) return false;
              String targetKey = buildRemoteName(account, file);
              synchronized (mPendingDownloads) {
 -                if (file.isDirectory()) {
 +                if (file.isFolder()) {
                      // this can be slow if there are many downloads :(
                      Iterator<String> it = mPendingDownloads.keySet().iterator();
                      boolean found = false;
              boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
                                                  // (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
                                                    (downloadResult.isIdPRedirection()
-                                                         && AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mDownloadClient.getAuthTokenType())));
+                                                         && MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
              if (needsToUpdateCredentials) {
                  // let the user update credentials with one click
                  Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
       * @param downloadResult    Result of the download operation
       */
      private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) {
-         Intent end = new Intent(DOWNLOAD_FINISH_MESSAGE);
+         Intent end = new Intent(getDownloadFinishMessage());
          end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
          end.putExtra(ACCOUNT_NAME, download.getAccount().name);
          end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
       * @param download          Added download operation
       */
      private void sendBroadcastNewDownload(DownloadFileOperation download) {
-         Intent added = new Intent(DOWNLOAD_ADDED_MESSAGE);
+         Intent added = new Intent(getDownloadAddedMessage());
          added.putExtra(ACCOUNT_NAME, download.getAccount().name);
          added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
          added.putExtra(EXTRA_FILE_PATH, download.getSavePath());
@@@ -71,6 -71,7 +71,7 @@@ 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;
@@@ -84,7 -85,7 +85,7 @@@ import eu.alefzero.webdav.WebdavClient
  
  public class FileUploader extends Service implements OnDatatransferProgressListener {
  
-     public static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
+     private static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
      public static final String EXTRA_UPLOAD_RESULT = "RESULT";
      public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
      public static final String EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH";
      private int mLastPercent;
      private RemoteViews mDefaultNotificationContentView;
  
+     
+     public String getUploadFinishMessage() {
+         return getClass().getName().toString() + UPLOAD_FINISH_MESSAGE;
+     }
+     
      /**
       * Builds a key for mPendingUploads from the account and file to upload
       * 
                  return false;
              String targetKey = buildRemoteName(account, file);
              synchronized (mPendingUploads) {
 -                if (file.isDirectory()) {
 +                if (file.isFolder()) {
                      // this can be slow if there are many uploads :(
                      Iterator<String> it = mPendingUploads.keySet().iterator();
                      boolean found = false;
              boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
                      //(uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() && 
                      (uploadResult.isIdPRedirection() &&
-                             AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(mUploadClient.getAuthTokenType())));
+                             MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
              if (needsToUpdateCredentials) {
                  // let the user update credentials with one click
                  Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
       * @param uploadResult Result of the upload operation
       */
      private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) {
-         Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
+         Intent end = new Intent(getUploadFinishMessage());
          end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
                                                                   // path, after
                                                                   // possible
@@@ -21,7 -21,7 +21,7 @@@ import java.io.IOException
  import org.apache.commons.httpclient.Credentials;
  
  import com.owncloud.android.Log_OC;
- import com.owncloud.android.authentication.AccountAuthenticator;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.network.BearerCredentials;
  import com.owncloud.android.network.OwnCloudClientUtils;
  import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
@@@ -136,8 -136,14 +136,8 @@@ public abstract class RemoteOperation i
          mCallerActivity = callerActivity;
          mClient = null;     // the client instance will be created from mAccount and mContext in the runnerThread to create below
          
 -        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);
                      boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
                      boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
                      if (bearerAuthorization) {
-                         am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
+                         am.invalidateAuthToken(MainApp.getAccountType(), ((BearerCredentials)cred).getAccessToken());
                      } else if (samlBasedSsoAuthorization ) {
-                         am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ssoSessionCookie);
+                         am.invalidateAuthToken(MainApp.getAccountType(), ssoSessionCookie);
                      } else {
                          am.clearPassword(mAccount);
                      }
  
  package com.owncloud.android.providers;
  
 +import java.util.ArrayList;
  import java.util.HashMap;
  
  import com.owncloud.android.Log_OC;
+ import com.owncloud.android.R;
 +import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.db.ProviderMeta;
  import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
  
  
  import android.content.ContentProvider;
 +import android.content.ContentProviderOperation;
 +import android.content.ContentProviderResult;
  import android.content.ContentUris;
  import android.content.ContentValues;
  import android.content.Context;
 +import android.content.OperationApplicationException;
  import android.content.UriMatcher;
  import android.database.Cursor;
  import android.database.SQLException;
@@@ -47,7 -43,6 +48,7 @@@ import android.text.TextUtils
   * The ContentProvider for the ownCloud App.
   * 
   * @author Bartek Przybylski
 + * @author David A. Velasco
   * 
   */
  public class FileContentProvider extends ContentProvider {
                  ProviderTableMeta.FILE_KEEP_IN_SYNC);
          mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
                  ProviderTableMeta.FILE_ACCOUNT_OWNER);
 +        mProjectionMap.put(ProviderTableMeta.FILE_ETAG, 
 +                ProviderTableMeta.FILE_ETAG);
      }
  
      private static final int SINGLE_FILE = 1;
      private static final int DIRECTORY = 2;
      private static final int ROOT_DIRECTORY = 3;
-     private static final UriMatcher mUriMatcher;
 -    
 -    private UriMatcher mUriMatcher;
 -//    static {
 -//        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 -//        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, null, ROOT_DIRECTORY);
 -//        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
 -//        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
 -//        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
 -//    }
  
-     public static final String METHOD_UPDATE_FOLDER_SIZE = "updateFolderSize";
++    private UriMatcher mUriMatcher;
      
-     static {
-         mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-         mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, null, ROOT_DIRECTORY);
-         mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
-         mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
-         mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/", DIRECTORY);
-         mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
-     }
      @Override
      public int delete(Uri uri, String where, String[] whereArgs) {
 +        //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this);
 +        int count = 0;
          SQLiteDatabase db = mDbHelper.getWritableDatabase();
 +        db.beginTransaction();
 +        try {
 +            count = delete(db, uri, where, whereArgs);
 +            db.setTransactionSuccessful();
 +        } finally {
 +            db.endTransaction();
 +        }
 +        getContext().getContentResolver().notifyChange(uri, null);
 +        return count;
 +    }
 +    
 +    
 +    private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
          int count = 0;
          switch (mUriMatcher.match(uri)) {
          case SINGLE_FILE:
 +            /*Cursor c = query(db, uri, null, where, whereArgs, null);
 +            String remotePath = "(unexisting)";
 +            if (c != null && c.moveToFirst()) {
 +                remotePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH));
 +            }
 +            Log_OC.d(TAG, "Removing FILE " + remotePath);
 +            */
              count = db.delete(ProviderTableMeta.DB_NAME,
                      ProviderTableMeta._ID
                              + "="
                              + uri.getPathSegments().get(1)
                              + (!TextUtils.isEmpty(where) ? " AND (" + where
                                      + ")" : ""), whereArgs);
 +            /* just for log
 +            if (c!=null) {
 +                c.close();
 +            }
 +            */
 +            break;
 +        case DIRECTORY:
 +            // deletion of folder is recursive
 +            /*
 +            Uri folderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, Long.parseLong(uri.getPathSegments().get(1)));
 +            Cursor folder = query(db, folderUri, null, null, null, null);
 +            String folderName = "(unknown)";
 +            if (folder != null && folder.moveToFirst()) {
 +                folderName = folder.getString(folder.getColumnIndex(ProviderTableMeta.FILE_PATH));
 +            }
 +            */
 +            Cursor children = query(uri, null, null, null, null);
 +            if (children != null && children.moveToFirst())  {
 +                long childId;
 +                boolean isDir; 
 +                //String remotePath; 
 +                while (!children.isAfterLast()) {
 +                    childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
 +                    isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
 +                    //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
 +                    if (isDir) {
 +                        count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
 +                    } else {
 +                        count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
 +                    }
 +                    children.moveToNext();
 +                }
 +                children.close();
 +            } /*else {
 +                Log_OC.d(TAG, "No child to remove in DIRECTORY " + folderName);
 +            }
 +            Log_OC.d(TAG, "Removing DIRECTORY " + folderName + " (or maybe not) ");
 +            */
 +            count += db.delete(ProviderTableMeta.DB_NAME,
 +                    ProviderTableMeta._ID
 +                    + "="
 +                    + uri.getPathSegments().get(1)
 +                    + (!TextUtils.isEmpty(where) ? " AND (" + where
 +                            + ")" : ""), whereArgs);
 +            /* Just for log
 +             if (folder != null) {
 +                folder.close();
 +            }*/
              break;
          case ROOT_DIRECTORY:
 +            //Log_OC.d(TAG, "Removing ROOT!");
              count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
              break;
          default:
 +            //Log_OC.e(TAG, "Unknown uri " + uri);
              throw new IllegalArgumentException("Unknown uri: " + uri.toString());
          }
 -        getContext().getContentResolver().notifyChange(uri, null);
          return count;
      }
 +    
  
      @Override
      public String getType(Uri uri) {
  
      @Override
      public Uri insert(Uri uri, ContentValues values) {
 +        //Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
 +        Uri newUri = null;
 +        SQLiteDatabase db = mDbHelper.getWritableDatabase();
 +        db.beginTransaction();
 +        try {
 +            newUri = insert(db, uri, values);
 +            db.setTransactionSuccessful();
 +        } finally {
 +            db.endTransaction();
 +        }
 +        getContext().getContentResolver().notifyChange(newUri, null);
 +        return newUri;
 +    }
 +    
 +    private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
          if (mUriMatcher.match(uri) != SINGLE_FILE &&
 -            mUriMatcher.match(uri) != ROOT_DIRECTORY) {
 -            
 +                mUriMatcher.match(uri) != ROOT_DIRECTORY) {
 +            //Log_OC.e(TAG, "Inserting invalid URI: " + uri);
              throw new IllegalArgumentException("Unknown uri id: " + uri);
          }
  
 -        SQLiteDatabase db = mDbHelper.getWritableDatabase();
          long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
          if (rowId > 0) {
 -            Uri insertedFileUri = ContentUris.withAppendedId(
 -                    ProviderTableMeta.CONTENT_URI_FILE, rowId);
 -            getContext().getContentResolver().notifyChange(insertedFileUri,
 -                    null);
 +            Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
 +            //Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
              return insertedFileUri;
 +        } else {
 +            //Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH)  + " at provider " + this);
 +            throw new SQLException("ERROR " + uri);
          }
 -        throw new SQLException("ERROR " + uri);
      }
  
 +    
      @Override
      public boolean onCreate() {
          mDbHelper = new DataBaseHelper(getContext());
+         
+         String authority = getContext().getResources().getString(R.string.authority);
+         mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+         mUriMatcher.addURI(authority, null, ROOT_DIRECTORY);
+         mUriMatcher.addURI(authority, "file/", SINGLE_FILE);
+         mUriMatcher.addURI(authority, "file/#", SINGLE_FILE);
++        mUriMatcher.addURI(authority, "dir/", DIRECTORY);
+         mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
+         
          return true;
      }
  
 +    
      @Override
 -    public Cursor query(Uri uri, String[] projection, String selection,
 -            String[] selectionArgs, String sortOrder) {
 +    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
 +        Cursor result = null;
 +        SQLiteDatabase db = mDbHelper.getReadableDatabase();
 +        db.beginTransaction();
 +        try {
 +            result = query(db, uri, projection, selection, selectionArgs, sortOrder);
 +            db.setTransactionSuccessful();
 +        } finally {
 +            db.endTransaction();
 +        }
 +        return result;
 +    }
 +    
 +    private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
          SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
  
          sqlQuery.setTables(ProviderTableMeta.DB_NAME);
          case ROOT_DIRECTORY:
              break;
          case DIRECTORY:
 +            String folderId = uri.getPathSegments().get(1);
              sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
 -                    + uri.getPathSegments().get(1));
 +                    + folderId);
              break;
          case SINGLE_FILE:
              if (uri.getPathSegments().size() > 1) {
              order = sortOrder;
          }
  
 -        SQLiteDatabase db = mDbHelper.getReadableDatabase();
          // DB case_sensitive
          db.execSQL("PRAGMA case_sensitive_like = true");
 -        Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
 -                null, null, order);
 -
 +        Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order);
          c.setNotificationUri(getContext().getContentResolver(), uri);
 -
          return c;
      }
  
      @Override
 -    public int update(Uri uri, ContentValues values, String selection,
 -            String[] selectionArgs) {
 -        return mDbHelper.getWritableDatabase().update(
 -                ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
 +    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
 +        
 +        //Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
 +        int count = 0;
 +        SQLiteDatabase db = mDbHelper.getWritableDatabase();
 +        db.beginTransaction();
 +        try {
 +            count = update(db, uri, values, selection, selectionArgs);
 +            db.setTransactionSuccessful();
 +        } finally {
 +            db.endTransaction();
 +        }
 +        getContext().getContentResolver().notifyChange(uri, null);
 +        return count;
 +    }
 +    
 +    
 +    private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
 +        switch (mUriMatcher.match(uri)) {
 +            case DIRECTORY:
 +                return updateFolderSize(db, selectionArgs[0]);
 +            default:
 +                return db.update(ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
 +        }
 +    }    
 +
 +    
 +    private int updateFolderSize(SQLiteDatabase db, String folderId) {
 +        int count = 0;
 +        String [] whereArgs = new String[] { folderId };
 +        
 +        // read current size saved for the folder 
 +        long folderSize = 0;
 +        long folderParentId = -1;
 +        Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId);
 +        String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
 +        String folderWhere = ProviderTableMeta._ID + "=?";
 +        Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null);
 +        if (folderCursor != null && folderCursor.moveToFirst()) {
 +            folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));;
 +            folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));;
 +        }
 +        folderCursor.close();
 +        
 +        // read and sum sizes of children
 +        long childrenSize = 0;
 +        Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId);
 +        String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
 +        String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?";
 +        Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null);
 +        if (childrenCursor != null && childrenCursor.moveToFirst()) {
 +            while (!childrenCursor.isAfterLast()) {
 +                childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));
 +                childrenCursor.moveToNext();
 +            }
 +        }
 +        childrenCursor.close();
 +        
 +        // update if needed
 +        if (folderSize != childrenSize) {
 +            Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
 +            ContentValues cv = new ContentValues();
 +            cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
 +            count = db.update(ProviderTableMeta.DB_NAME, cv, folderWhere, whereArgs);
 +            
 +            // propagate update until root
 +            if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
 +                Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId);
 +                updateFolderSize(db, String.valueOf(folderParentId));
 +            } else {
 +                Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId);
 +            }
 +        } else {
 +            Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize);
 +        }
 +        return count;
 +    }
 +
 +    
 +    @Override
 +    public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
 +        Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
 +        ContentProviderResult[] results = new ContentProviderResult[operations.size()];
 +        int i=0;
 +        
 +        SQLiteDatabase db = mDbHelper.getWritableDatabase();
 +        db.beginTransaction();  // it's supposed that transactions can be nested
 +        try {
 +            for (ContentProviderOperation operation : operations) {
 +                results[i] = operation.apply(this, results, i);
 +                i++;
 +            }
 +            db.setTransactionSuccessful();
 +        } finally {
 +            db.endTransaction();
 +        }
 +        Log_OC.d("FileContentProvider", "applied batch in provider " + this);
 +        return results;
      }
  
 +
      class DataBaseHelper extends SQLiteOpenHelper {
  
          public DataBaseHelper(Context context) {
                      + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
                      + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
                      + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
 -                    + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER );"
 +                    + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, "
 +                    + ProviderTableMeta.FILE_ETAG + " TEXT );"
                      );
          }
  
              }
              if (!upgraded)
                  Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
 +        
 +            if (oldVersion < 5 && newVersion >= 5) {
 +                Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
 +                db.beginTransaction();
 +                try {
 +                    db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
 +                            " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " +
 +                            " DEFAULT NULL");
 +                    
 +                    upgraded = true;
 +                    db.setTransactionSuccessful();
 +                } finally {
 +                    db.endTransaction();
 +                }
 +            }
 +            if (!upgraded)
 +                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
          }
 -
      }
  
  }
  package com.owncloud.android.syncadapter;\r
  \r
  import java.io.IOException;\r
- //import java.net.UnknownHostException;\r
- //import java.util.Date;\r
 -import java.util.Date;\r
  \r
  import org.apache.http.HttpRequest;\r
  import org.apache.http.HttpResponse;\r
  import org.apache.http.client.ClientProtocolException;\r
- //import org.apache.http.conn.ConnectionKeepAliveStrategy;\r
- //import org.apache.http.protocol.HttpContext;\r
 -import org.apache.http.conn.ConnectionKeepAliveStrategy;\r
 -import org.apache.http.protocol.HttpContext;\r
  \r
  import com.owncloud.android.authentication.AccountUtils;\r
  import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;\r
 -import com.owncloud.android.datamodel.DataStorageManager;\r
 +import com.owncloud.android.datamodel.FileDataStorageManager;\r
  import com.owncloud.android.network.OwnCloudClientUtils;\r
  \r
  import android.accounts.Account;\r
@@@ -43,13 -42,11 +39,13 @@@ import android.content.Context
  import eu.alefzero.webdav.WebdavClient;\r
  \r
  /**\r
 - * Base SyncAdapter for OwnCloud Designed to be subclassed for the concrete\r
 - * SyncAdapter, like ConcatsSync, CalendarSync, FileSync etc..\r
 + * Base synchronization adapter for ownCloud designed to be subclassed for different\r
 + * resource types, like FileSync, ConcatsSync, CalendarSync, etc..\r
   * \r
 - * @author sassman\r
 + * Implements the standard {@link AbstractThreadedSyncAdapter}.\r
   * \r
 + * @author sassman\r
 + * @author David A. Velasco\r
   */\r
  public abstract class AbstractOwnCloudSyncAdapter extends\r
          AbstractThreadedSyncAdapter {\r
@@@ -57,8 -54,8 +53,7 @@@
      private AccountManager accountManager;\r
      private Account account;\r
      private ContentProviderClient contentProvider;\r
-     //private Date lastUpdated;\r
 -    private Date lastUpdated;\r
 -    private DataStorageManager mStoreManager;\r
 +    private FileDataStorageManager mStoreManager;\r
  \r
      private WebdavClient mClient = null;\r
  \r
          this.contentProvider = contentProvider;\r
      }\r
  \r
 -    public Date getLastUpdated() {\r
 -        return lastUpdated;\r
 -    }\r
 -\r
 -    public void setLastUpdated(Date lastUpdated) {\r
 -        this.lastUpdated = lastUpdated;\r
 -    }\r
 -\r
 -    public void setStorageManager(DataStorageManager storage_manager) {\r
 +    public void setStorageManager(FileDataStorageManager storage_manager) {\r
          mStoreManager = storage_manager;\r
      }\r
  \r
 -    public DataStorageManager getStorageManager() {\r
 +    public FileDataStorageManager getStorageManager() {\r
          return mStoreManager;\r
      }\r
  \r
 -    protected ConnectionKeepAliveStrategy getKeepAliveStrategy() {\r
 -        return new ConnectionKeepAliveStrategy() {\r
 -            public long getKeepAliveDuration(HttpResponse response,\r
 -                    HttpContext context) {\r
 -                // Change keep alive straategy basing on response: ie\r
 -                // forbidden/not found/etc\r
 -                // should have keep alive 0\r
 -                // default return: 5s\r
 -                int statusCode = response.getStatusLine().getStatusCode();\r
 -\r
 -                // HTTP 400, 500 Errors as well as HTTP 118 - Connection timed\r
 -                // out\r
 -                if ((statusCode >= 400 && statusCode <= 418)\r
 -                        || (statusCode >= 421 && statusCode <= 426)\r
 -                        || (statusCode >= 500 && statusCode <= 510)\r
 -                        || statusCode == 118) {\r
 -                    return 0;\r
 -                }\r
 -\r
 -                return 5 * 1000;\r
 -            }\r
 -        };\r
 -    }\r
 -\r
 -    protected HttpResponse fireRawRequest(HttpRequest query)\r
 -            throws ClientProtocolException, OperationCanceledException,\r
 -            AuthenticatorException, IOException {\r
 -        /*\r
 -         * BasicHttpContext httpContext = new BasicHttpContext(); BasicScheme\r
 -         * basicAuth = new BasicScheme();\r
 -         * httpContext.setAttribute("preemptive-auth", basicAuth);\r
 -         * \r
 -         * HttpResponse response = getClient().execute(mHost, query,\r
 -         * httpContext);\r
 -         */\r
 -        return null;\r
 -    }\r
 -\r
      protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {\r
          AccountUtils.constructFullURLForAccount(getContext(), account);\r
          mClient = OwnCloudClientUtils.createOwnCloudClient(account, getContext());\r
      protected WebdavClient getClient() {\r
          return mClient;\r
      }\r
-         /*\r
-          * BasicHttpContext httpContext = new BasicHttpContext(); BasicScheme\r
-          * basicAuth = new BasicScheme();\r
-          * httpContext.setAttribute("preemptive-auth", basicAuth);\r
-          * \r
-          * HttpResponse response = getClient().execute(mHost, query,\r
-          * httpContext);\r
-          */\r
 +    \r
 +    \r
 +    /* method called by ContactSyncAdapter, that is never used */\r
 +    protected HttpResponse fireRawRequest(HttpRequest query)\r
 +            throws ClientProtocolException, OperationCanceledException,\r
 +            AuthenticatorException, IOException {\r
-     /* methods never used  below */\r
-     /*\r
-     public Date getLastUpdated() {\r
-         return lastUpdated;\r
-     }\r
\r
-     public void setLastUpdated(Date lastUpdated) {\r
-         this.lastUpdated = lastUpdated;\r
-     }\r
\r
-     protected ConnectionKeepAliveStrategy getKeepAliveStrategy() {\r
-         return new ConnectionKeepAliveStrategy() {\r
-             public long getKeepAliveDuration(HttpResponse response,\r
-                     HttpContext context) {\r
-                 // Change keep alive straategy basing on response: ie\r
-                 // forbidden/not found/etc\r
-                 // should have keep alive 0\r
-                 // default return: 5s\r
-                 int statusCode = response.getStatusLine().getStatusCode();\r
\r
-                 // HTTP 400, 500 Errors as well as HTTP 118 - Connection timed\r
-                 // out\r
-                 if ((statusCode >= 400 && statusCode <= 418)\r
-                         || (statusCode >= 421 && statusCode <= 426)\r
-                         || (statusCode >= 500 && statusCode <= 510)\r
-                         || statusCode == 118) {\r
-                     return 0;\r
-                 }\r
\r
-                 return 5 * 1000;\r
-             }\r
-         };\r
-     }\r
-      */\r
 +        return null;\r
 +    }\r
 +\r
  }
@@@ -27,9 -27,10 +27,9 @@@ import java.util.Map
  import org.apache.jackrabbit.webdav.DavException;
  
  import com.owncloud.android.Log_OC;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
- import com.owncloud.android.authentication.AccountAuthenticator;
  import com.owncloud.android.authentication.AuthenticatorActivity;
 -import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.operations.RemoteOperationResult;
@@@ -43,7 -44,6 +43,7 @@@ import android.accounts.AccountsExcepti
  import android.app.Notification;
  import android.app.NotificationManager;
  import android.app.PendingIntent;
 +import android.content.AbstractThreadedSyncAdapter;
  import android.content.ContentProviderClient;
  import android.content.ContentResolver;
  import android.content.Context;
@@@ -52,60 -52,36 +52,60 @@@ import android.content.SyncResult
  import android.os.Bundle;
  
  /**
 - * SyncAdapter implementation for syncing sample SyncAdapter contacts to the
 - * platform ContactOperations provider.
 + * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing 
 + * ownCloud files.
 + * 
 + * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}.
   * 
   * @author Bartek Przybylski
   * @author David A. Velasco
   */
  public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
  
 -    private final static String TAG = "FileSyncAdapter";
 +    private final static String TAG = FileSyncAdapter.class.getSimpleName();
  
 -    /** 
 -     * Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation
 -     */
 +    /** Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation */
      private static final int MAX_FAILED_RESULTS = 3; 
      
 +    
 +    /** Time stamp for the current synchronization process, used to distinguish fresh data */
      private long mCurrentSyncTime;
 +    
 +    /** Flag made 'true' when a request to cancel the synchronization is received */
      private boolean mCancellation;
 +    
 +    /** When 'true' the process was requested by the user through the user interface; when 'false', it was requested automatically by the system */
      private boolean mIsManualSync;
 -    private int mFailedResultsCounter;    
 +    
 +    /** Counter for failed operations in the synchronization process */
 +    private int mFailedResultsCounter;
 +    
 +    /** Result of the last failed operation */
      private RemoteOperationResult mLastFailedResult;
 -    private SyncResult mSyncResult;
 +    
 +    /** Counter of conflicts found between local and remote files */
      private int mConflictsFound;
 +    
 +    /** Counter of failed operations in synchronization of kept-in-sync files */
      private int mFailsInFavouritesFound;
 +    
 +    /** Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and couldn't be copied automatically into it */
      private Map<String, String> mForgottenLocalFiles;
  
 +    /** {@link SyncResult} instance to return to the system when the synchronization finish */
 +    private SyncResult mSyncResult;
 +    
      
 +    /**
 +     * Creates an {@link FileSyncAdapter}
 +     *
 +     * {@inheritDoc}
 +     */
      public FileSyncAdapter(Context context, boolean autoInitialize) {
          super(context, autoInitialize);
      }
  
 +    
      /**
       * {@inheritDoc}
       */
          mForgottenLocalFiles = new HashMap<String, String>();
          mSyncResult = syncResult;
          mSyncResult.fullSyncRequested = false;
 -        mSyncResult.delayUntil = 60*60*24; // sync after 24h
 +        mSyncResult.delayUntil = 60*60*24; // avoid too many automatic synchronizations
  
          this.setAccount(account);
          this.setContentProvider(provider);
 -        this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
 +        this.setStorageManager(new FileDataStorageManager(account, provider));
          try {
              this.initClientForCurrentAccount();
          } catch (IOException e) {
 -            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
 +            /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again
              mSyncResult.tooManyRetries = true;
              notifyFailedSynchronization();
              return;
          } catch (AccountsException e) {
 -            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
 +            /// the account is unknown for the Synchronization Manager, unreachable this context, or can not be authenticated; don't try this again
              mSyncResult.tooManyRetries = true;
              notifyFailedSynchronization();
              return;
              updateOCVersion();
              mCurrentSyncTime = System.currentTimeMillis();
              if (!mCancellation) {
 -                fetchData(OCFile.PATH_SEPARATOR, DataStorageManager.ROOT_PARENT_ID);
 +                synchronizeFolder(getStorageManager().getFileByPath(OCFile.ROOT_PATH));
                  
              } else {
 -                Log_OC.d(TAG, "Leaving synchronization before any remote request due to cancellation was requested");
 +                Log_OC.d(TAG, "Leaving synchronization before synchronizing the root folder because cancelation request");
              }
              
              
                  
                  /// notify the user about the failure of MANUAL synchronization
                  notifyFailedSynchronization();
 -                
              }
              if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
                  notifyFailsInFavourites();
              }
              if (mForgottenLocalFiles.size() > 0) {
                  notifyForgottenLocalFiles();
 -                
              }
              sendStickyBroadcast(false, null, mLastFailedResult);        // message to signal the end to the UI
          }
      /**
       * Called by system SyncManager when a synchronization is required to be cancelled.
       * 
 -     * Sets the mCancellation flag to 'true'. THe synchronization will be stopped when before a new folder is fetched. Data of the last folder
 -     * fetched will be still saved in the database. See onPerformSync implementation.
 +     * Sets the mCancellation flag to 'true'. THe synchronization will be stopped later, 
 +     * before a new folder is fetched. Data of the last folder synchronized will be still 
 +     * locally saved. 
 +     * 
 +     * See {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)}
 +     * and {@link #synchronizeFolder(String, long)}.
       */
      @Override
      public void onSyncCanceled() {
      
      
      /**
 -     * Synchronize the properties of files and folders contained in a remote folder given by remotePath.
 +     *  Synchronizes the list of files contained in a folder identified with its remote path.
 +     *  
 +     *  Fetches the list and properties of the files contained in the given folder, including their 
 +     *  properties, and updates the local database with them.
 +     *  
 +     *  Enters in the child folders to synchronize their contents also, following a recursive
 +     *  depth first strategy. 
       * 
 -     * @param remotePath        Remote path to the folder to synchronize.
 -     * @param parentId          Database Id of the folder to synchronize.
 +     *  @param folder                   Folder to synchronize.
       */
 -    private void fetchData(String remotePath, long parentId) {
 +    private void synchronizeFolder(OCFile folder) {
          
          if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
              return;
          
 -        // perform folder synchronization
 -        SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation(  remotePath, 
 +        /*
 +        OCFile folder, 
 +        long currentSyncTime, 
 +        boolean updateFolderProperties,
 +        boolean syncFullAccount,
 +        DataStorageManager dataStorageManager, 
 +        Account account, 
 +        Context context ) {
 +            
 +        }
 +        */
 +        // folder synchronization
 +        SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation(  folder, 
                                                                                      mCurrentSyncTime, 
 -                                                                                    parentId, 
 +                                                                                    true,
                                                                                      getStorageManager(), 
                                                                                      getAccount(), 
                                                                                      getContext()
          
          
          // synchronized folder -> notice to UI - ALWAYS, although !result.isSuccess
 -        sendStickyBroadcast(true, remotePath, null);
 +        sendStickyBroadcast(true, folder.getRemotePath(), null);
          
 +        // check the result of synchronizing the folder
          if (result.isSuccess() || result.getCode() == ResultCode.SYNC_CONFLICT) {
              
              if (result.getCode() == ResultCode.SYNC_CONFLICT) {
              if (synchFolderOp.getForgottenLocalFiles().size() > 0) {
                  mForgottenLocalFiles.putAll(synchFolderOp.getForgottenLocalFiles());
              }
 -            // synchronize children folders 
 -            List<OCFile> children = synchFolderOp.getChildren();
 -            fetchChildren(children);    // beware of the 'hidden' recursion here!
 -            
 -            sendStickyBroadcast(true, remotePath, null);
 +            if (result.isSuccess()) {
 +                // synchronize children folders 
 +                List<OCFile> children = synchFolderOp.getChildren();
 +                fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged());    // beware of the 'hidden' recursion here!
 +            }
              
          } else {
 +            // in failures, the statistics for the global result are updated
              if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
 -                   // (result.isTemporalRedirection() && result.isIdPRedirection() &&
                      ( result.isIdPRedirection() && 
-                             AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))) {
+                             MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
                  mSyncResult.stats.numAuthExceptions++;
                  
              } else if (result.getException() instanceof DavException) {
      }
  
      /**
 -     * Synchronize data of folders in the list of received files
 +     * Triggers the synchronization of any folder contained in the list of received files.
       * 
 -     * @param files         Files to recursively fetch 
 +     * @param files         Files to recursively synchronize.
       */
 -    private void fetchChildren(List<OCFile> files) {
 +    private void fetchChildren(OCFile parent, List<OCFile> files, boolean parentEtagChanged) {
          int i;
 +        OCFile newFile = null;
 +        String etag = null;
 +        boolean syncDown = false;
          for (i=0; i < files.size() && !mCancellation; i++) {
 -            OCFile newFile = files.get(i);
 -            if (newFile.isDirectory()) {
 -                fetchData(newFile.getRemotePath(), newFile.getFileId());
 -                
 -                // Update folder size on DB
 -                getStorageManager().calculateFolderSize(newFile.getFileId());                   
 +            newFile = files.get(i);
 +            if (newFile.isFolder()) {
 +                etag = newFile.getEtag();
 +                syncDown = (parentEtagChanged || etag == null || etag.length() == 0);
 +                if(syncDown) {
 +                    synchronizeFolder(newFile);
 +                    // update the size of the parent folder again after recursive synchronization 
 +                    //getStorageManager().updateFolderSize(parent.getFileId());  
 +                    sendStickyBroadcast(true, parent.getRemotePath(), null);        // notify again to refresh size in UI
 +                }
              }
          }
         
 -        if (mCancellation && i <files.size()) Log_OC.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " because cancelation request");
 +        if (mCancellation && i <files.size()) Log_OC.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " due to cancelation request");
      }
  
      
       * @param dirRemotePath     Remote path of a folder that was just synchronized (with or without success)
       */
      private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
-         Intent i = new Intent(FileSyncService.SYNC_MESSAGE);
+         FileSyncService fileSyncService = new FileSyncService();
+         
+         Intent i = new Intent(fileSyncService.getSyncMessage());
          i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
          i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name);
          if (dirRemotePath != null) {
                                               (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
                                                  // (mLastFailedResult.isTemporalRedirection() && mLastFailedResult.isIdPRedirection() && 
                                                  ( mLastFailedResult.isIdPRedirection() && 
-                                                  AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE.equals(getClient().getAuthTokenType()))
+                                                  MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
                                               )
                                             );
          // TODO put something smart in the contentIntent below for all the possible errors
@@@ -22,21 -22,21 +22,24 @@@ import android.content.Intent
  import android.os.IBinder;\r
  \r
  /**\r
 - * Background service for syncing files to our local Database\r
 + * Background service for synchronizing remote files with their local state.\r
   * \r
 - * @author Bartek Przybylski\r
 + * Serves as a connector to an instance of {@link FileSyncAdapter}, as required by standard Android APIs. \r
   * \r
 + * @author Bartek Przybylski\r
 + * @author David A. Velasco\r
   */\r
  public class FileSyncService extends Service {\r
 +    \r
      public static final String SYNC_MESSAGE = "ACCOUNT_SYNC";\r
      public static final String SYNC_FOLDER_REMOTE_PATH = "SYNC_FOLDER_REMOTE_PATH";\r
      public static final String IN_PROGRESS = "SYNC_IN_PROGRESS";\r
      public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
      public static final String SYNC_RESULT = "SYNC_RESULT";\r
  \r
+     public String getSyncMessage(){\r
+         return getClass().getName().toString() + SYNC_MESSAGE;\r
+     }\r
      /*\r
       * {@inheritDoc}\r
       */\r
@@@ -51,5 -51,4 +54,5 @@@
      public IBinder onBind(Intent intent) {\r
         return new FileSyncAdapter(getApplicationContext(), true).getSyncAdapterBinder();\r
      }\r
 +    \r
  }\r
@@@ -22,8 -22,8 +22,8 @@@ import java.io.File
  
  import android.accounts.Account;
  import android.app.AlertDialog;
 -import android.app.ProgressDialog;
  import android.app.Dialog;
 +import android.app.ProgressDialog;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.ContentResolver;
@@@ -58,8 -58,9 +58,8 @@@ import com.actionbarsherlock.view.MenuI
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
  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.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
@@@ -71,22 -72,21 +71,21 @@@ import com.owncloud.android.operations.
  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.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 +import com.owncloud.android.operations.SynchronizeFolderOperation;
  import com.owncloud.android.syncadapter.FileSyncService;
  import com.owncloud.android.ui.dialog.EditNameDialog;
 +import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
  import com.owncloud.android.ui.dialog.LoadingDialog;
  import com.owncloud.android.ui.dialog.SslValidatorDialog;
 -import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
  import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
  import com.owncloud.android.ui.fragment.FileDetailFragment;
  import com.owncloud.android.ui.fragment.FileFragment;
  import com.owncloud.android.ui.fragment.OCFileListFragment;
  import com.owncloud.android.ui.preview.PreviewImageActivity;
--import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
  import com.owncloud.android.ui.preview.PreviewVideoActivity;
  
@@@ -103,7 -103,7 +102,7 @@@ OCFileListFragment.ContainerActivity, F
      private ArrayAdapter<String> mDirectories;
  
      /** Access point to the cached database for the current ownCloud {@link Account} */
 -    private DataStorageManager mStorageManager = null;
 +    private FileDataStorageManager mStorageManager = null;
  
      private SyncBroadcastReceiver mSyncBroadcastReceiver;
      private UploadFinishReceiver mUploadFinishReceiver;
      private View mRightFragmentContainer;
  
      private static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
 +    private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS";
  
      public static final int DIALOG_SHORT_WAIT = 0;
      private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1;
      private OCFile mWaitingToPreview;
      private Handler mHandler;
      
 +    private boolean mSyncInProgress = false;
+     private String mDownloadAddedMessage;
+     private String mDownloadFinishMessage;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid
  
          mHandler = new Handler();
+         
+         FileDownloader downloader = new FileDownloader();
+         mDownloadAddedMessage = downloader.getDownloadAddedMessage();
+         mDownloadFinishMessage= downloader.getDownloadFinishMessage();
  
          /// bindings to transference services
          mUploadConnection = new ListServiceConnection(); 
          /// Load of saved instance state
          if(savedInstanceState != null) {
              mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW);
 -
 +            mSyncInProgress = savedInstanceState.getBoolean(KEY_SYNC_IN_PROGRESS);
 +           
          } else {
              mWaitingToPreview = null;
 -        }
 +            mSyncInProgress = false;
 +        }        
  
          /// USER INTERFACE
  
          // Action bar setup
          mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
          getSupportActionBar().setHomeButtonEnabled(true);       // mandatory since Android ICS, according to the official documentation
 -        setSupportProgressBarIndeterminateVisibility(false);    // always AFTER setContentView(...) ; to work around bug in its implementation
 +        setSupportProgressBarIndeterminateVisibility(mSyncInProgress);    // always AFTER setContentView(...) ; to work around bug in its implementation        
          
+         
+         
          Log_OC.d(TAG, "onCreate() end");
      }
  
              }
              if (file == null) {
                  // fall back to root folder
 -                file = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);  // never returns null
 +                file = mStorageManager.getFileByPath(OCFile.ROOT_PATH);  // never returns null
              }
              setFile(file);
 -            mDirectories.clear();
 -            OCFile fileIt = file;
 -            while(fileIt != null && fileIt.getFileName() != OCFile.PATH_SEPARATOR) {
 -                if (fileIt.isDirectory()) {
 -                    mDirectories.add(fileIt.getFileName());
 -                }
 -                // get parent from path
 -                parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName()));
 -                fileIt = mStorageManager.getFileByPath(parentPath);
 -            }
 -            mDirectories.add(OCFile.PATH_SEPARATOR);
 +            setNavigationListWithFolder(file);
              if (!stateWasRecovered) {
                  Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
                  initFragmentsWithFile();
 +                if (file.isFolder()) {
 +                    startSyncFolderOperation(file);
 +                }
                  
              } else {
 -                updateFragmentsVisibility(!file.isDirectory());
 -                updateNavigationElementsInActionBar(file.isDirectory() ? null : file);
 +                updateFragmentsVisibility(!file.isFolder());
 +                updateNavigationElementsInActionBar(file.isFolder() ? null : file);
              }
              
              
      }
  
  
 +    private void setNavigationListWithFolder(OCFile file) {
 +        mDirectories.clear();
 +        OCFile fileIt = file;
 +        String parentPath;
 +        while(fileIt != null && fileIt.getFileName() != OCFile.ROOT_PATH) {
 +            if (fileIt.isFolder()) {
 +                mDirectories.add(fileIt.getFileName());
 +            }
 +            //fileIt = mStorageManager.getFileById(fileIt.getParentId());
 +            // get parent from path
 +            parentPath = fileIt.getRemotePath().substring(0, fileIt.getRemotePath().lastIndexOf(fileIt.getFileName()));
 +            fileIt = mStorageManager.getFileByPath(parentPath);
 +        }
 +        mDirectories.add(OCFile.PATH_SEPARATOR);
 +    }
 +
 +
      private void createMinFragments() {
          OCFileListFragment listOfFiles = new OCFileListFragment();
          FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  
      private Fragment chooseInitialSecondFragment(OCFile file) {
          Fragment secondFragment = null;
 -        if (file != null && !file.isDirectory()) {
 +        if (file != null && !file.isFolder()) {
              if (file.isDown() && PreviewMediaFragment.canBePreviewed(file) 
                      && file.getLastSyncDateForProperties() > 0  // temporal fix
                      ) {
                  // the user browsed to other file ; forget the automatic preview 
                  mWaitingToPreview = null;
  
-             } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
+             } else if (downloadEvent.equals(mDownloadAddedMessage)) {
                  // grant that the right panel updates the progress bar
                  detailsFragment.listenForTransferProgress();
                  detailsFragment.updateFileDetails(true, false);
  
-             } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+             } else if (downloadEvent.equals(mDownloadFinishMessage)) {
                  //  update the right panel
                  boolean detailsFragmentChanged = false;
                  if (waitedPreview) {
              FileFragment second = getSecondFragment();
              OCFile currentDir = getCurrentDir();
              if((currentDir != null && currentDir.getParentId() != 0) || 
 -                    (second != null && second.getFile() != null)) {
 +                    (second != null && second.getFile() != null)) {                
                  onBackPressed(); 
 +                
              }
              break;
          }
      }
  
      private void startSynchronization() {
-         ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY);   // cancel the current synchronizations of any ownCloud account
+         ContentResolver.cancelSync(null, MainApp.getAuthTokenType());   // cancel the current synchronizations of any ownCloud account
          Bundle bundle = new Bundle();
          bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
          ContentResolver.requestSync(
                  getAccount(),
-                 AccountAuthenticator.AUTHORITY, bundle);
+                 MainApp.getAuthTokenType(), bundle);
      }
  
  
      @Override
      public boolean onNavigationItemSelected(int itemPosition, long itemId) {
 -        int i = itemPosition;
 -        while (i-- != 0) {
 -            onBackPressed();
 -        }
 -        // the next operation triggers a new call to this method, but it's necessary to 
 -        // ensure that the name exposed in the action bar is the current directory when the 
 -        // user selected it in the navigation list
 -        if (itemPosition != 0)
 +        if (itemPosition != 0) {
 +            String targetPath = "";
 +            for (int i=itemPosition; i < mDirectories.getCount() - 1; i++) {
 +                targetPath = mDirectories.getItem(i) + OCFile.PATH_SEPARATOR + targetPath; 
 +            }
 +            targetPath = OCFile.PATH_SEPARATOR + targetPath;
 +            OCFile targetFolder = mStorageManager.getFileByPath(targetPath);
 +            if (targetFolder != null) {
 +                browseTo(targetFolder);
 +            }
 +            
 +            // the next operation triggers a new call to this method, but it's necessary to 
 +            // ensure that the name exposed in the action bar is the current directory when the 
 +            // user selected it in the navigation list
              getSupportActionBar().setSelectedNavigationItem(0);
 +        }
          return true;
      }
  
                      finish();
                      return;
                  }
 -                popDirname();
 -                listOfFiles.onBrowseUp();
 +                int levelsUp = listOfFiles.onBrowseUp();
 +                for (int i=0; i < levelsUp && mDirectories.getCount() > 1 ; i++) {
 +                    popDirname();
 +                }
              }
          }
          if (listOfFiles != null) {  // should never be null, indeed
              setFile(listOfFiles.getCurrentFile());
          }
          cleanSecondFragment();
 +
      }
  
      @Override
          Log_OC.e(TAG, "onSaveInstanceState() start");
          super.onSaveInstanceState(outState);
          outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
 +        outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
 +
          Log_OC.d(TAG, "onSaveInstanceState() end");
      }
      
          super.onResume();
          Log_OC.e(TAG, "onResume() start");
  
+         FileUploader fileUploader = new FileUploader();
+         FileSyncService fileSyncService = new FileSyncService();
+         
          // Listen for sync messages
-         IntentFilter syncIntentFilter = new IntentFilter(FileSyncService.SYNC_MESSAGE);
+         IntentFilter syncIntentFilter = new IntentFilter(fileSyncService.getSyncMessage());
          mSyncBroadcastReceiver = new SyncBroadcastReceiver();
          registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
  
          // Listen for upload messages
-         IntentFilter uploadIntentFilter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+         IntentFilter uploadIntentFilter = new IntentFilter(fileUploader.getUploadFinishMessage());
          mUploadFinishReceiver = new UploadFinishReceiver();
          registerReceiver(mUploadFinishReceiver, uploadIntentFilter);
  
          // Listen for download messages
-         IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
-         downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+         IntentFilter downloadIntentFilter = new IntentFilter(mDownloadAddedMessage);
+         downloadIntentFilter.addAction(mDownloadFinishMessage);
          mDownloadFinishReceiver = new DownloadFinishReceiver();
          registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
      
      /**
       * Pushes a directory to the drop down list
       * @param directory to push
 -     * @throws IllegalArgumentException If the {@link OCFile#isDirectory()} returns false.
 +     * @throws IllegalArgumentException If the {@link OCFile#isFolder()} returns false.
       */
      public void pushDirname(OCFile directory) {
 -        if(!directory.isDirectory()){
 +        if(!directory.isFolder()){
              throw new IllegalArgumentException("Only directories may be pushed!");
          }
          mDirectories.insert(directory.getFileName(), 0);
          public void onReceive(Context context, Intent intent) {
              boolean inProgress = intent.getBooleanExtra(FileSyncService.IN_PROGRESS, false);
              String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
 -
 -            Log_OC.d(TAG, "sync of account " + accountName + " is in_progress: " + inProgress);
 +            RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
  
              if (getAccount() != null && accountName.equals(getAccount().name)
                      && mStorageManager != null
  
                  String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH); 
  
 -                boolean fillBlankRoot = false;
 -                OCFile currentDir = getCurrentDir();
 -                if (currentDir == null) {
 -                    currentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
 -                    fillBlankRoot = (currentDir != null);                   
 -                }
 +                OCFile currentFile = (getFile() == null) ? null : mStorageManager.getFileByPath(getFile().getRemotePath());
 +                OCFile currentDir = (getCurrentDir() == null) ? null : mStorageManager.getFileByPath(getCurrentDir().getRemotePath());
  
 -                if ((synchFolderRemotePath != null && currentDir != null && (currentDir.getRemotePath().equals(synchFolderRemotePath)))
 -                        || fillBlankRoot ) {
 -                    if (!fillBlankRoot) 
 -                        currentDir = mStorageManager.getFileByPath(synchFolderRemotePath);
 -                    OCFileListFragment fileListFragment = getListOfFilesFragment();
 -                    if (fileListFragment != null) {
 -                        fileListFragment.listDirectory(currentDir);
 +                if (currentDir == null) {
 +                    // current folder was removed from the server 
 +                    Toast.makeText( FileDisplayActivity.this, 
 +                                    String.format(getString(R.string.sync_current_folder_was_removed), mDirectories.getItem(0)), 
 +                                    Toast.LENGTH_LONG)
 +                        .show();
 +                    browseToRoot();
 +                    
 +                } else {
 +                    if (currentFile == null && !getFile().isFolder()) {
 +                        // currently selected file was removed in the server, and now we know it
 +                        cleanSecondFragment();
 +                        currentFile = currentDir;
                      }
 -                    if (getSecondFragment() == null)
 -                        setFile(currentDir);
 +                
 +                    if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) {
 +                        OCFileListFragment fileListFragment = getListOfFilesFragment();
 +                        if (fileListFragment != null) {
 +                            fileListFragment.listDirectory(currentDir);
 +                        }
 +                    }
 +                    setFile(currentFile);
                  }
                  
                  setSupportProgressBarIndeterminateVisibility(inProgress);
                  removeStickyBroadcast(intent);
 +                mSyncInProgress = inProgress;
  
              }
 -
 -            RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
 +            
              if (synchResult != null) {
                  if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
                      mLastSslUntrustedServerResult = synchResult;
              }
          }
      }
 -
 +    
  
      private class UploadFinishReceiver extends BroadcastReceiver {
          /**
       * {@inheritDoc}
       */
      @Override
 -    public DataStorageManager getStorageManager() {
 +    public FileDataStorageManager getStorageManager() {
          return mStorageManager;
      }
  
  
 +    public void browseToRoot() {
 +        OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +        if (listOfFiles != null) {  // should never be null, indeed
 +            while (mDirectories.getCount() > 1) {
 +                popDirname();
 +            }
 +            OCFile root = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
 +            listOfFiles.listDirectory(root);
 +            setFile(listOfFiles.getCurrentFile());
 +            startSyncFolderOperation(root);
 +        }
 +        cleanSecondFragment();
 +    }
 +    
 +    
 +    public void browseTo(OCFile folder) {
 +        if (folder == null || !folder.isFolder()) {
 +            throw new IllegalArgumentException("Trying to browse to invalid folder " + folder);
 +        }
 +        OCFileListFragment listOfFiles = getListOfFilesFragment(); 
 +        if (listOfFiles != null) {
 +            setNavigationListWithFolder(folder);
 +            listOfFiles.listDirectory(folder);
 +            setFile(listOfFiles.getCurrentFile());
 +            startSyncFolderOperation(folder);
 +        } else {
 +            Log_OC.e(TAG, "Unexpected null when accessing list fragment");
 +        }
 +        cleanSecondFragment();
 +    }
 +
 +
      /**
       * {@inheritDoc}
       * 
      public void onBrowsedDownTo(OCFile directory) {
          pushDirname(directory);
          cleanSecondFragment();
 +        
 +        // Sync Folder
 +        startSyncFolderOperation(directory);
 +        
      }
  
      /**
      }
  
  
 +//    private void updateDisplayHomeAtSync(){
 +//        ActionBar actionBar = getSupportActionBar();
 +//        OCFile currentDir = getCurrentDir();
 +//        if (currentDir.getParentId() != DataStorageManager.ROOT_PARENT_ID) {
 +//            actionBar.setHomeButtonEnabled(!mSyncInProgress);
 +//            actionBar.setDisplayHomeAsUpEnabled(!mSyncInProgress);
 +//        }
 +//        else {
 +//            actionBar.setHomeButtonEnabled(true);
 +//            actionBar.setDisplayHomeAsUpEnabled(false);
 +//        }
 +//    }
 +//    
      /**
       * {@inheritDoc}
       */
  
          } else if (operation instanceof CreateFolderOperation) {
              onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
 -        }
 +            
 +        } 
      }
  
  
              refeshListOfFilesFragment();
  
          } else {
 -            //dismissDialog(DIALOG_SHORT_WAIT);
              dismissLoadingDialog();
              try {
                  Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG); 
                  i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, getAccount());
                  startActivity(i);
  
 -            } else {
 -                Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG); 
 -                msg.show();
 -            }
 +            } 
  
          } else {
              if (operation.transferWasRequested()) {
      private OCFile getCurrentDir() {
          OCFile file = getFile();
          if (file != null) {
 -            if (file.isDirectory()) {
 +            if (file.isFolder()) {
                  return file;
              } else if (mStorageManager != null) {
                  String parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
          }
          return null;
      }
 +    
 +    public void startSyncFolderOperation(OCFile folder) {
 +        long currentSyncTime = System.currentTimeMillis(); 
 +        
 +        mSyncInProgress = true;
 +                
 +        // perform folder synchronization
 +        RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
 +                                                                        currentSyncTime, 
 +                                                                        false,
 +                                                                        getStorageManager(), 
 +                                                                        getAccount(), 
 +                                                                        getApplicationContext()
 +                                                                      );
 +        synchFolderOp.execute(getAccount(), this, null, null, this);
 +        
 +        setSupportProgressBarIndeterminateVisibility(true);
 +    }
  
 +    
 +//    public void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
 +//        int childCount = viewGroup.getChildCount();
 +//        for (int i = 0; i < childCount; i++) {
 +//          View view = viewGroup.getChildAt(i);
 +//          view.setEnabled(enabled);
 +//          view.setClickable(!enabled);
 +//          if (view instanceof ViewGroup) {
 +//            enableDisableViewGroup((ViewGroup) view, enabled);
 +//          }
 +//        }
 +//      }
  }
@@@ -207,7 -207,8 +207,8 @@@ public class FileDetailFragment extend
      public void onResume() {
          super.onResume();
          mUploadFinishReceiver = new UploadFinishReceiver();
-         IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+         FileUploader fileUploader = new FileUploader();
+         IntentFilter filter = new IntentFilter(fileUploader.getUploadFinishMessage());
          getActivity().registerReceiver(mUploadFinishReceiver, filter);
  
      }
      private void renameFile() {
          OCFile file = getFile();
          String fileName = file.getFileName();
 -        int extensionStart = file.isDirectory() ? -1 : fileName.lastIndexOf(".");
 +        int extensionStart = file.isFolder() ? -1 : fileName.lastIndexOf(".");
          int selectionEnd = (extensionStart >= 0) ? extensionStart : fileName.length();
          EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), fileName, 0, selectionEnd, this);
          dialog.show(getFragmentManager(), "nameeditdialog");
              }
              
          } else {
 -            mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, false, getActivity());
 +            mLastRemoteOperation = new SynchronizeFileOperation(file, null, mStorageManager, mAccount, true, getActivity());
              mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
              
              // update ui 
                  i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);
                  startActivity(i);
                  
 -            } else {
 -                Toast msg = Toast.makeText(getActivity(), R.string.sync_file_fail_msg, Toast.LENGTH_LONG); 
 -                msg.show();
 -            }
 +            } 
              
              if (file.isDown()) {
                  setButtonsForDown();
@@@ -36,6 -36,7 +36,6 @@@ import com.actionbarsherlock.app.Action
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
  import com.owncloud.android.authentication.AccountUtils;
 -import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
@@@ -66,7 -67,7 +66,7 @@@ public class PreviewImageActivity exten
      
      private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
      
 -    private DataStorageManager mStorageManager;
 +    private FileDataStorageManager mStorageManager;
      
      private ViewPager mViewPager; 
      private PreviewImagePagerAdapter mPreviewImagePagerAdapter;    
  
      private boolean mFullScreen;
      
+     private String mDownloadAddedMessage;
+     private String mDownloadFinishMessage;
+     
+     
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          } else {
              mRequestWaitingForBinder = false;
          }
+         
+         FileDownloader downloader = new FileDownloader();
+         mDownloadAddedMessage = downloader.getDownloadAddedMessage();
+         mDownloadFinishMessage= downloader.getDownloadFinishMessage();
      }
  
      private void initViewPager() {
          //OCFile parentFolder = mStorageManager.getFileById(getFile().getParentId());
          if (parentFolder == null) {
              // should not be necessary
 -            parentFolder = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
 +            parentFolder = mStorageManager.getFileByPath(OCFile.ROOT_PATH);
          }
          mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), mStorageManager);
          mViewPager = (ViewPager) findViewById(R.id.fragmentPager);
          super.onResume();
          //Log.e(TAG, "ACTIVITY, ONRESUME");
          mDownloadFinishReceiver = new DownloadFinishReceiver();
-         IntentFilter filter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
-         filter.addAction(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+         
+         IntentFilter filter = new IntentFilter(mDownloadFinishMessage);
+         filter.addAction(mDownloadAddedMessage);
          registerReceiver(mDownloadFinishReceiver, filter);
      }
  
                  boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
                  //boolean isOffscreen =  Math.abs((mViewPager.getCurrentItem() - position)) <= mViewPager.getOffscreenPageLimit();
                  
-                 if (position >= 0 && intent.getAction().equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+                 if (position >= 0 && intent.getAction().equals(mDownloadFinishMessage)) {
                      if (downloadWasFine) {
                          mPreviewImagePagerAdapter.updateFile(position, file);   
                          
              mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());            
              
              // Update file according to DB file, if it is possible
 -            if (file.getFileId() > DataStorageManager.ROOT_PARENT_ID)            
 +            if (file.getFileId() > FileDataStorageManager.ROOT_PARENT_ID)            
                  file = mStorageManager.getFileById(file.getFileId());
              
              if (file != null) {
@@@ -42,8 -42,8 +42,8 @@@ import org.apache.http.HttpStatus
  import org.apache.http.params.CoreProtocolPNames;
  
  import com.owncloud.android.Log_OC;
+ import com.owncloud.android.MainApp;
  
- import com.owncloud.android.authentication.AccountAuthenticator;
  import com.owncloud.android.network.BearerAuthScheme;
  import com.owncloud.android.network.BearerCredentials;
  
@@@ -72,7 -72,7 +72,7 @@@ public class WebdavClient extends HttpC
          getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
          mFollowRedirects = true;
          mSsoSessionCookie = null;
-         mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
+         mAuthTokenType = MainApp.getAuthTokenTypePass();
      }
  
      public void setBearerCredentials(String accessToken) {
@@@ -85,7 -85,7 +85,7 @@@
          mCredentials = new BearerCredentials(accessToken);
          getState().setCredentials(AuthScope.ANY, mCredentials);
          mSsoSessionCookie = null;
-         mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN;
+         mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();
      }
  
      public void setBasicCredentials(String username, String password) {
@@@ -97,7 -97,7 +97,7 @@@
          mCredentials = new UsernamePasswordCredentials(username, password);
          getState().setCredentials(AuthScope.ANY, mCredentials);
          mSsoSessionCookie = null;
-         mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD;
+         mAuthTokenType = MainApp.getAuthTokenTypePass();
      }
      
      public void setSsoSessionCookie(String accessToken) {
          getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
          mSsoSessionCookie = accessToken;
          mCredentials = null;
-         mAuthTokenType = AccountAuthenticator.AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE;
+         mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();
      }
      
      
          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 (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) {