Merge branch 'develop' into loggingtool
authorDavid A. Velasco <dvelasco@solidgear.es>
Mon, 15 Apr 2013 11:12:04 +0000 (13:12 +0200)
committerDavid A. Velasco <dvelasco@solidgear.es>
Mon, 15 Apr 2013 11:12:04 +0000 (13:12 +0200)
Conflicts:
AndroidManifest.xml
res/menu/main_menu.xml
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/InstantUploadService.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/ui/activity/FileDetailActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/UploadFilesActivity.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java
src/eu/alefzero/webdav/FileRequestEntity.java
src/eu/alefzero/webdav/WebdavClient.java

23 files changed:
1  2 
AndroidManifest.xml
res/values/strings.xml
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/db/DbHandler.java
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/files/services/InstantUploadService.java
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
src/com/owncloud/android/operations/DownloadFileOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/ui/activity/FileDetailActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/InstantUploadActivity.java
src/com/owncloud/android/ui/activity/UploadFilesActivity.java
src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java
src/eu/alefzero/webdav/FileRequestEntity.java
src/eu/alefzero/webdav/WebdavClient.java

diff --combined AndroidManifest.xml
 -<?xml version="1.0" encoding="utf-8"?>\r
 -<!-- \r
 -  ownCloud Android client application\r
 -\r
 -  Copyright (C) 2012  Bartek Przybylski\r
 -  Copyright (C) 2012-2013 ownCloud Inc.\r
 -\r
 -  This program is free software: you can redistribute it and/or modify\r
 -  it under the terms of the GNU General Public License as published by\r
 -  the Free Software Foundation, either version 2 of the License, or\r
 -  (at your option) any later version.\r
 -\r
 -  This program is distributed in the hope that it will be useful,\r
 -  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 -  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
 -  GNU General Public License for more details.\r
 -\r
 -  You should have received a copy of the GNU General Public License\r
 -  along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - -->\r
 -<manifest package="com.owncloud.android"\r
 -    android:versionCode="104000"\r
 -    android:versionName="1.4.0" xmlns:android="http://schemas.android.com/apk/res/android">\r
 -\r
 -    <uses-permission android:name="android.permission.GET_ACCOUNTS" />\r
 -    <uses-permission android:name="android.permission.USE_CREDENTIALS" />\r
 -    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />\r
 -    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />\r
 -    <uses-permission android:name="android.permission.INTERNET" />\r
 -    <uses-permission android:name="android.permission.WRITE_SETTINGS" />\r
 -    <uses-permission android:name="android.permission.READ_SYNC_STATS" />\r
 -    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />\r
 -    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />\r
 -    <uses-permission android:name="android.permission.BROADCAST_STICKY" />\r
 -    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />\r
 -    <uses-permission android:name="android.permission.READ_PHONE_STATE" />\r
 -    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>\r
 -    <uses-permission android:name="android.permission.WAKE_LOCK"/>\r
 -    \r
 -    <uses-sdk\r
 -        android:minSdkVersion="8"\r
 -        android:targetSdkVersion="13" />\r
 -\r
 -    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >\r
 -    </uses-permission>\r
 -\r
 -    <application\r
 -        android:icon="@drawable/icon"\r
 -        android:label="@string/app_name"\r
 -        android:theme="@style/Theme.ownCloud"> \r
 -        <activity\r
 -            android:name=".ui.activity.FileDisplayActivity"\r
 -            android:label="@string/app_name">\r
 -            <intent-filter>\r
 -                <action android:name="android.intent.action.MAIN" />\r
 -\r
 -                <category android:name="android.intent.category.LAUNCHER" />\r
 -            </intent-filter>\r
 -        </activity>\r
 -        <activity android:name=".ui.activity.UploadFilesActivity">\r
 -        </activity>\r
 -              <activity android:name=".ui.activity.InstantUploadActivity">\r
 -        </activity>\r
 -        <activity android:name=".ui.activity.FailedUploadActivity" android:theme="@android:style/Theme.Dialog" android:excludeFromRecents="true"/>\r
 -        <activity android:name=".Uploader" >\r
 -            <intent-filter>\r
 -                <action android:name="android.intent.action.SEND" >\r
 -                </action>\r
 -\r
 -                <category android:name="android.intent.category.DEFAULT" >\r
 -                </category>\r
 -\r
 -                <data android:mimeType="*/*" >\r
 -                </data>\r
 -            </intent-filter>\r
 -            <intent-filter>\r
 -                <action android:name="android.intent.action.SEND_MULTIPLE" >\r
 -                </action>\r
 -\r
 -                <category android:name="android.intent.category.DEFAULT" >\r
 -                </category>\r
 -\r
 -                <data android:mimeType="*/*" >\r
 -                </data>\r
 -            </intent-filter>\r
 -        </activity>\r
 -        <activity\r
 -            android:name=".ui.activity.Preferences"\r
 -            android:theme="@style/Theme.ownCloud" >\r
 -        </activity>\r
 -        <activity android:name=".ui.activity.PreferencesNewSessionewSession" >\r
 -        </activity>\r
 -        \r
 -              <activity       android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />\r
 -                      \r
 -        <activity     android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"\r
 -                                      android:label="@string/app_name"\r
 -                                      android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >\r
 -              </activity>        \r
 -\r
 -        <service\r
 -            android:name=".authenticator.AccountAuthenticatorService"\r
 -            android:exported="true">\r
 -            <intent-filter  android:priority="100">\r
 -                <action android:name="android.accounts.AccountAuthenticator" />\r
 -            </intent-filter>\r
 -\r
 -            <meta-data\r
 -                android:name="android.accounts.AccountAuthenticator"\r
 -                android:resource="@xml/authenticator" />\r
 -        </service>\r
 -        <service\r
 -            android:name=".syncadapter.FileSyncService"\r
 -            android:exported="true" >\r
 -            <intent-filter>\r
 -                <action android:name="android.content.SyncAdapter" />\r
 -            </intent-filter>\r
 -\r
 -            <meta-data\r
 -                android:name="android.content.SyncAdapter"\r
 -                android:resource="@xml/syncadapter_files" />\r
 -        </service>\r
 -\r
 -        <provider\r
 -            android:name=".providers.FileContentProvider"\r
 -            android:authorities="org.owncloud"\r
 -            android:enabled="true"\r
 -            android:exported="false"\r
 -            android:label="@string/sync_string_files"\r
 -            android:syncable="true" >\r
 -        </provider>\r
 -\r
 -        <activity\r
 -            android:name=".ui.activity.AuthenticatorActivity"\r
 -            android:exported="true"\r
 -            android:theme="@style/Theme.ownCloud.noActionBar" >\r
 -            <intent-filter>\r
 -                <action android:name="com.owncloud.android.workaround.accounts.CREATE" />\r
 -                <category android:name="android.intent.category.DEFAULT" />\r
 -            </intent-filter>\r
 -        </activity>\r
 -\r
 -        <service android:name=".files.services.FileDownloader" />\r
 -        <service android:name=".files.services.FileUploader" />\r
 -        <service android:name=".media.MediaService" />\r
 -\r
 -        <activity android:name=".ui.activity.FileDetailActivity" />\r
 -        <activity android:name=".ui.activity.PinCodeActivity" />\r
 -        <activity android:name=".extensions.ExtensionsAvailableActivity"></activity>\r
 -        <activity android:name=".extensions.ExtensionsListActivity"></activity>\r
 -        <activity android:name=".ui.activity.AccountSelectActivity" android:uiOptions="none" android:label="@string/prefs_accounts"></activity>\r
 -        <activity android:name=".ui.activity.ConflictsResolveActivity"/>\r
 -        <activity android:name=".ui.activity.GenericExplanationActivity"/>\r
 -        <activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/>\r
 +<?xml version="1.0" encoding="utf-8"?>
 +<!-- 
 +  ownCloud Android client application
 +
 +  Copyright (C) 2012  Bartek Przybylski
 +  Copyright (C) 2012-2013 ownCloud Inc.
 +
 +  This program is free software: you can redistribute it and/or modify
 +  it under the terms of the GNU General Public License as published by
 +  the Free Software Foundation, either version 2 of the License, or
 +  (at your option) any later version.
 +
 +  This program is distributed in the hope that it will be useful,
 +  but WITHOUT ANY WARRANTY; without even the implied warranty of
 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 +  GNU General Public License for more details.
 +
 +  You should have received a copy of the GNU General Public License
 +  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + -->
 +<manifest package="com.owncloud.android"
-     android:versionCode="103020"
-     android:versionName="1.3.20" xmlns:android="http://schemas.android.com/apk/res/android">
++    android:versionCode="104000"
++    android:versionName="1.4.0" xmlns:android="http://schemas.android.com/apk/res/android">
 +
 +    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
 +    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
 +    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
 +    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
 +    <uses-permission android:name="android.permission.INTERNET" />
 +    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 +    <uses-permission android:name="android.permission.READ_SYNC_STATS" />
 +    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
 +    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
 +    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
 +    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 +    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 +    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
++    <uses-permission android:name="android.permission.WAKE_LOCK"/>
++    
 +    <uses-sdk
 +        android:minSdkVersion="8"
 +        android:targetSdkVersion="13" />
 +
 +    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
 +    </uses-permission>
 +
 +    <application
 +        android:icon="@drawable/icon"
 +        android:label="@string/app_name"
 +        android:theme="@style/Theme.ownCloud"> 
 +        <activity
 +            android:name=".ui.activity.FileDisplayActivity"
 +            android:label="@string/app_name">
 +            <intent-filter>
 +                <action android:name="android.intent.action.MAIN" />
 +
 +                <category android:name="android.intent.category.LAUNCHER" />
 +            </intent-filter>
 +        </activity>
 +        <activity android:name=".ui.activity.UploadFilesActivity">
 +        </activity>
 +              <activity android:name=".ui.activity.InstantUploadActivity">
 +        </activity>
++        <activity android:name=".ui.activity.FailedUploadActivity" android:theme="@android:style/Theme.Dialog" android:excludeFromRecents="true"/>
 +        <activity android:name=".Uploader" >
 +            <intent-filter>
 +                <action android:name="android.intent.action.SEND" >
 +                </action>
 +
 +                <category android:name="android.intent.category.DEFAULT" >
 +                </category>
 +
 +                <data android:mimeType="*/*" >
 +                </data>
 +            </intent-filter>
 +            <intent-filter>
 +                <action android:name="android.intent.action.SEND_MULTIPLE" >
 +                </action>
 +
 +                <category android:name="android.intent.category.DEFAULT" >
 +                </category>
 +
 +                <data android:mimeType="*/*" >
 +                </data>
 +            </intent-filter>
 +        </activity>
 +        <activity
 +            android:name=".ui.activity.Preferences"
 +            android:theme="@style/Theme.ownCloud" >
 +        </activity>
 +        <activity android:name=".ui.activity.PreferencesNewSessionewSession" >
 +        </activity>
++        
++              <activity       android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
++                      
++        <activity     android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"
++                                      android:label="@string/app_name"
++                                      android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
++              </activity>        
 +
 +        <service
 +            android:name=".authenticator.AccountAuthenticatorService"
 +            android:exported="true">
 +            <intent-filter  android:priority="100">
 +                <action android:name="android.accounts.AccountAuthenticator" />
 +            </intent-filter>
 +
 +            <meta-data
 +                android:name="android.accounts.AccountAuthenticator"
 +                android:resource="@xml/authenticator" />
 +        </service>
 +        <service
 +            android:name=".syncadapter.FileSyncService"
 +            android:exported="true" >
 +            <intent-filter>
 +                <action android:name="android.content.SyncAdapter" />
 +            </intent-filter>
 +
 +            <meta-data
 +                android:name="android.content.SyncAdapter"
 +                android:resource="@xml/syncadapter_files" />
 +        </service>
 +
 +        <provider
 +            android:name=".providers.FileContentProvider"
 +            android:authorities="org.owncloud"
 +            android:enabled="true"
 +            android:exported="false"
 +            android:label="@string/sync_string_files"
 +            android:syncable="true" >
 +        </provider>
 +
 +        <activity
 +            android:name=".ui.activity.AuthenticatorActivity"
 +            android:exported="true"
 +            android:theme="@style/Theme.ownCloud.noActionBar" >
 +            <intent-filter>
 +                <action android:name="com.owncloud.android.workaround.accounts.CREATE" />
 +                <category android:name="android.intent.category.DEFAULT" />
 +            </intent-filter>
 +        </activity>
 +
-         <service android:name=".files.services.FileDownloader" >
-         </service>
++        <service android:name=".files.services.FileDownloader" />
++        <service android:name=".files.services.FileUploader" />
++        <service android:name=".media.MediaService" />
++        
 +        <activity android:name=".ui.activity.FileDetailActivity" />
 +        <activity android:name=".ui.activity.PinCodeActivity" />
 +        <activity android:name=".extensions.ExtensionsAvailableActivity"></activity>
 +        <activity android:name=".extensions.ExtensionsListActivity"></activity>
 +        <activity android:name=".ui.activity.AccountSelectActivity" android:uiOptions="none" android:label="@string/prefs_accounts"></activity>
 +        <activity android:name=".ui.activity.ConflictsResolveActivity"/>
 +        <activity android:name=".ui.activity.GenericExplanationActivity"/>
 +        <activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/>
++        
 +        <activity android:name=".ui.activity.LogHistoryActivity"/>
          
-         <service android:name=".files.services.FileUploader" >
-         </service>
          <service android:name=".files.services.InstantUploadService" />
 -        <receiver android:name=".files.InstantUploadBroadcastReceiver">\r
 -            <intent-filter>\r
 -                <action android:name="com.android.camera.NEW_PICTURE" />\r
 -                <data android:mimeType="image/*" />\r
 -            </intent-filter>\r
 -            <intent-filter>\r
 -                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>\r
 -            </intent-filter>\r
 -        </receiver>\r
 -        <receiver android:name=".files.BootupBroadcastReceiver">\r
 -            <intent-filter>\r
 -                <action android:name="android.intent.action.BOOT_COMPLETED"/>\r
 -            </intent-filter>\r
 -        </receiver>\r
 -        <service android:name=".files.services.FileObserverService"/>\r
 -    </application>\r
 -\r
 -</manifest>\r
 +        <receiver android:name=".files.InstantUploadBroadcastReceiver">
 +            <intent-filter>
 +                <action android:name="com.android.camera.NEW_PICTURE" />
 +                <data android:mimeType="image/*" />
 +            </intent-filter>
 +            <intent-filter>
 +                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
 +            </intent-filter>
 +        </receiver>
 +        <receiver android:name=".files.BootupBroadcastReceiver">
 +            <intent-filter>
 +                <action android:name="android.intent.action.BOOT_COMPLETED"/>
 +            </intent-filter>
 +        </receiver>
 +        <service android:name=".files.services.FileObserverService"/>
 +    </application>
++    
 +</manifest>
diff --combined res/values/strings.xml
@@@ -2,7 -2,6 +2,6 @@@
  <resources>
  
      <string name="app_name">ownCloud</string>
-     <string name="whats_new">What\'s new</string>
      <string name="main_password">Password:</string>
      <string name="main_login">Username:</string>
      <string name="main_button_login">Login</string>
@@@ -15,8 -14,7 +14,8 @@@
      <string name="main_settings">Settings</string>
      <string name="main_tit_accsetup">Setup Account</string>
      <string name="main_wrn_accsetup">There is no account set up on your device. In order to use this App, you need to create one.</string>
 -    <string name="about_message">%1$s Android App\n\nversion: %2$s</string>
 +    <string name="about_android">Android App </string>
 +    <string name="about_version">version: </string>
      <string name="actionbar_sync">Refresh</string>
      <string name="actionbar_upload">Upload</string>
      <string name="actionbar_upload_from_apps">Content from other apps</string>
@@@ -24,8 -22,9 +23,9 @@@
      <string name="actionbar_mkdir">Create directory</string>
      <string name="actionbar_search">Search</string>
      <string name="actionbar_settings">Settings</string>
+     <string name="actionbar_see_details">Details</string>
+     
      <string name="prefs_category_general">General</string>
-     <string name="prefs_category_trackmydevice">Device tracking</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_pincode_summary">Protect your client</string>
      <string name="prefs_instant_upload">Enable instant uploads</string>
      <string name="prefs_instant_upload_summary">Instantly upload photos taken by camera</string>
 +    <string name="prefs_log_title">Enable Logging</string>
 +    <string name="prefs_log_summary">This is used to log problems</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="auth_host_url">URL</string>
      <string name="auth_username">Username</string>
      <string name="auth_password">Password</string>
@@@ -62,6 -55,7 +62,7 @@@
      <string name="setup_title">Connect to your %1$s</string>
      <string name="setup_btn_connect">Connect</string>
      <string name="uploader_btn_upload_text">Upload</string>
+     <string name="uploader_top_message">Choose upload directory:</string>
      <string name="uploader_wrn_no_account_title">No account found</string>
      <string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please setup an account first.</string>
      <string name="uploader_wrn_no_account_setup_btn_text">Setup</string>
@@@ -91,6 -85,8 +92,8 @@@
      <string name="common_save_exit">Save &amp; Exit</string>
      <string name="common_exit">Leave %1$s</string>
      <string name="common_error">Error</string>
+     <string name="common_loading">Loading &#8230;</string>
+     <string name="common_error_unknown">Unknown error</string>
      <string name="about_title">About</string>
      <string name="delete_account">Delete account</string>
      <string name="create_account">Create account</string>
      <string name="downloader_download_succeeded_content">%1$s was successfully downloaded</string>
      <string name="downloader_download_failed_ticker">Download failed</string>
      <string name="downloader_download_failed_content">Download of %1$s could not be completed</string>
+     <string name="downloader_not_downloaded_yet">Not downloaded yet</string>
      <string name="common_choose_account">Choose account</string>
      <string name="sync_string_contacts">Contacts</string>
      <string name="sync_fail_ticker">Synchronization failed</string>
      <string name="pincode_wrong">Incorrect App PIN</string>
      <string name="pincode_removed">App PIN removed</string>
      <string name="pincode_stored">App PIN stored</string>
+     
+     <string name="media_notif_ticker">"%1$s music player"</string>
+     <string name="media_state_playing">"%1$s (playing)"</string>
+     <string name="media_state_loading">"%1$s (loading)"</string>
+     <string name="media_event_done">"%1$s playback finished"</string>
+     <string name="media_err_nothing_to_play">No media file found</string>
+       <string name="media_err_no_account">No account provided</string>
+     <string name="media_err_not_in_owncloud">File not in a valid account</string>
+     <string name="media_err_unsupported">Unsupported media codec</string>
+     <string name="media_err_io">Media file could not be read</string>
+     <string name="media_err_malformed">Media file not correctly encoded</string>
+     <string name="media_err_timeout">Too much time trying to play</string>
+     <string name="media_err_invalid_progressive_playback">Media file cannot be streamed</string>
+     <string name="media_err_unknown">Media file cannot be played with the stock media player</string>
+     <string name="media_err_security_ex">Security error trying to play %1$s</string>
+       <string name="media_err_io_ex">Input error trying to play %1$s</string>
+       <string name="media_err_unexpected">Unexpected error trying to play %1$s</string>
+       <string name="media_previous_description">Previous track button</string>
+       <string name="media_rewind_description">Rewind button</string>
+       <string name="media_play_pause_description">Play or pause button</string>
+       <string name="media_forward_description">Fast forward button</string>
+       <string name="media_next_description">Next track button</string>
      <string-array name="prefs_trackmydevice_intervall_keys">
          <item>15 Minutes</item>
          <item>30 Minutes</item>
          <item>60</item>
      </string-array>
  
 -    <string name="auth_trying_to_login">Trying to login…</string>
 +    <string name="auth_trying_to_login">Trying to login...</string>
      <string name="auth_no_net_conn_title">No network connection</string>
      <string name="auth_no_net_conn_message">No network connection has been detected, check your Internet connection and try again.</string>
      <string name="auth_connect_anyway">Connect anyway</string>
      <string name="auth_nossl_plain_ok_title">Secure connection unavailable.</string>
      <string name="auth_nossl_plain_ok_message">The Application cannot establish a secure connection to the server. A non secure connection is available. You may continue or cancel.</string>
      <string name="auth_connection_established">Connection established</string>
 -    <string name="auth_testing_connection">Testing connection…</string>
 +    <string name="auth_testing_connection">Testing connection...</string>
      <string name="auth_not_configured_title">Malformed server configuration</string>
      <string name="auth_not_configured_message">It seems that your server instance is not correctly configured. Contact your administrator for more details.</string>
      <string name="auth_unknown_error_title">Unknown error occurred!</string>
      <string name="ssl_validator_label_L">Location:</string>
      <string name="ssl_validator_label_validity">Validity:</string>
      <string name="ssl_validator_label_validity_from">From:</string>
-     <string name="ssl_validator_label_validity_to">To:</string>
-     <string name="ssl_validator_label_signature">Signature:</string>
-     <string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
-     <string name="text_placeholder">This is a placeholder</string>
+       <string name="ssl_validator_label_validity_to">To:</string>
+       <string name="ssl_validator_label_signature">Signature:</string>
+       <string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
+                       
+     <string name="placeholder_sentence">This is a placeholder</string>
+     <string name="placeholder_filename">placeholder.txt</string>
+     <string name="placeholder_filetype">PNG Image</string>
+     <string name="placeholder_filesize">389 KB</string>
+     <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
+     <string name="placeholder_media_time">12:23:45</string>
+     
      <string name="instant_upload_on_wifi">Upload pictures via WiFi only</string>
      <string name="instant_upload_path">/InstantUpload</string>
      <string name="conflict_title">Update conflict</string>
      <string name="conflict_keep_both">Keep both</string>
      <string name="conflict_overwrite">Overwrite</string>
      <string name="conflict_dont_upload">Don\'t upload</string>
+     
+     <string name="preview_image_description">Image preview</string>
+     <string name="preview_image_error_unknown_format">This image can not be shown</string>
+     <string name="preview_image_error_out_of_memory">"Not enough memory to show this image</string>
+     
      <!-- we need to improve the communication of errors to the user -->
      <string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local directory</string>
      <string name="actionbar_failed_instant_upload">Failed InstantUpload"</string>
      <string name="failed_upload_retry_text">retry to upload the image: </string>
      <string name="failed_upload_load_more_images">Load more Picrures</string>
      <string name="failed_upload_retry_do_nothing_text">do nothing you are not online for instant upload</string>
- </resources>
+       <string name="failed_upload_failure_text">Failure Message: </string>
+       <string name="failed_upload_quota_exceeded_text">Please check your server configuration,maybe your quota is exceeded.</string>
+ </resources>
@@@ -26,7 -26,6 +26,7 @@@ 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.db.ProviderMeta.ProviderTableMeta;
  import com.owncloud.android.utils.FileStorageUtils;
@@@ -157,7 -156,7 +157,7 @@@ public class FileDataStorageManager imp
                              cv, ProviderTableMeta._ID + "=?",
                              new String[] { String.valueOf(file.getFileId()) });
                  } catch (RemoteException e) {
 -                    Log.e(TAG,
 +                    Log_OC.e(TAG,
                              "Fail to insert insert file to database "
                                      + e.getMessage());
                  }
                      result_uri = getContentProvider().insert(
                              ProviderTableMeta.CONTENT_URI_FILE, cv);
                  } catch (RemoteException e) {
 -                    Log.e(TAG,
 +                    Log_OC.e(TAG,
                              "Fail to insert insert file to database "
                                      + e.getMessage());
                  }
              }
              
          } catch (OperationApplicationException e) {
 -            Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
 +            Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
              
          } catch (RemoteException e) {
 -            Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
 +            Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
          }
          
          // update new id in file objects for insertions
                  if (results[i].uri != null) {
                      newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
                      files.get(i).setFileId(newId);
 -                    //Log.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
 +                    //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
                  }
              }
          }
                              ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                              new String[] { mAccount.name }, null);
                  } catch (RemoteException e) {
 -                    Log.e(TAG, e.getMessage());
 +                    Log_OC.e(TAG, e.getMessage());
                      return ret;
                  }
              } else {
                                  + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                          new String[] { value, mAccount.name }, null);
              } catch (RemoteException e) {
 -                Log.e(TAG,
 +                Log_OC.e(TAG,
                          "Couldn't determine file existance, assuming non existance: "
                                  + e.getMessage());
                  return false;
                                  + "=?", new String[] { value, mAccount.name },
                          null);
              } catch (RemoteException e) {
 -                Log.e(TAG, "Could not get file details: " + e.getMessage());
 +                Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
                  c = null;
              }
          }
                                                      ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
                                                      new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
                  } catch (RemoteException e) {
 -                    Log.e(TAG, e.getMessage());
 +                    Log_OC.e(TAG, e.getMessage());
                  }
              } else {
                  c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
                  }
                  
              } catch (OperationApplicationException e) {
 -                Log.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
 +                Log_OC.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
                  
              } catch (RemoteException e) {
 -                Log.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", 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;
+     }
  }
@@@ -21,11 -21,12 +21,11 @@@ package com.owncloud.android.datamodel
  
  import java.io.File;
  
 -import android.content.Intent;
 -import android.net.Uri;
 +import com.owncloud.android.Log_OC;
 +
  import android.os.Parcel;
  import android.os.Parcelable;
--import android.util.Log;
+ import android.webkit.MimeTypeMap;
  
  public class OCFile implements Parcelable, Comparable<OCFile> {
  
       * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory 
       */
      public void setFileName(String name) {
 -        Log.d(TAG, "OCFile name changin from " + mRemotePath);
 +        Log_OC.d(TAG, "OCFile name changin from " + mRemotePath);
          if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(PATH_SEPARATOR)) {
              String parent = (new File(getRemotePath())).getParent();
              parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
              if (isDirectory()) {
                  mRemotePath += PATH_SEPARATOR;
              }
 -            Log.d(TAG, "OCFile name changed to " + mRemotePath);
 +            Log_OC.d(TAG, "OCFile name changed to " + mRemotePath);
          }
      }
  
          return 0;
      }
  
+     /** @return  'True' if the file contains audio */
+     public boolean isAudio() {
+         return (mMimeType != null && mMimeType.startsWith("audio/"));
+     }
+     /** @return  'True' if the file contains video */
+     public boolean isVideo() {
+         return (mMimeType != null && mMimeType.startsWith("video/"));
+     }
+     /** @return  'True' if the file contains an image */
+     public boolean isImage() {
+         return ((mMimeType != null && mMimeType.startsWith("image/")) ||
+                  getMimeTypeFromName().startsWith("image/"));
+     }
+     
+     public String getMimeTypeFromName() {
+         String extension = "";
+         int pos = mRemotePath.lastIndexOf('.');
+         if (pos >= 0) {
+             extension = mRemotePath.substring(pos + 1);
+         }
+         String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
+         return (result != null) ? result : "";
+     }
  }
@@@ -17,8 -17,6 +17,8 @@@
   */
  package com.owncloud.android.db;
  
 +import com.owncloud.android.Log_OC;
 +
  import android.content.ContentValues;
  import android.content.Context;
  import android.database.Cursor;
@@@ -52,21 -50,23 +52,23 @@@ public class DbHandler 
          mDB.close();
      }
  
-     public boolean putFileForLater(String filepath, String account) {
+     public boolean putFileForLater(String filepath, String account, String message) {
          ContentValues cv = new ContentValues();
          cv.put("path", filepath);
          cv.put("account", account);
          cv.put("attempt", UPLOAD_STATUS_UPLOAD_LATER);
+         cv.put("message", message);
          long result = mDB.insert(TABLE_INSTANT_UPLOAD, null, cv);
 -        Log.d(TABLE_INSTANT_UPLOAD, "putFileForLater returns with: " + result + " for file: " + filepath);
 +        Log_OC.d(TABLE_INSTANT_UPLOAD, "putFileForLater returns with: " + result + " for file: " + filepath);
          return result != -1;
      }
  
-     public int updateFileState(String filepath, Integer status) {
+     public int updateFileState(String filepath, Integer status, String message) {
          ContentValues cv = new ContentValues();
          cv.put("attempt", status);
+         cv.put("message", message);
          int result = mDB.update(TABLE_INSTANT_UPLOAD, cv, "path=?", new String[] { filepath });
 -        Log.d(TABLE_INSTANT_UPLOAD, "updateFileState returns with: " + result + " for file: " + filepath);
 +        Log_OC.d(TABLE_INSTANT_UPLOAD, "updateFileState returns with: " + result + " for file: " + filepath);
          return result;
      }
  
@@@ -89,7 -89,7 +91,7 @@@
       */
      public boolean removeIUPendingFile(String localPath) {
          long result = mDB.delete(TABLE_INSTANT_UPLOAD, "path = ?", new String[] { localPath });
 -        Log.d(TABLE_INSTANT_UPLOAD, "delete returns with: " + result + " for file: " + localPath);
 +        Log_OC.d(TABLE_INSTANT_UPLOAD, "delete returns with: " + result + " for file: " + localPath);
          return result != 0;
  
      }
          @Override
          public void onCreate(SQLiteDatabase db) {
              db.execSQL("CREATE TABLE " + TABLE_INSTANT_UPLOAD + " (" + " _id INTEGER PRIMARY KEY, " + " path TEXT,"
-                     + " account TEXT,attempt INTEGER);");
+                     + " account TEXT,attempt INTEGER,message TEXT);");
          }
  
          @Override
          public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-             db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt;");
+             if (oldVersion < 2) {
+                 db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt INTEGER;");
+             }
+             db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN message TEXT;");
  
          }
      }
@@@ -35,21 -35,20 +35,21 @@@ import android.util.Log
  import android.webkit.MimeTypeMap;
  
  import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.authenticator.AccountAuthenticator;
  import com.owncloud.android.db.DbHandler;
  import com.owncloud.android.files.services.FileUploader;
+ import com.owncloud.android.utils.FileStorageUtils;
  
  public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
  
-     public static String INSTANT_UPLOAD_DIR = "/InstantUpload/";
      private static String TAG = "PhotoTakenBroadcastReceiver";
      private static final String[] CONTENT_PROJECTION = { Media.DATA, Media.DISPLAY_NAME, Media.MIME_TYPE, Media.SIZE };
      private static String NEW_PHOTO_ACTION = "com.android.camera.NEW_PICTURE";
  
      @Override
      public void onReceive(Context context, Intent intent) {
 -        Log.d(TAG, "Received: " + intent.getAction());
 +        Log_OC.d(TAG, "Received: " + intent.getAction());
          if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION)) {
              handleConnectivityAction(context, intent);
          } else if (intent.getAction().equals(NEW_PHOTO_ACTION)) {
@@@ -57,7 -56,7 +57,7 @@@
          } else if (intent.getAction().equals(FileUploader.UPLOAD_FINISH_MESSAGE)) {
              handleUploadFinished(context, intent);
          } else {
 -            Log.e(TAG, "Incorrect intent sent: " + intent.getAction());
 +            Log_OC.e(TAG, "Incorrect intent sent: " + intent.getAction());
          }
      }
  
@@@ -67,7 -66,7 +67,7 @@@
              DbHandler db = new DbHandler(context);
              String localPath = intent.getStringExtra(FileUploader.EXTRA_OLD_FILE_PATH);
              if (!db.removeIUPendingFile(localPath)) {
 -                Log.w(TAG, "Tried to remove non existing instant upload file " + localPath);
 +                Log_OC.w(TAG, "Tried to remove non existing instant upload file " + localPath);
              }
              db.close();
          }
  
      private void handleNewPhotoAction(Context context, Intent intent) {
          if (!instantUploadEnabled(context)) {
 -            Log.d(TAG, "Instant upload disabled, abording uploading");
 +            Log_OC.d(TAG, "Instant upload disabled, abording uploading");
              return;
          }
  
          Account account = AccountUtils.getCurrentOwnCloudAccount(context);
          if (account == null) {
 -            Log.w(TAG, "No owncloud account found for instant upload, aborting");
 +            Log_OC.w(TAG, "No owncloud account found for instant upload, aborting");
              return;
          }
  
          Cursor c = context.getContentResolver().query(intent.getData(), CONTENT_PROJECTION, null, null, null);
  
          if (!c.moveToFirst()) {
 -            Log.e(TAG, "Couldn't resolve given uri: " + intent.getDataString());
 +            Log_OC.e(TAG, "Couldn't resolve given uri: " + intent.getDataString());
              return;
          }
  
          String mime_type = c.getString(c.getColumnIndex(Media.MIME_TYPE));
  
          c.close();
 -        Log.e(TAG, file_path + "");
 +        Log_OC.e(TAG, file_path + "");
  
          // same always temporally the picture to upload
          DbHandler db = new DbHandler(context);
-         db.putFileForLater(file_path, account.name);
+         db.putFileForLater(file_path, account.name, null);
          db.close();
  
          if (!isOnline(context) || (instantUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context))) {
          Intent i = new Intent(context, FileUploader.class);
          i.putExtra(FileUploader.KEY_ACCOUNT, account);
          i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path);
-         i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + file_name);
+         i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(file_name));
          i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
          i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type);
          i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
  
      private void handleConnectivityAction(Context context, Intent intent) {
          if (!instantUploadEnabled(context)) {
 -            Log.d(TAG, "Instant upload disabled, abording uploading");
 +            Log_OC.d(TAG, "Instant upload disabled, abording uploading");
              return;
          }
  
                                      f.getName().substring(f.getName().lastIndexOf('.') + 1));
  
                          } catch (Throwable e) {
 -                            Log.e(TAG, "Trying to find out MIME type of a file without extension: " + f.getName());
 +                            Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + f.getName());
                          }
                          if (mimeType == null)
                              mimeType = "application/octet-stream";
                          Intent i = new Intent(context, FileUploader.class);
                          i.putExtra(FileUploader.KEY_ACCOUNT, account);
                          i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path);
-                         i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + f.getName());
+                         i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(f.getName()));
                          i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
                          i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
                          context.startService(i);
  
                      } else {
 -                        Log.w(TAG, "Instant upload file " + f.getAbsolutePath() + " dont exist anymore");
 +                        Log_OC.w(TAG, "Instant upload file " + f.getAbsolutePath() + " dont exist anymore");
                      }
                  } while (c.moveToNext());
              }
 -/* ownCloud Android client application\r
 - *   Copyright (C) 2012 Bartek Przybylski\r
 - *   Copyright (C) 2012-2013 ownCloud Inc.\r
 - *\r
 - *   This program is free software: you can redistribute it and/or modify\r
 - *   it under the terms of the GNU General Public License as published by\r
 - *   the Free Software Foundation, either version 2 of the License, or\r
 - *   (at your option) any later version.\r
 - *\r
 - *   This program is distributed in the hope that it will be useful,\r
 - *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 - *   GNU General Public License for more details.\r
 - *\r
 - *   You should have received a copy of the GNU General Public License\r
 - *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - *\r
 - */\r
 -\r
 -package com.owncloud.android.files.services;\r
 -\r
 -import java.io.File;\r
 -import java.util.AbstractList;\r
 -import java.util.HashMap;\r
 -import java.util.Iterator;\r
 -import java.util.Map;\r
 -import java.util.Vector;\r
 -import java.util.concurrent.ConcurrentHashMap;\r
 -import java.util.concurrent.ConcurrentMap;\r
 -\r
 -import com.owncloud.android.datamodel.FileDataStorageManager;\r
 -import com.owncloud.android.datamodel.OCFile;\r
 -import eu.alefzero.webdav.OnDatatransferProgressListener;\r
 -\r
 -import com.owncloud.android.network.OwnCloudClientUtils;\r
 -import com.owncloud.android.operations.DownloadFileOperation;\r
 -import com.owncloud.android.operations.RemoteOperationResult;\r
 -import com.owncloud.android.ui.activity.FileDetailActivity;\r
 -import com.owncloud.android.ui.fragment.FileDetailFragment;\r
 -import com.owncloud.android.ui.preview.PreviewImageActivity;\r
 -import com.owncloud.android.ui.preview.PreviewImageFragment;\r
 -\r
 -import android.accounts.Account;\r
 -import android.app.Notification;\r
 -import android.app.NotificationManager;\r
 -import android.app.PendingIntent;\r
 -import android.app.Service;\r
 -import android.content.Intent;\r
 -import android.os.Binder;\r
 -import android.os.Handler;\r
 -import android.os.HandlerThread;\r
 -import android.os.IBinder;\r
 -import android.os.Looper;\r
 -import android.os.Message;\r
 -import android.os.Process;\r
 -import android.util.Log;\r
 -import android.widget.RemoteViews;\r
 -\r
 -import com.owncloud.android.AccountUtils;\r
 -import com.owncloud.android.R;\r
 -import eu.alefzero.webdav.WebdavClient;\r
 -\r
 -public class FileDownloader extends Service implements OnDatatransferProgressListener {\r
 -    \r
 -    public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
 -    public static final String EXTRA_FILE = "FILE";\r
 -    \r
 -    public static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";\r
 -    public static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";\r
 -    public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";    \r
 -    public static final String EXTRA_FILE_PATH = "FILE_PATH";\r
 -    public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";\r
 -    public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
 -    \r
 -    private static final String TAG = "FileDownloader";\r
 -\r
 -    private Looper mServiceLooper;\r
 -    private ServiceHandler mServiceHandler;\r
 -    private IBinder mBinder;\r
 -    private WebdavClient mDownloadClient = null;\r
 -    private Account mLastAccount = null;\r
 -    private FileDataStorageManager mStorageManager;\r
 -    \r
 -    private ConcurrentMap<String, DownloadFileOperation> mPendingDownloads = new ConcurrentHashMap<String, DownloadFileOperation>();\r
 -    private DownloadFileOperation mCurrentDownload = null;\r
 -    \r
 -    private NotificationManager mNotificationManager;\r
 -    private Notification mNotification;\r
 -    private int mLastPercent;\r
 -    \r
 -    \r
 -    /**\r
 -     * Builds a key for mPendingDownloads from the account and file to download\r
 -     * \r
 -     * @param account   Account where the file to download is stored\r
 -     * @param file      File to download\r
 -     */\r
 -    private String buildRemoteName(Account account, OCFile file) {\r
 -        return account.name + file.getRemotePath();\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * Service initialization\r
 -     */\r
 -    @Override\r
 -    public void onCreate() {\r
 -        super.onCreate();\r
 -        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);\r
 -        HandlerThread thread = new HandlerThread("FileDownloaderThread",\r
 -                Process.THREAD_PRIORITY_BACKGROUND);\r
 -        thread.start();\r
 -        mServiceLooper = thread.getLooper();\r
 -        mServiceHandler = new ServiceHandler(mServiceLooper, this);\r
 -        mBinder = new FileDownloaderBinder();\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * Entry point to add one or several files to the queue of downloads.\r
 -     * \r
 -     * New downloads are added calling to startService(), resulting in a call to this method. This ensures the service will keep on working \r
 -     * although the caller activity goes away.\r
 -     */\r
 -    @Override\r
 -    public int onStartCommand(Intent intent, int flags, int startId) {\r
 -        if (    !intent.hasExtra(EXTRA_ACCOUNT) ||\r
 -                !intent.hasExtra(EXTRA_FILE)\r
 -                /*!intent.hasExtra(EXTRA_FILE_PATH) ||\r
 -                !intent.hasExtra(EXTRA_REMOTE_PATH)*/\r
 -           ) {\r
 -            Log.e(TAG, "Not enough information provided in intent");\r
 -            return START_NOT_STICKY;\r
 -        }\r
 -        Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);\r
 -        OCFile file = intent.getParcelableExtra(EXTRA_FILE);\r
 -        \r
 -        AbstractList<String> requestedDownloads = new Vector<String>(); // dvelasco: now this always contains just one element, but that can change in a near future (download of multiple selection)\r
 -        String downloadKey = buildRemoteName(account, file);\r
 -        try {\r
 -            DownloadFileOperation newDownload = new DownloadFileOperation(account, file); \r
 -            mPendingDownloads.putIfAbsent(downloadKey, newDownload);\r
 -            newDownload.addDatatransferProgressListener(this);\r
 -            newDownload.addDatatransferProgressListener((FileDownloaderBinder)mBinder);\r
 -            requestedDownloads.add(downloadKey);\r
 -            sendBroadcastNewDownload(newDownload);\r
 -            \r
 -        } catch (IllegalArgumentException e) {\r
 -            Log.e(TAG, "Not enough information provided in intent: " + e.getMessage());\r
 -            return START_NOT_STICKY;\r
 -        }\r
 -        \r
 -        if (requestedDownloads.size() > 0) {\r
 -            Message msg = mServiceHandler.obtainMessage();\r
 -            msg.arg1 = startId;\r
 -            msg.obj = requestedDownloads;\r
 -            mServiceHandler.sendMessage(msg);\r
 -        }\r
 -\r
 -        return START_NOT_STICKY;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Provides a binder object that clients can use to perform operations on the queue of downloads, excepting the addition of new files. \r
 -     * \r
 -     * Implemented to perform cancellation, pause and resume of existing downloads.\r
 -     */\r
 -    @Override\r
 -    public IBinder onBind(Intent arg0) {\r
 -        return mBinder;\r
 -    }\r
 -\r
 -\r
 -    /**\r
 -     * Called when ALL the bound clients were onbound.\r
 -     */\r
 -    @Override\r
 -    public boolean onUnbind(Intent intent) {\r
 -        ((FileDownloaderBinder)mBinder).clearListeners();\r
 -        return false;   // not accepting rebinding (default behaviour)\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     *  Binder to let client components to perform operations on the queue of downloads.\r
 -     * \r
 -     *  It provides by itself the available operations.\r
 -     */\r
 -    public class FileDownloaderBinder extends Binder implements OnDatatransferProgressListener {\r
 -        \r
 -        /** \r
 -         * Map of listeners that will be reported about progress of downloads from a {@link FileDownloaderBinder} instance \r
 -         */\r
 -        private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();\r
 -        \r
 -        \r
 -        /**\r
 -         * Cancels a pending or current download of a remote file.\r
 -         * \r
 -         * @param account       Owncloud account where the remote file is stored.\r
 -         * @param file          A file in the queue of pending downloads\r
 -         */\r
 -        public void cancel(Account account, OCFile file) {\r
 -            DownloadFileOperation download = null;\r
 -            synchronized (mPendingDownloads) {\r
 -                download = mPendingDownloads.remove(buildRemoteName(account, file));\r
 -            }\r
 -            if (download != null) {\r
 -                download.cancel();\r
 -            }\r
 -        }\r
 -        \r
 -        \r
 -        public void clearListeners() {\r
 -            mBoundListeners.clear();\r
 -        }\r
 -\r
 -\r
 -        /**\r
 -         * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download.\r
 -         * \r
 -         * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting to download. \r
 -         * \r
 -         * @param account       Owncloud account where the remote file is stored.\r
 -         * @param file          A file that could be in the queue of downloads.\r
 -         */\r
 -        public boolean isDownloading(Account account, OCFile file) {\r
 -            if (account == null || file == null) return false;\r
 -            String targetKey = buildRemoteName(account, file);\r
 -            synchronized (mPendingDownloads) {\r
 -                if (file.isDirectory()) {\r
 -                    // this can be slow if there are many downloads :(\r
 -                    Iterator<String> it = mPendingDownloads.keySet().iterator();\r
 -                    boolean found = false;\r
 -                    while (it.hasNext() && !found) {\r
 -                        found = it.next().startsWith(targetKey);\r
 -                    }\r
 -                    return found;\r
 -                } else {\r
 -                    return (mPendingDownloads.containsKey(targetKey));\r
 -                }\r
 -            }\r
 -        }\r
 -\r
 -        \r
 -        /**\r
 -         * Adds a listener interested in the progress of the download for a concrete file.\r
 -         * \r
 -         * @param listener      Object to notify about progress of transfer.    \r
 -         * @param account       ownCloud account holding the file of interest.\r
 -         * @param file          {@link OCfile} of interest for listener. \r
 -         */\r
 -        public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {\r
 -            if (account == null || file == null || listener == null) return;\r
 -            String targetKey = buildRemoteName(account, file);\r
 -            mBoundListeners.put(targetKey, listener);\r
 -        }\r
 -        \r
 -        \r
 -        \r
 -        /**\r
 -         * Removes a listener interested in the progress of the download for a concrete file.\r
 -         * \r
 -         * @param listener      Object to notify about progress of transfer.    \r
 -         * @param account       ownCloud account holding the file of interest.\r
 -         * @param file          {@link OCfile} of interest for listener. \r
 -         */\r
 -        public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {\r
 -            if (account == null || file == null || listener == null) return;\r
 -            String targetKey = buildRemoteName(account, file);\r
 -            if (mBoundListeners.get(targetKey) == listener) {\r
 -                mBoundListeners.remove(targetKey);\r
 -            }\r
 -        }\r
 -\r
 -\r
 -        @Override\r
 -        public void onTransferProgress(long progressRate) {\r
 -            // old way, should not be in use any more\r
 -        }\r
 -\r
 -\r
 -        @Override\r
 -        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,\r
 -                String fileName) {\r
 -            String key = buildRemoteName(mCurrentDownload.getAccount(), mCurrentDownload.getFile());\r
 -            OnDatatransferProgressListener boundListener = mBoundListeners.get(key);\r
 -            if (boundListener != null) {\r
 -                boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName);\r
 -            }\r
 -        }\r
 -        \r
 -    }\r
 -    \r
 -    \r
 -    /** \r
 -     * Download worker. Performs the pending downloads in the order they were requested. \r
 -     * \r
 -     * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}. \r
 -     */\r
 -    private static class ServiceHandler extends Handler {\r
 -        // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak\r
 -        FileDownloader mService;\r
 -        public ServiceHandler(Looper looper, FileDownloader service) {\r
 -            super(looper);\r
 -            if (service == null)\r
 -                throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");\r
 -            mService = service;\r
 -        }\r
 -\r
 -        @Override\r
 -        public void handleMessage(Message msg) {\r
 -            @SuppressWarnings("unchecked")\r
 -            AbstractList<String> requestedDownloads = (AbstractList<String>) msg.obj;\r
 -            if (msg.obj != null) {\r
 -                Iterator<String> it = requestedDownloads.iterator();\r
 -                while (it.hasNext()) {\r
 -                    mService.downloadFile(it.next());\r
 -                }\r
 -            }\r
 -            mService.stopSelf(msg.arg1);\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -\r
 -    /**\r
 -     * Core download method: requests a file to download and stores it.\r
 -     * \r
 -     * @param downloadKey   Key to access the download to perform, contained in mPendingDownloads \r
 -     */\r
 -    private void downloadFile(String downloadKey) {\r
 -        \r
 -        synchronized(mPendingDownloads) {\r
 -            mCurrentDownload = mPendingDownloads.get(downloadKey);\r
 -        }\r
 -        \r
 -        if (mCurrentDownload != null) {\r
 -            \r
 -            notifyDownloadStart(mCurrentDownload);\r
 -\r
 -            /// prepare client object to send the request to the ownCloud server\r
 -            if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {\r
 -                mLastAccount = mCurrentDownload.getAccount();\r
 -                mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());\r
 -                mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());\r
 -            }\r
 -\r
 -            /// perform the download\r
 -            RemoteOperationResult downloadResult = null;\r
 -            try {\r
 -                downloadResult = mCurrentDownload.execute(mDownloadClient);\r
 -                if (downloadResult.isSuccess()) {\r
 -                    saveDownloadedFile();\r
 -                }\r
 -            \r
 -            } finally {\r
 -                synchronized(mPendingDownloads) {\r
 -                    mPendingDownloads.remove(downloadKey);\r
 -                }\r
 -            }\r
 -\r
 -            \r
 -            /// notify result\r
 -            notifyDownloadResult(mCurrentDownload, downloadResult);\r
 -            \r
 -            sendBroadcastDownloadFinished(mCurrentDownload, downloadResult);\r
 -        }\r
 -    }\r
 -\r
 -\r
 -    /**\r
 -     * Updates the OC File after a successful download.\r
 -     */\r
 -    private void saveDownloadedFile() {\r
 -        OCFile file = mCurrentDownload.getFile();\r
 -        long syncDate = System.currentTimeMillis();\r
 -        file.setLastSyncDateForProperties(syncDate);\r
 -        file.setLastSyncDateForData(syncDate);\r
 -        file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());\r
 -        file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());\r
 -        // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available\r
 -        file.setMimetype(mCurrentDownload.getMimeType());\r
 -        file.setStoragePath(mCurrentDownload.getSavePath());\r
 -        file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));\r
 -        mStorageManager.saveFile(file);\r
 -    }\r
 -\r
 -\r
 -    /**\r
 -     * Creates a status notification to show the download progress\r
 -     * \r
 -     * @param download  Download operation starting.\r
 -     */\r
 -    private void notifyDownloadStart(DownloadFileOperation download) {\r
 -        /// create status notification with a progress bar\r
 -        mLastPercent = 0;\r
 -        mNotification = new Notification(R.drawable.icon, getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis());\r
 -        mNotification.flags |= Notification.FLAG_ONGOING_EVENT;\r
 -        mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout);\r
 -        mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, download.getSize() < 0);\r
 -        mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName()));\r
 -        mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);\r
 -        \r
 -        /// includes a pending intent in the notification showing the details view of the file\r
 -        Intent showDetailsIntent = null;\r
 -        if (PreviewImageFragment.canBePreviewed(download.getFile())) {\r
 -            showDetailsIntent = new Intent(this, PreviewImageActivity.class);\r
 -        } else {\r
 -            showDetailsIntent = new Intent(this, FileDetailActivity.class);\r
 -        }\r
 -        showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());\r
 -        showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());\r
 -        showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);\r
 -        mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);\r
 -        \r
 -        mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * Callback method to update the progress bar in the status notification.\r
 -     */\r
 -    @Override\r
 -    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) {\r
 -        int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));\r
 -        if (percent != mLastPercent) {\r
 -          mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0);\r
 -          String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName);\r
 -          mNotification.contentView.setTextViewText(R.id.status_text, text);\r
 -          mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);\r
 -        }\r
 -        mLastPercent = percent;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Callback method to update the progress bar in the status notification (old version)\r
 -     */\r
 -    @Override\r
 -    public void onTransferProgress(long progressRate) {\r
 -        // NOTHING TO DO HERE ANYMORE\r
 -    }\r
 -    \r
 -\r
 -    /**\r
 -     * Updates the status notification with the result of a download operation.\r
 -     * \r
 -     * @param downloadResult    Result of the download operation.\r
 -     * @param download          Finished download operation\r
 -     */\r
 -    private void notifyDownloadResult(DownloadFileOperation download, RemoteOperationResult downloadResult) {\r
 -        mNotificationManager.cancel(R.string.downloader_download_in_progress_ticker);\r
 -        if (!downloadResult.isCancelled()) {\r
 -            int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : R.string.downloader_download_failed_ticker;\r
 -            int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;\r
 -            Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());\r
 -            finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;\r
 -            Intent showDetailsIntent = null;\r
 -            if (downloadResult.isSuccess()) {\r
 -                if (PreviewImageFragment.canBePreviewed(download.getFile())) {\r
 -                    showDetailsIntent = new Intent(this, PreviewImageActivity.class);\r
 -                } else {\r
 -                    showDetailsIntent = new Intent(this, FileDetailActivity.class);\r
 -                }\r
 -                showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());\r
 -                showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());\r
 -                showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);\r
 -                \r
 -            } else {\r
 -                // TODO put something smart in showDetailsIntent\r
 -                showDetailsIntent = new Intent();\r
 -            }\r
 -            finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);\r
 -            finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);\r
 -            mNotificationManager.notify(tickerId, finalNotification);\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Sends a broadcast when a download finishes in order to the interested activities can update their view\r
 -     * \r
 -     * @param download          Finished download operation\r
 -     * @param downloadResult    Result of the download operation\r
 -     */\r
 -    private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) {\r
 -        Intent end = new Intent(DOWNLOAD_FINISH_MESSAGE);\r
 -        end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());\r
 -        end.putExtra(ACCOUNT_NAME, download.getAccount().name);\r
 -        end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());\r
 -        end.putExtra(EXTRA_FILE_PATH, download.getSavePath());\r
 -        sendStickyBroadcast(end);\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Sends a broadcast when a new download is added to the queue.\r
 -     * \r
 -     * @param download          Added download operation\r
 -     */\r
 -    private void sendBroadcastNewDownload(DownloadFileOperation download) {\r
 -        Intent added = new Intent(DOWNLOAD_ADDED_MESSAGE);\r
 -        added.putExtra(ACCOUNT_NAME, download.getAccount().name);\r
 -        added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());\r
 -        added.putExtra(EXTRA_FILE_PATH, download.getSavePath());\r
 -        sendStickyBroadcast(added);\r
 -    }\r
 -\r
 -}\r
 +/* ownCloud Android client application
 + *   Copyright (C) 2012 Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License as published by
 + *   the Free Software Foundation, either version 2 of the License, or
 + *   (at your option) any later version.
 + *
 + *   This program is distributed in the hope that it will be useful,
 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *   GNU General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +package com.owncloud.android.files.services;
 +
 +import java.io.File;
 +import java.util.AbstractList;
++import java.util.HashMap;
 +import java.util.Iterator;
++import java.util.Map;
 +import java.util.Vector;
 +import java.util.concurrent.ConcurrentHashMap;
 +import java.util.concurrent.ConcurrentMap;
 +
 +import com.owncloud.android.datamodel.FileDataStorageManager;
 +import com.owncloud.android.datamodel.OCFile;
 +import eu.alefzero.webdav.OnDatatransferProgressListener;
 +
 +import com.owncloud.android.network.OwnCloudClientUtils;
 +import com.owncloud.android.operations.DownloadFileOperation;
 +import com.owncloud.android.operations.RemoteOperationResult;
 +import com.owncloud.android.ui.activity.FileDetailActivity;
 +import com.owncloud.android.ui.fragment.FileDetailFragment;
++import com.owncloud.android.ui.preview.PreviewImageActivity;
++import com.owncloud.android.ui.preview.PreviewImageFragment;
 +
 +import android.accounts.Account;
 +import android.app.Notification;
 +import android.app.NotificationManager;
 +import android.app.PendingIntent;
 +import android.app.Service;
 +import android.content.Intent;
 +import android.os.Binder;
 +import android.os.Handler;
 +import android.os.HandlerThread;
 +import android.os.IBinder;
 +import android.os.Looper;
 +import android.os.Message;
 +import android.os.Process;
- import android.util.Log;
 +import android.widget.RemoteViews;
 +
 +import com.owncloud.android.Log_OC;
 +import com.owncloud.android.R;
 +import eu.alefzero.webdav.WebdavClient;
 +
 +public class FileDownloader extends Service implements OnDatatransferProgressListener {
 +    
 +    public static final String EXTRA_ACCOUNT = "ACCOUNT";
 +    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";
 +    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";
 +    public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
 +    
 +    private static final String TAG = "FileDownloader";
 +
 +    private Looper mServiceLooper;
 +    private ServiceHandler mServiceHandler;
 +    private IBinder mBinder;
 +    private WebdavClient mDownloadClient = null;
 +    private Account mLastAccount = null;
 +    private FileDataStorageManager mStorageManager;
 +    
 +    private ConcurrentMap<String, DownloadFileOperation> mPendingDownloads = new ConcurrentHashMap<String, DownloadFileOperation>();
 +    private DownloadFileOperation mCurrentDownload = null;
 +    
 +    private NotificationManager mNotificationManager;
 +    private Notification mNotification;
 +    private int mLastPercent;
 +    
 +    
 +    /**
 +     * Builds a key for mPendingDownloads from the account and file to download
 +     * 
 +     * @param account   Account where the file to download is stored
 +     * @param file      File to download
 +     */
 +    private String buildRemoteName(Account account, OCFile file) {
 +        return account.name + file.getRemotePath();
 +    }
 +
 +    
 +    /**
 +     * Service initialization
 +     */
 +    @Override
 +    public void onCreate() {
 +        super.onCreate();
 +        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 +        HandlerThread thread = new HandlerThread("FileDownloaderThread",
 +                Process.THREAD_PRIORITY_BACKGROUND);
 +        thread.start();
 +        mServiceLooper = thread.getLooper();
 +        mServiceHandler = new ServiceHandler(mServiceLooper, this);
 +        mBinder = new FileDownloaderBinder();
 +    }
 +
 +    
 +    /**
 +     * Entry point to add one or several files to the queue of downloads.
 +     * 
 +     * New downloads are added calling to startService(), resulting in a call to this method. This ensures the service will keep on working 
 +     * although the caller activity goes away.
 +     */
 +    @Override
 +    public int onStartCommand(Intent intent, int flags, int startId) {
 +        if (    !intent.hasExtra(EXTRA_ACCOUNT) ||
 +                !intent.hasExtra(EXTRA_FILE)
 +                /*!intent.hasExtra(EXTRA_FILE_PATH) ||
 +                !intent.hasExtra(EXTRA_REMOTE_PATH)*/
 +           ) {
 +            Log_OC.e(TAG, "Not enough information provided in intent");
 +            return START_NOT_STICKY;
 +        }
 +        Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
 +        OCFile file = intent.getParcelableExtra(EXTRA_FILE);
 +        
 +        AbstractList<String> requestedDownloads = new Vector<String>(); // dvelasco: now this always contains just one element, but that can change in a near future (download of multiple selection)
 +        String downloadKey = buildRemoteName(account, file);
 +        try {
 +            DownloadFileOperation newDownload = new DownloadFileOperation(account, file); 
 +            mPendingDownloads.putIfAbsent(downloadKey, newDownload);
 +            newDownload.addDatatransferProgressListener(this);
++            newDownload.addDatatransferProgressListener((FileDownloaderBinder)mBinder);
 +            requestedDownloads.add(downloadKey);
 +            sendBroadcastNewDownload(newDownload);
 +            
 +        } catch (IllegalArgumentException e) {
 +            Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
 +            return START_NOT_STICKY;
 +        }
 +        
 +        if (requestedDownloads.size() > 0) {
 +            Message msg = mServiceHandler.obtainMessage();
 +            msg.arg1 = startId;
 +            msg.obj = requestedDownloads;
 +            mServiceHandler.sendMessage(msg);
 +        }
 +
 +        return START_NOT_STICKY;
 +    }
 +    
 +    
 +    /**
 +     * Provides a binder object that clients can use to perform operations on the queue of downloads, excepting the addition of new files. 
 +     * 
 +     * Implemented to perform cancellation, pause and resume of existing downloads.
 +     */
 +    @Override
 +    public IBinder onBind(Intent arg0) {
 +        return mBinder;
 +    }
 +
++
++    /**
++     * Called when ALL the bound clients were onbound.
++     */
++    @Override
++    public boolean onUnbind(Intent intent) {
++        ((FileDownloaderBinder)mBinder).clearListeners();
++        return false;   // not accepting rebinding (default behaviour)
++    }
++
 +    
 +    /**
 +     *  Binder to let client components to perform operations on the queue of downloads.
 +     * 
 +     *  It provides by itself the available operations.
 +     */
-     public class FileDownloaderBinder extends Binder {
++    public class FileDownloaderBinder extends Binder implements OnDatatransferProgressListener {
++        
++        /** 
++         * Map of listeners that will be reported about progress of downloads from a {@link FileDownloaderBinder} instance 
++         */
++        private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
++        
 +        
 +        /**
 +         * Cancels a pending or current download of a remote file.
 +         * 
 +         * @param account       Owncloud account where the remote file is stored.
 +         * @param file          A file in the queue of pending downloads
 +         */
 +        public void cancel(Account account, OCFile file) {
 +            DownloadFileOperation download = null;
 +            synchronized (mPendingDownloads) {
 +                download = mPendingDownloads.remove(buildRemoteName(account, file));
 +            }
 +            if (download != null) {
 +                download.cancel();
 +            }
 +        }
 +        
 +        
++        public void clearListeners() {
++            mBoundListeners.clear();
++        }
++
++
 +        /**
 +         * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download.
 +         * 
 +         * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting to download. 
 +         * 
 +         * @param account       Owncloud account where the remote file is stored.
 +         * @param file          A file that could be in the queue of downloads.
 +         */
 +        public boolean isDownloading(Account account, OCFile file) {
 +            if (account == null || file == null) return false;
 +            String targetKey = buildRemoteName(account, file);
 +            synchronized (mPendingDownloads) {
 +                if (file.isDirectory()) {
 +                    // this can be slow if there are many downloads :(
 +                    Iterator<String> it = mPendingDownloads.keySet().iterator();
 +                    boolean found = false;
 +                    while (it.hasNext() && !found) {
 +                        found = it.next().startsWith(targetKey);
 +                    }
 +                    return found;
 +                } else {
 +                    return (mPendingDownloads.containsKey(targetKey));
 +                }
 +            }
 +        }
++
++        
++        /**
++         * Adds a listener interested in the progress of the download for a concrete file.
++         * 
++         * @param listener      Object to notify about progress of transfer.    
++         * @param account       ownCloud account holding the file of interest.
++         * @param file          {@link OCfile} of interest for listener. 
++         */
++        public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
++            if (account == null || file == null || listener == null) return;
++            String targetKey = buildRemoteName(account, file);
++            mBoundListeners.put(targetKey, listener);
++        }
++        
++        
++        
++        /**
++         * Removes a listener interested in the progress of the download for a concrete file.
++         * 
++         * @param listener      Object to notify about progress of transfer.    
++         * @param account       ownCloud account holding the file of interest.
++         * @param file          {@link OCfile} of interest for listener. 
++         */
++        public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
++            if (account == null || file == null || listener == null) return;
++            String targetKey = buildRemoteName(account, file);
++            if (mBoundListeners.get(targetKey) == listener) {
++                mBoundListeners.remove(targetKey);
++            }
++        }
++
++
++        @Override
++        public void onTransferProgress(long progressRate) {
++            // old way, should not be in use any more
++        }
++
++
++        @Override
++        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
++                String fileName) {
++            String key = buildRemoteName(mCurrentDownload.getAccount(), mCurrentDownload.getFile());
++            OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
++            if (boundListener != null) {
++                boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName);
++            }
++        }
++        
 +    }
 +    
 +    
 +    /** 
 +     * Download worker. Performs the pending downloads in the order they were requested. 
 +     * 
 +     * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}. 
 +     */
 +    private static class ServiceHandler extends Handler {
 +        // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak
 +        FileDownloader mService;
 +        public ServiceHandler(Looper looper, FileDownloader service) {
 +            super(looper);
 +            if (service == null)
 +                throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
 +            mService = service;
 +        }
 +
 +        @Override
 +        public void handleMessage(Message msg) {
 +            @SuppressWarnings("unchecked")
 +            AbstractList<String> requestedDownloads = (AbstractList<String>) msg.obj;
 +            if (msg.obj != null) {
 +                Iterator<String> it = requestedDownloads.iterator();
 +                while (it.hasNext()) {
 +                    mService.downloadFile(it.next());
 +                }
 +            }
 +            mService.stopSelf(msg.arg1);
 +        }
 +    }
 +    
 +    
 +
 +    /**
 +     * Core download method: requests a file to download and stores it.
 +     * 
 +     * @param downloadKey   Key to access the download to perform, contained in mPendingDownloads 
 +     */
 +    private void downloadFile(String downloadKey) {
 +        
 +        synchronized(mPendingDownloads) {
 +            mCurrentDownload = mPendingDownloads.get(downloadKey);
 +        }
 +        
 +        if (mCurrentDownload != null) {
 +            
 +            notifyDownloadStart(mCurrentDownload);
 +
 +            /// prepare client object to send the request to the ownCloud server
 +            if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
 +                mLastAccount = mCurrentDownload.getAccount();
 +                mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
 +                mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
 +            }
 +
 +            /// perform the download
 +            RemoteOperationResult downloadResult = null;
 +            try {
 +                downloadResult = mCurrentDownload.execute(mDownloadClient);
 +                if (downloadResult.isSuccess()) {
 +                    saveDownloadedFile();
 +                }
 +            
 +            } finally {
 +                synchronized(mPendingDownloads) {
 +                    mPendingDownloads.remove(downloadKey);
 +                }
 +            }
 +
 +            
 +            /// notify result
 +            notifyDownloadResult(mCurrentDownload, downloadResult);
 +            
 +            sendBroadcastDownloadFinished(mCurrentDownload, downloadResult);
 +        }
 +    }
 +
 +
 +    /**
 +     * Updates the OC File after a successful download.
 +     */
 +    private void saveDownloadedFile() {
 +        OCFile file = mCurrentDownload.getFile();
 +        long syncDate = System.currentTimeMillis();
 +        file.setLastSyncDateForProperties(syncDate);
 +        file.setLastSyncDateForData(syncDate);
 +        file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());
 +        file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());
 +        // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available
 +        file.setMimetype(mCurrentDownload.getMimeType());
 +        file.setStoragePath(mCurrentDownload.getSavePath());
 +        file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
 +        mStorageManager.saveFile(file);
 +    }
 +
 +
 +    /**
 +     * Creates a status notification to show the download progress
 +     * 
 +     * @param download  Download operation starting.
 +     */
 +    private void notifyDownloadStart(DownloadFileOperation download) {
 +        /// create status notification with a progress bar
 +        mLastPercent = 0;
 +        mNotification = new Notification(R.drawable.icon, getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis());
 +        mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
 +        mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout);
 +        mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, download.getSize() < 0);
 +        mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName()));
 +        mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
 +        
 +        /// includes a pending intent in the notification showing the details view of the file
-         Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
++        Intent showDetailsIntent = null;
++        if (PreviewImageFragment.canBePreviewed(download.getFile())) {
++            showDetailsIntent = new Intent(this, PreviewImageActivity.class);
++        } else {
++            showDetailsIntent = new Intent(this, FileDetailActivity.class);
++        }
 +        showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
 +        showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
 +        showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 +        mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
 +        
 +        mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
 +    }
 +
 +    
 +    /**
 +     * Callback method to update the progress bar in the status notification.
 +     */
 +    @Override
 +    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) {
 +        int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
 +        if (percent != mLastPercent) {
 +          mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0);
 +          String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName);
 +          mNotification.contentView.setTextViewText(R.id.status_text, text);
 +          mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
 +        }
 +        mLastPercent = percent;
 +    }
 +    
 +    
 +    /**
 +     * Callback method to update the progress bar in the status notification (old version)
 +     */
 +    @Override
 +    public void onTransferProgress(long progressRate) {
 +        // NOTHING TO DO HERE ANYMORE
 +    }
 +    
 +
 +    /**
 +     * Updates the status notification with the result of a download operation.
 +     * 
 +     * @param downloadResult    Result of the download operation.
 +     * @param download          Finished download operation
 +     */
 +    private void notifyDownloadResult(DownloadFileOperation download, RemoteOperationResult downloadResult) {
 +        mNotificationManager.cancel(R.string.downloader_download_in_progress_ticker);
 +        if (!downloadResult.isCancelled()) {
 +            int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : R.string.downloader_download_failed_ticker;
 +            int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
 +            Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());
 +            finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
-             // TODO put something smart in the contentIntent below
-             finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
++            Intent showDetailsIntent = null;
++            if (downloadResult.isSuccess()) {
++                if (PreviewImageFragment.canBePreviewed(download.getFile())) {
++                    showDetailsIntent = new Intent(this, PreviewImageActivity.class);
++                } else {
++                    showDetailsIntent = new Intent(this, FileDetailActivity.class);
++                }
++                showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
++                showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
++                showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
++                
++            } else {
++                // TODO put something smart in showDetailsIntent
++                showDetailsIntent = new Intent();
++            }
++            finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
 +            finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);
 +            mNotificationManager.notify(tickerId, finalNotification);
 +        }
 +    }
 +    
 +    
 +    /**
 +     * Sends a broadcast when a download finishes in order to the interested activities can update their view
 +     * 
 +     * @param download          Finished download operation
 +     * @param downloadResult    Result of the download operation
 +     */
 +    private void sendBroadcastDownloadFinished(DownloadFileOperation download, RemoteOperationResult downloadResult) {
 +        Intent end = new Intent(DOWNLOAD_FINISH_MESSAGE);
 +        end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
 +        end.putExtra(ACCOUNT_NAME, download.getAccount().name);
 +        end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
 +        end.putExtra(EXTRA_FILE_PATH, download.getSavePath());
 +        sendStickyBroadcast(end);
 +    }
 +    
 +    
 +    /**
 +     * Sends a broadcast when a new download is added to the queue.
 +     * 
 +     * @param download          Added download operation
 +     */
 +    private void sendBroadcastNewDownload(DownloadFileOperation download) {
 +        Intent added = new Intent(DOWNLOAD_ADDED_MESSAGE);
-         /*added.putExtra(ACCOUNT_NAME, download.getAccount().name);
-         added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());*/
++        added.putExtra(ACCOUNT_NAME, download.getAccount().name);
++        added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
 +        added.putExtra(EXTRA_FILE_PATH, download.getSavePath());
 +        sendStickyBroadcast(added);
 +    }
 +
 +}
@@@ -21,7 -21,9 +21,9 @@@ package com.owncloud.android.files.serv
  
  import java.io.File;
  import java.util.AbstractList;
+ import java.util.HashMap;
  import java.util.Iterator;
+ import java.util.Map;
  import java.util.Vector;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
@@@ -49,21 -51,22 +51,23 @@@ import android.webkit.MimeTypeMap
  import android.widget.RemoteViews;
  import android.widget.Toast;
  
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.R;
  import com.owncloud.android.authenticator.AccountAuthenticator;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.db.DbHandler;
- import com.owncloud.android.files.InstantUploadBroadcastReceiver;
  import com.owncloud.android.network.OwnCloudClientUtils;
  import com.owncloud.android.operations.ChunkedUploadFileOperation;
  import com.owncloud.android.operations.RemoteOperationResult;
  import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.operations.UploadFileOperation;
+ import com.owncloud.android.ui.activity.FailedUploadActivity;
  import com.owncloud.android.ui.activity.FileDetailActivity;
  import com.owncloud.android.ui.activity.InstantUploadActivity;
  import com.owncloud.android.ui.fragment.FileDetailFragment;
+ import com.owncloud.android.ui.preview.PreviewImageActivity;
+ import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.utils.OwnCloudVersion;
  
  import eu.alefzero.webdav.OnDatatransferProgressListener;
@@@ -119,8 -122,8 +123,8 @@@ public class FileUploader extends Servi
      /**
       * Builds a key for mPendingUploads from the account and file to upload
       * 
-      * @param account Account where the file to download is stored
-      * @param file File to download
+      * @param account   Account where the file to upload is stored
+      * @param file      File to upload
       */
      private String buildRemoteName(Account account, OCFile file) {
          return account.name + file.getRemotePath();
      @Override
      public void onCreate() {
          super.onCreate();
 -        Log.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
 +        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
          mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
          HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND);
          thread.start();
      public int onStartCommand(Intent intent, int flags, int startId) {
          if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE)
                  || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
 -            Log.e(TAG, "Not enough information provided in intent");
 +            Log_OC.e(TAG, "Not enough information provided in intent");
              return Service.START_NOT_STICKY;
          }
          int uploadType = intent.getIntExtra(KEY_UPLOAD_TYPE, -1);
          if (uploadType == -1) {
 -            Log.e(TAG, "Incorrect upload type provided");
 +            Log_OC.e(TAG, "Incorrect upload type provided");
              return Service.START_NOT_STICKY;
          }
          Account account = intent.getParcelableExtra(KEY_ACCOUNT);
          }
  
          if (intent.hasExtra(KEY_FILE) && files == null) {
 -            Log.e(TAG, "Incorrect array for OCFiles provided in upload intent");
 +            Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent");
              return Service.START_NOT_STICKY;
  
          } else if (!intent.hasExtra(KEY_FILE)) {
              if (localPaths == null) {
 -                Log.e(TAG, "Incorrect array for local paths provided in upload intent");
 +                Log_OC.e(TAG, "Incorrect array for local paths provided in upload intent");
                  return Service.START_NOT_STICKY;
              }
              if (remotePaths == null) {
 -                Log.e(TAG, "Incorrect array for remote paths provided in upload intent");
 +                Log_OC.e(TAG, "Incorrect array for remote paths provided in upload intent");
                  return Service.START_NOT_STICKY;
              }
              if (localPaths.length != remotePaths.length) {
 -                Log.e(TAG, "Different number of remote paths and local paths!");
 +                Log_OC.e(TAG, "Different number of remote paths and local paths!");
                  return Service.START_NOT_STICKY;
              }
  
                  }
                  mPendingUploads.putIfAbsent(uploadKey, newUpload);
                  newUpload.addDatatransferProgressListener(this);
+                 newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder);
                  requestedUploads.add(uploadKey);
              }
  
          } catch (IllegalArgumentException e) {
 -            Log.e(TAG, "Not enough information provided in intent: " + e.getMessage());
 +            Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
              return START_NOT_STICKY;
  
          } catch (IllegalStateException e) {
 -            Log.e(TAG, "Bad information provided in intent: " + e.getMessage());
 +            Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
              return START_NOT_STICKY;
  
          } catch (Exception e) {
 -            Log.e(TAG, "Unexpected exception while processing upload intent", e);
 +            Log_OC.e(TAG, "Unexpected exception while processing upload intent", e);
              return START_NOT_STICKY;
  
          }
              msg.obj = requestedUploads;
              mServiceHandler.sendMessage(msg);
          }
 -        Log.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
 +        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
          return Service.START_NOT_STICKY;
      }
  
      public IBinder onBind(Intent arg0) {
          return mBinder;
      }
+     
+     /**
+      * Called when ALL the bound clients were onbound.
+      */
+     @Override
+     public boolean onUnbind(Intent intent) {
+         ((FileUploaderBinder)mBinder).clearListeners();
+         return false;   // not accepting rebinding (default behaviour)
+     }
+     
  
      /**
       * Binder to let client components to perform operations on the queue of
       * 
       * It provides by itself the available operations.
       */
-     public class FileUploaderBinder extends Binder {
+     public class FileUploaderBinder extends Binder implements OnDatatransferProgressListener {
+         
+         /** 
+          * Map of listeners that will be reported about progress of uploads from a {@link FileUploaderBinder} instance 
+          */
+         private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
+         
          /**
           * Cancels a pending or current upload of a remote file.
           * 
                  upload.cancel();
              }
          }
+         
+         
+         
+         public void clearListeners() {
+             mBoundListeners.clear();
+         }
  
+         
+         
          /**
           * Returns True when the file described by 'file' is being uploaded to
           * the ownCloud account 'account' or waiting for it
           * 
-          * If 'file' is a directory, returns 'true' if some of its descendant
-          * files is downloading or waiting to download.
+          * If 'file' is a directory, returns 'true' if some of its descendant files is uploading or waiting to upload. 
           * 
           * @param account Owncloud account where the remote file will be stored.
           * @param file A file that could be in the queue of pending uploads
              String targetKey = buildRemoteName(account, file);
              synchronized (mPendingUploads) {
                  if (file.isDirectory()) {
-                     // this can be slow if there are many downloads :(
+                     // this can be slow if there are many uploads :(
                      Iterator<String> it = mPendingUploads.keySet().iterator();
                      boolean found = false;
                      while (it.hasNext() && !found) {
                  }
              }
          }
+         /**
+          * Adds a listener interested in the progress of the upload for a concrete file.
+          * 
+          * @param listener      Object to notify about progress of transfer.    
+          * @param account       ownCloud account holding the file of interest.
+          * @param file          {@link OCfile} of interest for listener. 
+          */
+         public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+             if (account == null || file == null || listener == null) return;
+             String targetKey = buildRemoteName(account, file);
+             mBoundListeners.put(targetKey, listener);
+         }
+         
+         
+         
+         /**
+          * Removes a listener interested in the progress of the upload for a concrete file.
+          * 
+          * @param listener      Object to notify about progress of transfer.    
+          * @param account       ownCloud account holding the file of interest.
+          * @param file          {@link OCfile} of interest for listener. 
+          */
+         public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+             if (account == null || file == null || listener == null) return;
+             String targetKey = buildRemoteName(account, file);
+             if (mBoundListeners.get(targetKey) == listener) {
+                 mBoundListeners.remove(targetKey);
+             }
+         }
+         @Override
+         public void onTransferProgress(long progressRate) {
+             // old way, should not be in use any more
+         }
+         @Override
+         public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
+                 String fileName) {
+             String key = buildRemoteName(mCurrentUpload.getAccount(), mCurrentUpload.getFile());
+             OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
+             if (boundListener != null) {
+                 boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName);
+             }
+         }
+         
      }
  
      /**
  
              // / create remote folder for instant uploads
              if (mCurrentUpload.isRemoteFolderToBeCreated()) {
-                 mUploadClient.createDirectory(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR); // ignoring
-                                                                                                   // result;
-                                                                                                   // fail
-                                                                                                   // could
-                                                                                                   // just
-                                                                                                   // mean
-                                                                                                   // that
-                                                                                                   // it
-                                                                                                   // already
-                                                                                                   // exists,
-                                                                                                   // but
-                                                                                                   // local
-                                                                                                   // database
-                                                                                                   // is
-                                                                                                   // not
-                                                                                                   // synchronized;
-                                                                                                   // the
-                                                                                                   // upload
-                                                                                                   // will
-                                                                                                   // be
-                                                                                                   // tried
-                                                                                                   // anyway
+                 mUploadClient.createDirectory(InstantUploadService.INSTANT_UPLOAD_DIR);
+                 // ignoring result fail could just mean that it already exists,
+                 // but local database is not synchronized the upload will be
+                 // tried anyway
              }
  
              // / perform the upload
              } finally {
                  synchronized (mPendingUploads) {
                      mPendingUploads.remove(uploadKey);
 -                    Log.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
 +                    Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
                  }
              }
  
              }
  
              result = new RemoteOperationResult(isMultiStatus, status);
 -            Log.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
 +            Log_OC.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
                      + result.getLogMessage());
  
          } catch (Exception e) {
              result = new RemoteOperationResult(e);
 -            Log.e(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
 +            Log_OC.e(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": "
                      + result.getLogMessage(), e);
  
          } finally {
          file.setMimetype(we.contentType());
          file.setModificationTimestamp(we.modifiedTimestamp());
          file.setModificationTimestampAtLastSyncForData(we.modifiedTimestamp());
-         // file.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where
-         // available
+         // file.setEtag(mCurrentUpload.getEtag());    // TODO Etag, where available
      }
  
      private boolean checkAndFixInstantUploadDirectory(FileDataStorageManager storageManager) {
-         OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR);
+         OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadService.INSTANT_UPLOAD_DIR);
          if (instantUploadDir == null) {
              // first instant upload in the account, or never account not
              // synchronized after the remote InstantUpload folder was created
-             OCFile newDir = new OCFile(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR);
+             OCFile newDir = new OCFile(InstantUploadService.INSTANT_UPLOAD_DIR);
              newDir.setMimetype("DIR");
              OCFile path = storageManager.getFileByPath(OCFile.PATH_SEPARATOR);
  
                  mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                          remotePath.substring(remotePath.lastIndexOf('.') + 1));
              } catch (IndexOutOfBoundsException e) {
 -                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath);
 +                Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath);
              }
          }
          if (mimeType == null) {
       * 
       * @param upload Upload operation starting.
       */
+     @SuppressWarnings("deprecation")
      private void notifyUploadStart(UploadFileOperation upload) {
          // / create status notification with a progress bar
          mLastPercent = 0;
          mNotification.contentView.setTextViewText(R.id.status_text,
                  String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
          mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
-         // / includes a pending intent in the notification showing the details
-         // view of the file
-         Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+         
+         /// includes a pending intent in the notification showing the details view of the file
+         Intent showDetailsIntent = null;
+         if (PreviewImageFragment.canBePreviewed(upload.getFile())) {
+             showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+         } else {
+             showDetailsIntent = new Intent(this, FileDetailActivity.class);
+             showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+         }
          showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile());
          showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount());
          showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
       * @param upload Finished upload operation
       */
      private void notifyUploadResult(RemoteOperationResult uploadResult, UploadFileOperation upload) {
 -        Log.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
 +        Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
          if (uploadResult.isCancelled()) {
              // / cancelled operation -> silent removal of progress notification
              mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
                                                                      // flag
              mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
              mNotification.contentView = mDefaultNotificationContentView;
-             // / includes a pending intent in the notification showing the
-             // details view of the file
-             Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+             
+             /// includes a pending intent in the notification showing the details view of the file
+             Intent showDetailsIntent = null;
+             if (PreviewImageFragment.canBePreviewed(upload.getFile())) {
+                 showDetailsIntent = new Intent(this, PreviewImageActivity.class); 
+             } else {
+                 showDetailsIntent = new Intent(this, FileDetailActivity.class); 
+                 showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+             }
              showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile());
              showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount());
              showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                      getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
              finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
  
-             Intent detailUploudIntent = new Intent(this, InstantUploadActivity.class);
-             detailUploudIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
-             finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
-                     (int) System.currentTimeMillis(), detailUploudIntent, PendingIntent.FLAG_UPDATE_CURRENT
-                             | PendingIntent.FLAG_ONE_SHOT);
              String content = null;
              if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
                      || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
                  // from a RemoteOperationResult and a RemoteOperation
                  content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(),
                          getString(R.string.app_name));
+             } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+                 content = getString(R.string.failed_upload_quota_exceeded_text);
              } else {
                  content = String
                          .format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
              }
-             finalNotification.setLatestEventInfo(getApplicationContext(),
-                     getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
  
-             mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
+             // we add only for instant-uploads the InstantUploadActivity and the
+             // db entry
+             Intent detailUploadIntent = null;
+             if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) {
+                 detailUploadIntent = new Intent(this, InstantUploadActivity.class);
+                 detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
+             } else {
+                 detailUploadIntent = new Intent(this, FailedUploadActivity.class);
+                 detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
+             }
+             finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
+                     (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT
+                             | PendingIntent.FLAG_ONE_SHOT);
  
-             DbHandler db = new DbHandler(this.getBaseContext());
-             if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED) == 0) {
-                 db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name);
+             if (upload.isInstant()) {
+                 DbHandler db = null;
+                 try {
+                     db = new DbHandler(this.getBaseContext());
+                     String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
+                     Log.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
+                     if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+                         message = getString(R.string.failed_upload_quota_exceeded_text);
+                     }
+                     if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
+                             message) == 0) {
+                         db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
+                     }
+                 } finally {
+                     if (db != null) {
+                         db.close();
+                     }
+                 }
              }
-             db.close();
+             finalNotification.setLatestEventInfo(getApplicationContext(),
+                     getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
  
+             mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
          }
  
      }
@@@ -23,16 -23,16 +23,16 @@@ import java.util.HashMap
  import java.util.LinkedList;
  import java.util.List;
  
 +import com.owncloud.android.Log_OC;
++import com.owncloud.android.utils.FileStorageUtils;
 +import com.owncloud.android.network.OwnCloudClientUtils;
 +
 +import eu.alefzero.webdav.WebdavClient;
 +
  import android.accounts.Account;
  import android.app.Service;
  import android.content.Intent;
  import android.os.IBinder;
--import android.util.Log;
 -
 -import com.owncloud.android.network.OwnCloudClientUtils;
 -import com.owncloud.android.utils.FileStorageUtils;
 -
 -import eu.alefzero.webdav.WebdavClient;
  
  public class InstantUploadService extends Service {
  
@@@ -44,7 -44,7 +44,7 @@@
  
      private static String TAG = "InstantUploadService";
      // TODO make it configurable over the settings dialog
-     public static String INSTANT_UPLOAD_DIR = "/InstantUpload";
+     public static final String INSTANT_UPLOAD_DIR = "/InstantUpload";
      private UploaderRunnable mUploaderRunnable;
  
      @Override
          if (intent == null || !intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_DISPLAY_NAME)
                  || !intent.hasExtra(KEY_FILE_PATH) || !intent.hasExtra(KEY_FILE_SIZE)
                  || !intent.hasExtra(KEY_MIME_TYPE)) {
 -            Log.w(TAG, "Not all required information was provided, abording");
 +            Log_OC.w(TAG, "Not all required information was provided, abording");
              return Service.START_NOT_STICKY;
          }
-         
          if (mUploaderRunnable == null) {
              mUploaderRunnable = new UploaderRunnable();
          }
-         
          String filename = intent.getStringExtra(KEY_DISPLAY_NAME);
          String filepath = intent.getStringExtra(KEY_FILE_PATH);
          String mimetype = intent.getStringExtra(KEY_MIME_TYPE);
          Account account = intent.getParcelableExtra(KEY_ACCOUNT);
          long filesize = intent.getLongExtra(KEY_FILE_SIZE, -1);
-         
          mUploaderRunnable.addElementToQueue(filename, filepath, mimetype, filesize, account);
-         
          // starting new thread for new download doesnt seems like a good idea
          // maybe some thread pool or single background thread would be better
 -        Log.d(TAG, "Starting instant upload thread");
 +        Log_OC.d(TAG, "Starting instant upload thread");
          new Thread(mUploaderRunnable).start();
-         
          return Service.START_STICKY;
      }
-     
      private class UploaderRunnable implements Runnable {
-         
          Object mLock;
          List<HashMap<String, Object>> mHashMapList;
-         
          public UploaderRunnable() {
              mHashMapList = new LinkedList<HashMap<String, Object>>();
              mLock = new Object();
          }
-         
-         public void addElementToQueue(String filename,
-                                       String filepath,
-                                       String mimetype,
-                                       long length,
-                                       Account account) {
+         public void addElementToQueue(String filename, String filepath, String mimetype, long length, Account account) {
              HashMap<String, Object> new_map = new HashMap<String, Object>();
              new_map.put(KEY_ACCOUNT, account);
              new_map.put(KEY_DISPLAY_NAME, filename);
              new_map.put(KEY_FILE_PATH, filepath);
              new_map.put(KEY_MIME_TYPE, mimetype);
              new_map.put(KEY_FILE_SIZE, length);
-             
              synchronized (mLock) {
                  mHashMapList.add(new_map);
              }
          }
-         
          private HashMap<String, Object> getFirstObject() {
              synchronized (mLock) {
                  if (mHashMapList.size() == 0)
                  return ret;
              }
          }
-         
          public void run() {
              HashMap<String, Object> working_map;
-             
              while ((working_map = getFirstObject()) != null) {
                  Account account = (Account) working_map.get(KEY_ACCOUNT);
                  String filename = (String) working_map.get(KEY_DISPLAY_NAME);
                  String mimetype = (String) working_map.get(KEY_MIME_TYPE);
                  
                  WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(account, getApplicationContext());
-                 
-                 wdc.createDirectory(INSTANT_UPLOAD_DIR);    // fail could just mean that it already exists; put will be tried anyway
+                 wdc.createDirectory(INSTANT_UPLOAD_DIR); // fail could just mean that it already exists put will be tried anyway
                  try {
-                     wdc.putFile(filepath, INSTANT_UPLOAD_DIR + "/" + filename, mimetype);
+                     wdc.putFile(filepath, FileStorageUtils.getInstantUploadFilePath(filename), mimetype);
                  } catch (Exception e) {
                      // nothing to do; this service is deprecated, indeed
                  }
              }
          }
      }
-     
  }
@@@ -28,8 -28,8 +28,9 @@@ import java.util.Random
  import org.apache.commons.httpclient.HttpException;
  import org.apache.commons.httpclient.methods.PutMethod;
  
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.network.ProgressiveDataTransferer;
  
  import android.accounts.Account;
  import android.util.Log;
@@@ -63,19 -63,19 +64,19 @@@ public class ChunkedUploadFileOperatio
              File file = new File(getStoragePath());
              raf = new RandomAccessFile(file, "r");
              channel = raf.getChannel();
-             ChunkFromFileChannelRequestEntity entity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
-             entity.addOnDatatransferProgressListeners(getDataTransferListeners());
+             mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
+             ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
              long offset = 0;
              String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
              long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
              for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
                  mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
                  mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
-                 entity.setOffset(offset);
-                 mPutMethod.setRequestEntity(entity);
+                 ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
+                 mPutMethod.setRequestEntity(mEntity);
                  status = client.executeMethod(mPutMethod);
                  client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
 -                Log.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
 +                Log_OC.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
                  if (!isSuccess(status))
                      break;
              }
@@@ -33,7 -33,6 +33,7 @@@ import org.apache.commons.httpclient.Ht
  import org.apache.commons.httpclient.methods.GetMethod;
  import org.apache.http.HttpStatus;
  
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.operations.RemoteOperation;
  import com.owncloud.android.operations.RemoteOperationResult;
@@@ -105,7 -104,7 +105,7 @@@ public class DownloadFileOperation exte
                      .getMimeTypeFromExtension(
                              mFile.getRemotePath().substring(mFile.getRemotePath().lastIndexOf('.') + 1));
              } catch (IndexOutOfBoundsException e) {
 -                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + mFile.getRemotePath());
 +                Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + mFile.getRemotePath());
              }
          }
          if (mimeType == null) {
      
      
      public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
-         mDataTransferListeners.add(listener);
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.add(listener);
+         }
      }
      
+     public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.remove(listener);
+         }
+     }
      @Override
      protected RemoteOperationResult run(WebdavClient client) {
          RemoteOperationResult result = null;
                  result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
              else
                  result = new RemoteOperationResult(isSuccess(status), status);
 -            Log.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
 +            Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
              
          } catch (Exception e) {
              result = new RemoteOperationResult(e);
 -            Log.e(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage(), e);
 +            Log_OC.e(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage(), e);
          }
          
          return result;
                      }
                      fos.write(bytes, 0, readResult);
                      transferred += readResult;
-                     it = mDataTransferListeners.iterator();
-                     while (it.hasNext()) {
-                         it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+                     synchronized (mDataTransferListeners) {
+                         it = mDataTransferListeners.iterator();
+                         while (it.hasNext()) {
+                             it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+                         }
                      }
                  }
                  savedFile = true;
          mCancellationRequested.set(true);   // atomic set; there is no need of synchronizing it
      }
  
  }
@@@ -28,7 -28,6 +28,7 @@@ import android.content.Context
  import android.content.Intent;
  import android.util.Log;
  
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
@@@ -159,11 -158,11 +159,11 @@@ public class SynchronizeFileOperation e
            
              }
              
 -            Log.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage());
 +            Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage());
            
          } catch (Exception e) {
              result = new RemoteOperationResult(e);
-             Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage(), result.getException());
 -            Log.e(TAG, "Synchronizing " + mAccount.name + ", file " + (mLocalFile != null ? mLocalFile.getRemotePath() : "NULL") + ": " + result.getLogMessage(), result.getException());
++            Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + (mLocalFile != null ? mLocalFile.getRemotePath() : "NULL") + ": " + result.getLogMessage(), result.getException());
  
          } finally {
              if (propfind != null)
@@@ -30,11 -30,15 +30,15 @@@ import java.util.concurrent.atomic.Atom
  
  import org.apache.commons.httpclient.HttpException;
  import org.apache.commons.httpclient.methods.PutMethod;
+ import org.apache.commons.httpclient.methods.RequestEntity;
  import org.apache.http.HttpStatus;
  
 -import android.util.Log;
 +import com.owncloud.android.Log_OC;
+ import android.accounts.Account;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileUploader;
+ import com.owncloud.android.network.ProgressiveDataTransferer;
  import com.owncloud.android.operations.RemoteOperation;
  import com.owncloud.android.operations.RemoteOperationResult;
  import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
@@@ -44,8 -48,6 +48,6 @@@ import eu.alefzero.webdav.FileRequestEn
  import eu.alefzero.webdav.OnDatatransferProgressListener;
  import eu.alefzero.webdav.WebdavClient;
  import eu.alefzero.webdav.WebdavUtils;
- import android.accounts.Account;
- import android.util.Log;
  
  /**
   * Remote operation performing the upload of a file to an ownCloud server
@@@ -53,7 -55,7 +55,7 @@@
   * @author David A. Velasco
   */
  public class UploadFileOperation extends RemoteOperation {
-     
      private static final String TAG = UploadFileOperation.class.getSimpleName();
  
      private Account mAccount;
@@@ -71,6 -73,8 +73,8 @@@
      private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
      private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
  
+     protected RequestEntity mEntity = null;
      
      public UploadFileOperation( Account account,
                                  OCFile file,
              throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation");
          if (file == null)
              throw new IllegalArgumentException("Illegal NULL file in UploadFileOperation creation");
-         if (file.getStoragePath() == null || file.getStoragePath().length() <= 0 || !(new File(file.getStoragePath()).exists())) {
-             throw new IllegalArgumentException("Illegal file in UploadFileOperation; storage path invalid or file not found: " + file.getStoragePath());
+         if (file.getStoragePath() == null || file.getStoragePath().length() <= 0
+                 || !(new File(file.getStoragePath()).exists())) {
+             throw new IllegalArgumentException(
+                     "Illegal file in UploadFileOperation; storage path invalid or file not found: "
+                             + file.getStoragePath());
          }
-         
          mAccount = account;
          mFile = file;
          mRemotePath = file.getRemotePath();
          mOriginalFileName = mFile.getFileName();
      }
  
      public Account getAccount() {
          return mAccount;
      }
-     
      public String getFileName() {
          return mOriginalFileName;
      }
-     
      public OCFile getFile() {
          return mFile;
      }
-     
      public OCFile getOldFile() {
-         return mOldFile; 
+         return mOldFile;
      }
-     
      public String getOriginalStoragePath() {
          return mOriginalStoragePath;
      }
-     
      public String getStoragePath() {
          return mFile.getStoragePath();
      }
  
      public String getRemotePath() {
-         return mFile.getRemotePath(); 
+         return mFile.getRemotePath();
      }
  
      public String getMimeType() {
          return mFile.getMimetype();
      }
-     
      public boolean isInstant() {
          return mIsInstant;
      }
      public boolean isRemoteFolderToBeCreated() {
          return mRemoteFolderToBeCreated;
      }
-     
      public void setRemoteFolderToBeCreated() {
          mRemoteFolderToBeCreated = true;
      }
      public boolean getForceOverwrite() {
          return mForceOverwrite;
      }
-     
      public boolean wasRenamed() {
          return mWasRenamed;
      }
-     
      public Set<OnDatatransferProgressListener> getDataTransferListeners() {
          return mDataTransferListeners;
      }
      
      public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
-         mDataTransferListeners.add(listener);
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.add(listener);
+         }
+         if (mEntity != null) {
+             ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
+         }
      }
      
+     public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.remove(listener);
+         }
+         if (mEntity != null) {
+             ((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
+         }
+     }
      @Override
      protected RemoteOperationResult run(WebdavClient client) {
          RemoteOperationResult result = null;
          boolean localCopyPassed = false, nameCheckPassed = false;
          File temporalFile = null, originalFile = new File(mOriginalStoragePath), expectedFile = null;
          try {
-             /// rename the file to upload, if necessary
+             // / rename the file to upload, if necessary
              if (!mForceOverwrite) {
                  String remotePath = getAvailableRemotePath(client, mRemotePath);
                  mWasRenamed = !remotePath.equals(mRemotePath);
                  if (mWasRenamed) {
-                    createNewOCFile(remotePath);
+                     createNewOCFile(remotePath);
                  }
              }
              nameCheckPassed = true;
-         
-             String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);  /// not before getAvailableRemotePath() !!!
+             String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); // /
+                                                                                                 // not
+                                                                                                 // before
+                                                                                                 // getAvailableRemotePath()
+                                                                                                 // !!!
              expectedFile = new File(expectedPath);
-             
-             /// check location of local file; if not the expected, copy to a temporal file before upload (if COPY is the expected behaviour)
+             // / check location of local file; if not the expected, copy to a
+             // temporal file before upload (if COPY is the expected behaviour)
              if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) {
  
                  if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
                      result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL);
-                     return result;  // error condition when the file should be copied
-                         
+                     return result; // error condition when the file should be
+                                    // copied
                  } else {
                      String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath();
                      mFile.setStoragePath(temporalPath);
                      temporalFile = new File(temporalPath);
-                     if (!mOriginalStoragePath.equals(temporalPath)) {   // preventing weird but possible situation
+                     if (!mOriginalStoragePath.equals(temporalPath)) { // preventing
+                                                                       // weird
+                                                                       // but
+                                                                       // possible
+                                                                       // situation
                          InputStream in = null;
                          OutputStream out = null;
                          try {
                              temporalFile.createNewFile();
                              if (!temporalFile.isFile()) {
                                  throw new IOException("Unexpected error: target file could not be created");
-                             }                    
+                             }
                              in = new FileInputStream(originalFile);
                              out = new FileOutputStream(temporalFile);
                              byte[] buf = new byte[1024];
                              int len;
-                             while ((len = in.read(buf)) > 0){
+                             while ((len = in.read(buf)) > 0) {
                                  out.write(buf, 0, len);
                              }
-                             
                          } catch (Exception e) {
                              result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
                              return result;
-                             
                          } finally {
                              try {
-                                 if (in != null) in.close();
+                                 if (in != null)
+                                     in.close();
                              } catch (Exception e) {
 -                                Log.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath
 -                                        + " (ignoring)", e);
 +                                Log_OC.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath + " (ignoring)", e);
                              }
                              try {
-                                 if (out != null) out.close();
+                                 if (out != null)
+                                     out.close();
                              } catch (Exception e) {
 -                                Log.d(TAG, "Weird exception while closing output stream for " + expectedPath
 -                                        + " (ignoring)", e);
 +                                Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e);
                              }
                          }
                      }
                  }
              }
              localCopyPassed = true;
-             
-             /// perform the upload
-             synchronized(mCancellationRequested) {
+             // / perform the upload
+             synchronized (mCancellationRequested) {
                  if (mCancellationRequested.get()) {
                      throw new OperationCancelledException();
                  } else {
                  }
              }
              int status = uploadFile(client);
-             
-             
-             /// move local temporal file or original file to its corresponding location in the ownCloud local folder
+             // / move local temporal file or original file to its corresponding
+             // location in the ownCloud local folder
              if (isSuccess(status)) {
                  if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
                      mFile.setStoragePath(null);
-                     
                  } else {
                      mFile.setStoragePath(expectedPath);
                      File fileToMove = null;
-                     if (temporalFile != null) {             // FileUploader.LOCAL_BEHAVIOUR_COPY ; see where temporalFile was set
+                     if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
+                                                 // ; see where temporalFile was
+                                                 // set
                          fileToMove = temporalFile;
-                     } else {                                // FileUploader.LOCAL_BEHAVIOUR_MOVE
+                     } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
                          fileToMove = originalFile;
                      }
                      if (!expectedFile.equals(fileToMove)) {
                          expectedFolder.mkdirs();
                          if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
                              mFile.setStoragePath(null); // forget the local file
-                             // by now, treat this as a success; the file was uploaded; the user won't like that the local file is not linked, but this should be a veeery rare fail;
-                             // the best option could be show a warning message (but not a fail)
-                             //result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
-                             //return result;
+                             // by now, treat this as a success; the file was
+                             // uploaded; the user won't like that the local file
+                             // is not linked, but this should be a very rare
+                             // fail;
+                             // the best option could be show a warning message
+                             // (but not a fail)
+                             // result = new
+                             // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
+                             // return result;
                          }
                      }
-                 } 
+                 }
              }
-             
              result = new RemoteOperationResult(isSuccess(status), status);
-             
-             
          } catch (Exception e) {
              // TODO something cleaner with cancellations
              if (mCancellationRequested.get()) {
              } else {
                  result = new RemoteOperationResult(e);
              }
-             
-             
          } finally {
              if (temporalFile != null && !originalFile.equals(temporalFile)) {
                  temporalFile.delete();
              }
              if (result.isSuccess()) {
 -                Log.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
 -
 +                Log_OC.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
-                     
              } else {
                  if (result.getException() != null) {
                      String complement = "";
                      if (!nameCheckPassed) {
                          complement = " (while checking file existence in server)";
                      } else if (!localCopyPassed) {
-                         complement = " (while copying local file to " + FileStorageUtils.getSavePath(mAccount.name) + ")";
+                         complement = " (while copying local file to " + FileStorageUtils.getSavePath(mAccount.name)
+                                 + ")";
                      }
 -                    Log.e(TAG,
 -                            "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage()
 -                                    + complement, result.getException());
 +                    Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage() + complement, result.getException());
                  } else {
 -                    Log.e(TAG,
 -                            "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
 +                    Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
                  }
              }
          }
-         
          return result;
      }
  
-     
      private void createNewOCFile(String newRemotePath) {
          // a new OCFile instance must be created for a new remote path
          OCFile newFile = new OCFile(newRemotePath);
          mFile = newFile;
      }
  
      public boolean isSuccess(int status) {
          return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
      }
-     
-     
      protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
          int status = -1;
          try {
              File f = new File(mFile.getStoragePath());
-             FileRequestEntity entity = new FileRequestEntity(f, getMimeType());
-             entity.addOnDatatransferProgressListeners(mDataTransferListeners);
-             mPutMethod.setRequestEntity(entity);
+             mEntity  = new FileRequestEntity(f, getMimeType());
+             synchronized (mDataTransferListeners) {
+                 ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
+             }
+             mPutMethod.setRequestEntity(mEntity);
              status = client.executeMethod(mPutMethod);
              client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
-             
          } finally {
-             mPutMethod.releaseConnection();    // let the connection available for other methods
+             mPutMethod.releaseConnection(); // let the connection available for
+                                             // other methods
          }
          return status;
      }
-     
      /**
-      * Checks if remotePath does not exist in the server and returns it, or adds a suffix to it in order to avoid the server
-      * file is overwritten.
+      * Checks if remotePath does not exist in the server and returns it, or adds
+      * a suffix to it in order to avoid the server file is overwritten.
       * 
       * @param string
       * @return
          if (!check) {
              return remotePath;
          }
-     
          int pos = remotePath.lastIndexOf(".");
          String suffix = "";
          String extension = "";
          if (pos >= 0) {
-             extension = remotePath.substring(pos+1);
+             extension = remotePath.substring(pos + 1);
              remotePath = remotePath.substring(0, pos);
          }
          int count = 2;
              count++;
          } while (check);
  
-         if (pos >=0) {
+         if (pos >= 0) {
              return remotePath + suffix + "." + extension;
          } else {
              return remotePath + suffix;
          }
      }
  
      public void cancel() {
-         synchronized(mCancellationRequested) {
+         synchronized (mCancellationRequested) {
              mCancellationRequested.set(true);
              if (mPutMethod != null)
                  mPutMethod.abort();
          }
      }
  
  }
 -/* ownCloud Android client application\r
 - *   Copyright (C) 2011  Bartek Przybylski\r
 - *   Copyright (C) 2012-2013 ownCloud Inc.\r
 - *\r
 - *   This program is free software: you can redistribute it and/or modify\r
 - *   it under the terms of the GNU General Public License as published by\r
 - *   the Free Software Foundation, either version 2 of the License, or\r
 - *   (at your option) any later version.\r
 - *\r
 - *   This program is distributed in the hope that it will be useful,\r
 - *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 - *   GNU General Public License for more details.\r
 - *\r
 - *   You should have received a copy of the GNU General Public License\r
 - *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - *\r
 - */\r
 -package com.owncloud.android.ui.activity;\r
 -\r
 -import android.accounts.Account;\r
 -import android.app.Dialog;\r
 -import android.app.ProgressDialog;\r
 -import android.content.BroadcastReceiver;\r
 -import android.content.ComponentName;\r
 -import android.content.Context;\r
 -import android.content.Intent;\r
 -import android.content.IntentFilter;\r
 -import android.content.ServiceConnection;\r
 -import android.content.res.Configuration;\r
 -import android.os.Bundle;\r
 -import android.os.IBinder;\r
 -import android.support.v4.app.Fragment;\r
 -import android.support.v4.app.FragmentTransaction;\r
 -import android.util.Log;\r
 -\r
 -import com.actionbarsherlock.app.ActionBar;\r
 -import com.actionbarsherlock.app.SherlockFragmentActivity;\r
 -import com.actionbarsherlock.view.MenuItem;\r
 -import com.owncloud.android.datamodel.FileDataStorageManager;\r
 -import com.owncloud.android.datamodel.OCFile;\r
 -import com.owncloud.android.files.services.FileDownloader;\r
 -import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 -import com.owncloud.android.files.services.FileUploader;\r
 -import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
 -import com.owncloud.android.ui.fragment.FileDetailFragment;\r
 -import com.owncloud.android.ui.fragment.FileFragment;\r
 -import com.owncloud.android.ui.preview.PreviewMediaFragment;\r
 -\r
 -import com.owncloud.android.AccountUtils;\r
 -import com.owncloud.android.R;\r
 -\r
 -/**\r
 - * This activity displays the details of a file like its name, its size and so\r
 - * on.\r
 - * \r
 - * @author Bartek Przybylski\r
 - * @author David A. Velasco\r
 - */\r
 -public class FileDetailActivity extends SherlockFragmentActivity implements FileFragment.ContainerActivity {\r
 -    \r
 -    public static final int DIALOG_SHORT_WAIT = 0;\r
 -\r
 -    public static final String TAG = FileDetailActivity.class.getSimpleName();\r
 -    \r
 -    public static final String EXTRA_MODE = "MODE";\r
 -    public static final int MODE_DETAILS = 0;\r
 -    public static final int MODE_PREVIEW = 1;\r
 -\r
 -    public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";\r
 -    \r
 -    private boolean mConfigurationChangedToLandscape = false;\r
 -    private FileDownloaderBinder mDownloaderBinder = null;\r
 -    private ServiceConnection mDownloadConnection, mUploadConnection = null;\r
 -    private FileUploaderBinder mUploaderBinder = null;\r
 -    private boolean mWaitingToPreview;\r
 -    \r
 -    private OCFile mFile;\r
 -    private Account mAccount;\r
 -\r
 -    private FileDataStorageManager mStorageManager;\r
 -    private DownloadFinishReceiver mDownloadFinishReceiver;\r
 -    \r
 -\r
 -    @Override\r
 -    protected void onCreate(Bundle savedInstanceState) {\r
 -        super.onCreate(savedInstanceState);\r
 -\r
 -        mFile = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);\r
 -        mAccount = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);\r
 -        mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());\r
 -        \r
 -        // check if configuration changed to large-land ; for a tablet being changed from portrait to landscape when in FileDetailActivity \r
 -        Configuration conf = getResources().getConfiguration();\r
 -        mConfigurationChangedToLandscape = (conf.orientation == Configuration.ORIENTATION_LANDSCAPE && \r
 -                                                (conf.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE\r
 -                                           );\r
 -\r
 -        if (!mConfigurationChangedToLandscape) {\r
 -            setContentView(R.layout.file_activity_details);\r
 -        \r
 -            ActionBar actionBar = getSupportActionBar();\r
 -            actionBar.setDisplayHomeAsUpEnabled(true);\r
 -\r
 -            if (savedInstanceState == null) {\r
 -                mWaitingToPreview = false;\r
 -                createChildFragment();\r
 -            } else {\r
 -                mWaitingToPreview = savedInstanceState.getBoolean(KEY_WAITING_TO_PREVIEW);\r
 -            }\r
 -            \r
 -            mDownloadConnection = new DetailsServiceConnection();\r
 -            bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);\r
 -            mUploadConnection = new DetailsServiceConnection();\r
 -            bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);\r
 -            \r
 -            \r
 -        }  else {\r
 -            backToDisplayActivity(false);   // the 'back' won't be effective until this.onStart() and this.onResume() are completed;\r
 -        }\r
 -        \r
 -        \r
 -    }\r
 -\r
 -    /**\r
 -     * Creates the proper fragment depending upon the state of the handled {@link OCFile} and\r
 -     * the requested {@link Intent}.\r
 -     */\r
 -    private void createChildFragment() {\r
 -        int mode = getIntent().getIntExtra(EXTRA_MODE, MODE_PREVIEW); \r
 -        \r
 -        Fragment newFragment = null;\r
 -        if (PreviewMediaFragment.canBePreviewed(mFile) && mode == MODE_PREVIEW) {\r
 -            if (mFile.isDown()) {\r
 -                newFragment = new PreviewMediaFragment(mFile, mAccount);\r
 -            \r
 -            } else {\r
 -                newFragment = new FileDetailFragment(mFile, mAccount);\r
 -                mWaitingToPreview = true;\r
 -            }\r
 -            \r
 -        } else {\r
 -            newFragment = new FileDetailFragment(mFile, mAccount);\r
 -        }\r
 -        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();\r
 -        ft.replace(R.id.fragment, newFragment, FileDetailFragment.FTAG);\r
 -        ft.commit();\r
 -    }\r
 -    \r
 -\r
 -    @Override\r
 -    protected void onSaveInstanceState(Bundle outState) {\r
 -        super.onSaveInstanceState(outState);\r
 -        outState.putBoolean(KEY_WAITING_TO_PREVIEW, mWaitingToPreview);\r
 -    }\r
 -    \r
 -    \r
 -    @Override\r
 -    public void onPause() {\r
 -        super.onPause();\r
 -        if (mDownloadFinishReceiver != null) {\r
 -            unregisterReceiver(mDownloadFinishReceiver);\r
 -            mDownloadFinishReceiver = null;\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    @Override\r
 -    public void onResume() {\r
 -        super.onResume();\r
 -        if (!mConfigurationChangedToLandscape) {\r
 -            // TODO this is probably unnecessary\r
 -            Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);\r
 -            if (fragment != null && fragment instanceof FileDetailFragment) {\r
 -                ((FileDetailFragment) fragment).updateFileDetails(false, false);\r
 -            }\r
 -        }\r
 -        // Listen for download messages\r
 -        IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);\r
 -        downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);\r
 -        mDownloadFinishReceiver = new DownloadFinishReceiver();\r
 -        registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);\r
 -    }\r
 -    \r
 -    \r
 -    /** Defines callbacks for service binding, passed to bindService() */\r
 -    private class DetailsServiceConnection implements ServiceConnection {\r
 -\r
 -        @Override\r
 -        public void onServiceConnected(ComponentName component, IBinder service) {\r
 -                \r
 -            if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {\r
 -                Log.d(TAG, "Download service connected");\r
 -                mDownloaderBinder = (FileDownloaderBinder) service;\r
 -                if (mWaitingToPreview) {\r
 -                    requestForDownload();\r
 -                }\r
 -                    \r
 -            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {\r
 -                Log.d(TAG, "Upload service connected");\r
 -                mUploaderBinder = (FileUploaderBinder) service;\r
 -            } else {\r
 -                return;\r
 -            }\r
 -            \r
 -            Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);\r
 -            FileDetailFragment detailsFragment = (fragment instanceof FileDetailFragment) ? (FileDetailFragment) fragment : null;\r
 -            if (detailsFragment != null) {\r
 -                detailsFragment.listenForTransferProgress();\r
 -                detailsFragment.updateFileDetails(mWaitingToPreview, false);   // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())\r
 -            }\r
 -        }\r
 -\r
 -        @Override\r
 -        public void onServiceDisconnected(ComponentName component) {\r
 -            if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {\r
 -                Log.d(TAG, "Download service disconnected");\r
 -                mDownloaderBinder = null;\r
 -            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {\r
 -                Log.d(TAG, "Upload service disconnected");\r
 -                mUploaderBinder = null;\r
 -            }\r
 -        }\r
 -    };    \r
 -    \r
 -    \r
 -    @Override\r
 -    public void onDestroy() {\r
 -        super.onDestroy();\r
 -        if (mDownloadConnection != null) {\r
 -            unbindService(mDownloadConnection);\r
 -            mDownloadConnection = null;\r
 -        }\r
 -        if (mUploadConnection != null) {\r
 -            unbindService(mUploadConnection);\r
 -            mUploadConnection = null;\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    @Override\r
 -    public boolean onOptionsItemSelected(MenuItem item) {\r
 -        boolean returnValue = false;\r
 -        \r
 -        switch(item.getItemId()){\r
 -        case android.R.id.home:\r
 -            backToDisplayActivity(true);\r
 -            returnValue = true;\r
 -            break;\r
 -        default:\r
 -              returnValue = super.onOptionsItemSelected(item);\r
 -        }\r
 -        \r
 -        return returnValue;\r
 -    }\r
 -\r
 -\r
 -\r
 -    private void backToDisplayActivity(boolean moveToParent) {\r
 -        Intent intent = new Intent(this, FileDisplayActivity.class);\r
 -        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);\r
 -        OCFile targetFile = null;\r
 -        if (mFile != null) {\r
 -            targetFile = moveToParent ? mStorageManager.getFileById(mFile.getParentId()) : mFile;\r
 -        }\r
 -        intent.putExtra(FileDetailFragment.EXTRA_FILE, targetFile);\r
 -        intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);\r
 -        startActivity(intent);\r
 -        finish();\r
 -    }\r
 -    \r
 -    \r
 -    @Override\r
 -    protected Dialog onCreateDialog(int id) {\r
 -        Dialog dialog = null;\r
 -        switch (id) {\r
 -        case DIALOG_SHORT_WAIT: {\r
 -            ProgressDialog working_dialog = new ProgressDialog(this);\r
 -            working_dialog.setMessage(getResources().getString(\r
 -                    R.string.wait_a_moment));\r
 -            working_dialog.setIndeterminate(true);\r
 -            working_dialog.setCancelable(false);\r
 -            dialog = working_dialog;\r
 -            break;\r
 -        }\r
 -        default:\r
 -            dialog = null;\r
 -        }\r
 -        return dialog;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    @Override\r
 -    public void onFileStateChanged() {\r
 -        // nothing to do here!\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    @Override\r
 -    public FileDownloaderBinder getFileDownloaderBinder() {\r
 -        return mDownloaderBinder;\r
 -    }\r
 -\r
 -\r
 -    @Override\r
 -    public FileUploaderBinder getFileUploaderBinder() {\r
 -        return mUploaderBinder;\r
 -    }\r
 -\r
 -\r
 -    @Override\r
 -    public void showFragmentWithDetails(OCFile file) {\r
 -        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\r
 -        transaction.replace(R.id.fragment, new FileDetailFragment(file, mAccount), FileDetailFragment.FTAG); \r
 -        transaction.commit();\r
 -    }\r
 -\r
 -    \r
 -    private void requestForDownload() {\r
 -        if (!mDownloaderBinder.isDownloading(mAccount, mFile)) {\r
 -            Intent i = new Intent(this, FileDownloader.class);\r
 -            i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);\r
 -            i.putExtra(FileDownloader.EXTRA_FILE, mFile);\r
 -            startService(i);\r
 -        }\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * Class waiting for broadcast events from the {@link FielDownloader} service.\r
 -     * \r
 -     * Updates the UI when a download is started or finished, provided that it is relevant for the\r
 -     * current file.\r
 -     */\r
 -    private class DownloadFinishReceiver extends BroadcastReceiver {\r
 -        @Override\r
 -        public void onReceive(Context context, Intent intent) {\r
 -            boolean sameAccount = isSameAccount(context, intent);\r
 -            String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);\r
 -            boolean samePath = (mFile != null && mFile.getRemotePath().equals(downloadedRemotePath));\r
 -            \r
 -            if (sameAccount && samePath) {\r
 -                updateChildFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));\r
 -            }\r
 -            \r
 -            removeStickyBroadcast(intent);\r
 -        }\r
 -\r
 -        private boolean isSameAccount(Context context, Intent intent) {\r
 -            String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);\r
 -            return (accountName != null && accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name));\r
 -        }\r
 -    }\r
 -\r
 -\r
 -    public void updateChildFragment(String downloadEvent, String downloadedRemotePath, boolean success) {\r
 -        Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);\r
 -        if (fragment != null && fragment instanceof FileDetailFragment) {\r
 -            FileDetailFragment detailsFragment = (FileDetailFragment) fragment;\r
 -            OCFile fileInFragment = detailsFragment.getFile();\r
 -            if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) {\r
 -                // this never should happen; fileInFragment should be always equals to mFile, that was compared to downloadedRemotePath in DownloadReceiver \r
 -                mWaitingToPreview = false;\r
 -                \r
 -            } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {\r
 -                // grants that the progress bar is updated\r
 -                detailsFragment.listenForTransferProgress();\r
 -                detailsFragment.updateFileDetails(true, false);\r
 -                \r
 -            } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {\r
 -                //  refresh the details fragment \r
 -                if (success && mWaitingToPreview) {\r
 -                    mFile = mStorageManager.getFileById(mFile.getFileId());   // update the file from database, for the local storage path\r
 -                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();\r
 -                    transaction.replace(R.id.fragment, new PreviewMediaFragment(mFile, mAccount), FileDetailFragment.FTAG);\r
 -                    transaction.commit();\r
 -                    mWaitingToPreview = false;\r
 -                    \r
 -                } else {\r
 -                    detailsFragment.updateFileDetails(false, (success));\r
 -                    // TODO error message if !success Â¿?\r
 -                }\r
 -            }\r
 -        } // TODO else if (fragment != null && fragment )\r
 -        \r
 -        \r
 -    }\r
 -\r
 -}\r
 +/* ownCloud Android client application
 + *   Copyright (C) 2011  Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License as published by
 + *   the Free Software Foundation, either version 2 of the License, or
 + *   (at your option) any later version.
 + *
 + *   This program is distributed in the hope that it will be useful,
 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *   GNU General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +package com.owncloud.android.ui.activity;
 +
 +import android.accounts.Account;
 +import android.app.Dialog;
 +import android.app.ProgressDialog;
++import android.content.BroadcastReceiver;
 +import android.content.ComponentName;
 +import android.content.Context;
 +import android.content.Intent;
++import android.content.IntentFilter;
 +import android.content.ServiceConnection;
 +import android.content.res.Configuration;
 +import android.os.Bundle;
 +import android.os.IBinder;
++import android.support.v4.app.Fragment;
 +import android.support.v4.app.FragmentTransaction;
 +import android.util.Log;
 +
 +import com.actionbarsherlock.app.ActionBar;
 +import com.actionbarsherlock.app.SherlockFragmentActivity;
 +import com.actionbarsherlock.view.MenuItem;
++import com.owncloud.android.datamodel.FileDataStorageManager;
 +import com.owncloud.android.datamodel.OCFile;
 +import com.owncloud.android.files.services.FileDownloader;
 +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 +import com.owncloud.android.files.services.FileUploader;
 +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 +import com.owncloud.android.ui.fragment.FileDetailFragment;
++import com.owncloud.android.ui.fragment.FileFragment;
++import com.owncloud.android.ui.preview.PreviewMediaFragment;
++import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.Log_OC;
++
 +import com.owncloud.android.R;
 +
 +/**
 + * This activity displays the details of a file like its name, its size and so
 + * on.
 + * 
 + * @author Bartek Przybylski
-  * 
++ * @author David A. Velasco
 + */
- public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {
++public class FileDetailActivity extends SherlockFragmentActivity implements FileFragment.ContainerActivity {
 +    
 +    public static final int DIALOG_SHORT_WAIT = 0;
 +
 +    public static final String TAG = FileDetailActivity.class.getSimpleName();
 +    
++    public static final String EXTRA_MODE = "MODE";
++    public static final int MODE_DETAILS = 0;
++    public static final int MODE_PREVIEW = 1;
++
++    public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
++    
 +    private boolean mConfigurationChangedToLandscape = false;
 +    private FileDownloaderBinder mDownloaderBinder = null;
 +    private ServiceConnection mDownloadConnection, mUploadConnection = null;
 +    private FileUploaderBinder mUploaderBinder = null;
++    private boolean mWaitingToPreview;
++    
++    private OCFile mFile;
++    private Account mAccount;
 +
++    private FileDataStorageManager mStorageManager;
++    private DownloadFinishReceiver mDownloadFinishReceiver;
++    
 +
 +    @Override
 +    protected void onCreate(Bundle savedInstanceState) {
 +        super.onCreate(savedInstanceState);
 +
++        mFile = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
++        mAccount = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
++        mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
++        
 +        // check if configuration changed to large-land ; for a tablet being changed from portrait to landscape when in FileDetailActivity 
 +        Configuration conf = getResources().getConfiguration();
 +        mConfigurationChangedToLandscape = (conf.orientation == Configuration.ORIENTATION_LANDSCAPE && 
 +                                                (conf.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
 +                                           );
 +
 +        if (!mConfigurationChangedToLandscape) {
-             mDownloadConnection = new DetailsServiceConnection();
-             bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
-             mUploadConnection = new DetailsServiceConnection();
-             bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
-             
 +            setContentView(R.layout.file_activity_details);
 +        
 +            ActionBar actionBar = getSupportActionBar();
 +            actionBar.setDisplayHomeAsUpEnabled(true);
 +
-             OCFile file = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
-             Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
-             FileDetailFragment mFileDetail = new FileDetailFragment(file, account);
-         
-             FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
-             ft.replace(R.id.fragment, mFileDetail, FileDetailFragment.FTAG);
-             ft.commit();
++            if (savedInstanceState == null) {
++                mWaitingToPreview = false;
++                createChildFragment();
++            } else {
++                mWaitingToPreview = savedInstanceState.getBoolean(KEY_WAITING_TO_PREVIEW);
++            }
++            
++            mDownloadConnection = new DetailsServiceConnection();
++            bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
++            mUploadConnection = new DetailsServiceConnection();
++            bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
++            
 +            
 +        }  else {
-             backToDisplayActivity();   // the 'back' won't be effective until this.onStart() and this.onResume() are completed;
++            backToDisplayActivity(false);   // the 'back' won't be effective until this.onStart() and this.onResume() are completed;
 +        }
 +        
++    }
++    
++    /**
++     * Creates the proper fragment depending upon the state of the handled {@link OCFile} and
++     * the requested {@link Intent}.
++     */
++    private void createChildFragment() {
++        int mode = getIntent().getIntExtra(EXTRA_MODE, MODE_PREVIEW); 
 +        
++        Fragment newFragment = null;
++        if (PreviewMediaFragment.canBePreviewed(mFile) && mode == MODE_PREVIEW) {
++            if (mFile.isDown()) {
++                newFragment = new PreviewMediaFragment(mFile, mAccount);
++            
++            } else {
++                newFragment = new FileDetailFragment(mFile, mAccount);
++                mWaitingToPreview = true;
++            }
++            
++        } else {
++            newFragment = new FileDetailFragment(mFile, mAccount);
++        }
++        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
++        ft.replace(R.id.fragment, newFragment, FileDetailFragment.FTAG);
++        ft.commit();
++    }
++    
++
++    @Override
++    protected void onSaveInstanceState(Bundle outState) {
++        super.onSaveInstanceState(outState);
++        outState.putBoolean(KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
++    }
++    
++    
++    @Override
++    public void onPause() {
++        super.onPause();
++        if (mDownloadFinishReceiver != null) {
++            unregisterReceiver(mDownloadFinishReceiver);
++            mDownloadFinishReceiver = null;
++        }
++    }
++
++    
++    @Override
++    public void onResume() {
++        super.onResume();
++        if (!mConfigurationChangedToLandscape) {
++            // TODO this is probably unnecessary
++            Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
++            if (fragment != null && fragment instanceof FileDetailFragment) {
++                ((FileDetailFragment) fragment).updateFileDetails(false, false);
++            }
++        }
++        // Listen for download messages
++        IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
++        downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
++        mDownloadFinishReceiver = new DownloadFinishReceiver();
++        registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
 +    }
 +    
 +    
 +    /** Defines callbacks for service binding, passed to bindService() */
 +    private class DetailsServiceConnection implements ServiceConnection {
 +
 +        @Override
 +        public void onServiceConnected(ComponentName component, IBinder service) {
++                
 +            if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {
 +                Log_OC.d(TAG, "Download service connected");
 +                mDownloaderBinder = (FileDownloaderBinder) service;
++                if (mWaitingToPreview) {
++                    requestForDownload();
++                }
++                    
 +            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
 +                Log_OC.d(TAG, "Upload service connected");
 +                mUploaderBinder = (FileUploaderBinder) service;
 +            } else {
 +                return;
 +            }
-             FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
-             if (fragment != null)
-                 fragment.updateFileDetails(false);   // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
++            
++            Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
++            FileDetailFragment detailsFragment = (fragment instanceof FileDetailFragment) ? (FileDetailFragment) fragment : null;
++            if (detailsFragment != null) {
++                detailsFragment.listenForTransferProgress();
++                detailsFragment.updateFileDetails(mWaitingToPreview, false);   // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
++            }
 +        }
 +
 +        @Override
 +        public void onServiceDisconnected(ComponentName component) {
 +            if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {
 +                Log_OC.d(TAG, "Download service disconnected");
 +                mDownloaderBinder = null;
 +            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
 +                Log_OC.d(TAG, "Upload service disconnected");
 +                mUploaderBinder = null;
 +            }
 +        }
 +    };    
 +    
++    
 +    @Override
 +    public void onDestroy() {
 +        super.onDestroy();
 +        if (mDownloadConnection != null) {
 +            unbindService(mDownloadConnection);
 +            mDownloadConnection = null;
 +        }
 +        if (mUploadConnection != null) {
 +            unbindService(mUploadConnection);
 +            mUploadConnection = null;
 +        }
 +    }
 +    
 +    
 +    @Override
 +    public boolean onOptionsItemSelected(MenuItem item) {
 +        boolean returnValue = false;
 +        
 +        switch(item.getItemId()){
 +        case android.R.id.home:
-             backToDisplayActivity();
++            backToDisplayActivity(true);
 +            returnValue = true;
 +            break;
 +        default:
-               returnValue = super.onOptionsItemSelected(item);
++            returnValue = super.onOptionsItemSelected(item);
 +        }
 +        
 +        return returnValue;
 +    }
 +
-     @Override
-     protected void onResume() {
-         
-         super.onResume();
-         if (!mConfigurationChangedToLandscape) { 
-             FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
-             fragment.updateFileDetails(false);
-         }
-     }
-     
-     private void backToDisplayActivity() {
++    private void backToDisplayActivity(boolean moveToParent) {
 +        Intent intent = new Intent(this, FileDisplayActivity.class);
 +        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-         intent.putExtra(FileDetailFragment.EXTRA_FILE, getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE));
-         intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT));
++        OCFile targetFile = null;
++        if (mFile != null) {
++            targetFile = moveToParent ? mStorageManager.getFileById(mFile.getParentId()) : mFile;
++        }
++        intent.putExtra(FileDetailFragment.EXTRA_FILE, targetFile);
++        intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
 +        startActivity(intent);
 +        finish();
 +    }
 +    
 +    
 +    @Override
 +    protected Dialog onCreateDialog(int id) {
 +        Dialog dialog = null;
 +        switch (id) {
 +        case DIALOG_SHORT_WAIT: {
 +            ProgressDialog working_dialog = new ProgressDialog(this);
 +            working_dialog.setMessage(getResources().getString(
 +                    R.string.wait_a_moment));
 +            working_dialog.setIndeterminate(true);
 +            working_dialog.setCancelable(false);
 +            dialog = working_dialog;
 +            break;
 +        }
 +        default:
 +            dialog = null;
 +        }
 +        return dialog;
 +    }
 +    
-     
++
 +    /**
 +     * {@inheritDoc}
 +     */
 +    @Override
 +    public void onFileStateChanged() {
 +        // nothing to do here!
 +    }
 +
 +    
 +    /**
 +     * {@inheritDoc}
 +     */
 +    @Override
 +    public FileDownloaderBinder getFileDownloaderBinder() {
 +        return mDownloaderBinder;
 +    }
 +
 +
 +    @Override
 +    public FileUploaderBinder getFileUploaderBinder() {
 +        return mUploaderBinder;
 +    }
++
++
++    @Override
++    public void showFragmentWithDetails(OCFile file) {
++        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
++        transaction.replace(R.id.fragment, new FileDetailFragment(file, mAccount), FileDetailFragment.FTAG); 
++        transaction.commit();
++    }
++
++    
++    private void requestForDownload() {
++        if (!mDownloaderBinder.isDownloading(mAccount, mFile)) {
++            Intent i = new Intent(this, FileDownloader.class);
++            i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);
++            i.putExtra(FileDownloader.EXTRA_FILE, mFile);
++            startService(i);
++        }
++    }
++
 +    
++    /**
++     * Class waiting for broadcast events from the {@link FielDownloader} service.
++     * 
++     * Updates the UI when a download is started or finished, provided that it is relevant for the
++     * current file.
++     */
++    private class DownloadFinishReceiver extends BroadcastReceiver {
++        @Override
++        public void onReceive(Context context, Intent intent) {
++            boolean sameAccount = isSameAccount(context, intent);
++            String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
++            boolean samePath = (mFile != null && mFile.getRemotePath().equals(downloadedRemotePath));
++            
++            if (sameAccount && samePath) {
++                updateChildFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
++            }
++            
++            removeStickyBroadcast(intent);
++        }
++
++        private boolean isSameAccount(Context context, Intent intent) {
++            String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
++            return (accountName != null && accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name));
++        }
++    }
++
++
++    public void updateChildFragment(String downloadEvent, String downloadedRemotePath, boolean success) {
++        Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
++        if (fragment != null && fragment instanceof FileDetailFragment) {
++            FileDetailFragment detailsFragment = (FileDetailFragment) fragment;
++            OCFile fileInFragment = detailsFragment.getFile();
++            if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) {
++                // this never should happen; fileInFragment should be always equals to mFile, that was compared to downloadedRemotePath in DownloadReceiver 
++                mWaitingToPreview = false;
++                
++            } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
++                // grants that the progress bar is updated
++                detailsFragment.listenForTransferProgress();
++                detailsFragment.updateFileDetails(true, false);
++                
++            } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
++                //  refresh the details fragment 
++                if (success && mWaitingToPreview) {
++                    mFile = mStorageManager.getFileById(mFile.getFileId());   // update the file from database, for the local storage path
++                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
++                    transaction.replace(R.id.fragment, new PreviewMediaFragment(mFile, mAccount), FileDetailFragment.FTAG);
++                    transaction.commit();
++                    mWaitingToPreview = false;
++                    
++                } else {
++                    detailsFragment.updateFileDetails(false, (success));
++                    // TODO error message if !success Â¿?
++                }
++            }
++        } // TODO else if (fragment != null && fragment )
++        
++    }
++
 +}
@@@ -4,7 -4,7 +4,7 @@@
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
-  *   the Free Software Foundation, either version 2 of the License, or
+  *   the Free Software Foundation, either version 3 of the License, or
   *   (at your option) any later version.
   *
   *   This program is distributed in the hope that it will be useful,
@@@ -23,9 -23,9 +23,9 @@@ import java.io.File
  
  import android.accounts.Account;
  import android.app.AlertDialog;
+ import android.app.ProgressDialog;
  import android.app.AlertDialog.Builder;
  import android.app.Dialog;
- import android.app.ProgressDialog;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.ContentResolver;
@@@ -49,6 -49,7 +49,7 @@@ import android.os.Handler
  import android.os.IBinder;
  import android.preference.PreferenceManager;
  import android.provider.MediaStore;
+ import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentTransaction;
  import android.util.Log;
  import android.view.View;
@@@ -66,8 -67,6 +67,8 @@@ import com.actionbarsherlock.view.MenuI
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
  import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.Log_OC;
 +import com.owncloud.android.R;
  import com.owncloud.android.authenticator.AccountAuthenticator;
  import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.FileDataStorageManager;
@@@ -81,29 -80,36 +82,36 @@@ import com.owncloud.android.network.Own
  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.syncadapter.FileSyncService;
  import com.owncloud.android.ui.dialog.ChangelogDialog;
+ import com.owncloud.android.ui.dialog.EditNameDialog;
  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.R;
  import eu.alefzero.webdav.WebdavClient;
  
  /**
   * Displays, what files the user has available in his ownCloud.
   * 
   * @author Bartek Przybylski
-  * 
+  * @author David A. Velasco
   */
  
- public class FileDisplayActivity extends SherlockFragmentActivity implements OCFileListFragment.ContainerActivity,
-         FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener {
+ public class FileDisplayActivity extends SherlockFragmentActivity implements
+     OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener, EditNameDialogListener {
+     
      private ArrayAdapter<String> mDirectories;
      private OCFile mCurrentDir = null;
      private OCFile mCurrentFile = null;
      private OCFileListFragment mFileList;
      
      private boolean mDualPane;
+     private boolean mBackFromCreatingFirstAccount;
      
      private static final int DIALOG_SETUP_ACCOUNT = 0;
      private static final int DIALOG_CREATE_DIR = 1;
 -    private static final int DIALOG_ABOUT_APP = 2;
      public static final int DIALOG_SHORT_WAIT = 3;
      private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
      private static final int DIALOG_SSL_VALIDATOR = 5;
      
      private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
      private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
-     private static final int ACTION_SELECT_FAILED_INSTANT_UPLOAD = 2;
+     
      private static final String TAG = "FileDisplayActivity";
  
+     private static int[] mMenuIdentifiersToPatch = {R.id.action_about_app};
      
 -    
+     private OCFile mWaitingToPreview;
+     private Handler mHandler;
      @Override
      public void onCreate(Bundle savedInstanceState) {
 -        Log.d(getClass().toString(), "onCreate() start");
 +        Log_OC.d(getClass().toString(), "onCreate() start");
          super.onCreate(savedInstanceState);
  
          /// Load of parameters from received intent
-         mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); // no check necessary, mCurrenDir == null if the parameter is not in the intent
          Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
-         if (account != null)
-             AccountUtils.setCurrentOwnCloudAccount(this, account.name);
+         if (account != null && AccountUtils.setCurrentOwnCloudAccount(this, account.name)) {
+             mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); 
+         }
          
          /// Load of saved instance state: keep this always before initDataFromCurrentAccount()
          if(savedInstanceState != null) {
              // TODO - test if savedInstanceState should take precedence over file in the intent ALWAYS (now), NEVER, or SOME TIMES
              mCurrentDir = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);
+             mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW);
+         } else {
+             mWaitingToPreview = null;
          }
          
          if (!AccountUtils.accountsAreSetup(this)) {
              /// no account available: FORCE ACCOUNT CREATION
              mStorageManager = null;
              createFirstAccount();
-         } else { // / at least an account is available
-             initDataFromCurrentAccount(); // it checks mCurrentDir and
-                                           // mCurrentFile with the current
-                                           // account
+             
+         } else {    /// at least an account is available
+             
+             initDataFromCurrentAccount();   // it checks mCurrentDir and mCurrentFile with the current account
+             
          }
          
          mUploadConnection = new ListServiceConnection(); 
          // Drop-down navigation 
          mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
          OCFile currFile = mCurrentDir;
-         while (currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) {
+         while(mStorageManager != null && currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) {
              mDirectories.add(currFile.getFileName());
              currFile = mStorageManager.getFileById(currFile.getParentId());
          }
          mFileList = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
          mDualPane = (findViewById(R.id.file_details_container) != null);
          if (mDualPane) {
-             initFileDetailsInDualPane();
+             if (savedInstanceState == null) initFileDetailsInDualPane();
+         } else {
+             // quick patchES to fix problem in turn from landscape to portrait, when a file is selected in the right pane
+             // TODO serious refactorization in activities and fragments providing file browsing and handling 
+             if (mCurrentFile != null) {
+                 onFileClick(mCurrentFile);
+                 mCurrentFile = null;
+             }
+             Fragment rightPanel = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+             if (rightPanel != null) {
+                 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+                 transaction.remove(rightPanel);
+                 transaction.commit();
+             }
          }
              
          // Action bar setup
          
          
          // show changelog, if needed
-         showChangeLog();
+         //showChangeLog();
+         mBackFromCreatingFirstAccount = false;
          
 -        Log.d(getClass().toString(), "onCreate() end");
 +        Log_OC.d(getClass().toString(), "onCreate() end");
      }
  
      
          startActivity(intent);  // the new activity won't be created until this.onStart() and this.onResume() are finished;
      }
  
+     
      /**
       *  Load of state dependent of the existence of an ownCloud account
       */
          if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) {
              FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
              if (mCurrentFile != null) {
-                 transaction.replace(R.id.file_details_container,
-                         new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)),
-                         FileDetailFragment.FTAG); // empty FileDetailFragment
+                 if (PreviewMediaFragment.canBePreviewed(mCurrentFile)) {
+                     if (mCurrentFile.isDown()) {
+                         transaction.replace(R.id.file_details_container, new PreviewMediaFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+                     } else {
+                         transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+                         mWaitingToPreview = mCurrentFile;
+                     }
+                 } else {
+                     transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+                 }
                  mCurrentFile = null;
+                 
              } else {
-                 transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null),
-                         FileDetailFragment.FTAG); // empty FileDetailFragment
+                 transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
              }
              transaction.commit();
          }
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getSherlock().getMenuInflater();
-             inflater.inflate(R.menu.menu, menu);
+             inflater.inflate(R.menu.main_menu, menu);
+             
 -            patchHiddenAccents(menu);
 -            
              return true;
      }
  
 -    /**
 -     * Workaround for this: <a href="http://code.google.com/p/android/issues/detail?id=3974">http://code.google.com/p/android/issues/detail?id=3974</a> 
 -     * 
 -     * @param menu      Menu to patch
 -     */
 -    private void patchHiddenAccents(Menu menu) {
 -        for (int i = 0; i < mMenuIdentifiersToPatch.length ; i++) {
 -            MenuItem aboutItem = menu.findItem(mMenuIdentifiersToPatch[i]);
 -            if (aboutItem != null && aboutItem.getIcon() instanceof BitmapDrawable) {
 -                // Clip off the bottom three (density independent) pixels of transparent padding
 -                Bitmap original = ((BitmapDrawable) aboutItem.getIcon()).getBitmap();
 -                float scale = getResources().getDisplayMetrics().density;
 -                int clippedHeight = (int) (original.getHeight() - (3 * scale));
 -                Bitmap scaled = Bitmap.createBitmap(original, 0, 0, original.getWidth(), clippedHeight);
 -                aboutItem.setIcon(new BitmapDrawable(getResources(), scaled));
 -            }
 -        }
 -    }
 -
 -
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          boolean retval = true;
          switch (item.getItemId()) {
-         case R.id.createDirectoryItem: {
-             showDialog(DIALOG_CREATE_DIR);
-             break;
-         }
-         case R.id.startSync: {
-             startSynchronization();
-             break;
-         }
-         case R.id.action_upload: {
-             showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
-             break;
-         }
-         case R.id.action_settings: {
-             Intent settingsIntent = new Intent(this, Preferences.class);
-             startActivity(settingsIntent);
-             break;
-         }
-         case android.R.id.home: {
-             if (mCurrentDir != null && mCurrentDir.getParentId() != 0) {
-                 onBackPressed();
+             case R.id.action_create_dir: {
+                 EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.uploader_info_dirname), "", this);
+                 dialog.show(getSupportFragmentManager(), "createdirdialog");
+                 break;
              }
-             break;
-         }
-         default:
-             retval = super.onOptionsItemSelected(item);
+             case R.id.action_sync_account: {
+                 startSynchronization();
+                 break;
+             }
+             case R.id.action_upload: {
+                 showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
+                 break;
+             }
+             case R.id.action_settings: {
+                 Intent settingsIntent = new Intent(this, Preferences.class);
+                 startActivity(settingsIntent);
+                 break;
+             }
 -            case R.id.action_about_app: {
 -                showDialog(DIALOG_ABOUT_APP);
 -                break;
 -            }
+             case android.R.id.home: {
+                 if(mCurrentDir != null && mCurrentDir.getParentId() != 0){
+                     onBackPressed(); 
+                 }
+                 break;
+             }
+             default:
+                 retval = super.onOptionsItemSelected(item);
          }
          return retval;
      }
       * Called, when the user selected something for uploading
       */
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
-         if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS
-                 && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
+         
+         if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
              requestSimpleUpload(data, resultCode);
-         } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES
-                 && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
+             
+         } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
              requestMultipleUpload(data, resultCode);
              
          }
              }
              if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR))
                  remotePathBase += OCFile.PATH_SEPARATOR;
-             for (int j = 0; j < remotePaths.length; j++) {
+             for (int j = 0; j< remotePaths.length; j++) {
                  remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName();
              }
  
              startService(i);
              
          } else {
 -            Log.d("FileDisplay", "User clicked on 'Update' with no selection");
 +            Log_OC.d("FileDisplay", "User clicked on 'Update' with no selection");
              Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), Toast.LENGTH_LONG);
              t.show();
              return;
                  filepath = filemanagerstring;
              
          } catch (Exception e) {
 -            Log.e("FileDisplay", "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e);
 +            Log_OC.e("FileDisplay", "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e);
              e.printStackTrace();
              
          } finally {
              if (filepath == null) {
 -                Log.e("FileDisplay", "Couldnt resolve path to file");
 +                Log_OC.e("FileDisplay", "Couldnt resolve path to file");
                  Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
                  t.show();
                  return;
          }
  
          Intent i = new Intent(this, FileUploader.class);
-         i.putExtra(FileUploader.KEY_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+         i.putExtra(FileUploader.KEY_ACCOUNT,
+                 AccountUtils.getCurrentOwnCloudAccount(this));
          String remotepath = new String();
          for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
              remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
          mCurrentDir = mFileList.getCurrentFile();
          
          if (mDualPane) {
-             // Resets the FileDetailsFragment on Tablets so that it always
-             // displays
-             FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
-                     FileDetailFragment.FTAG);
-             if (fileDetails != null && !fileDetails.isEmpty()) {
+             // Resets the FileDetailsFragment on Tablets so that it always displays
+             Fragment fileFragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+             if (fileFragment != null && (fileFragment instanceof PreviewMediaFragment || !((FileDetailFragment) fileFragment).isEmpty())) {
                  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                 transaction.remove(fileDetails);
-                 transaction.add(R.id.file_details_container, new FileDetailFragment(null, null),
-                         FileDetailFragment.FTAG);
+                 transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment                
                  transaction.commit();
              }
          }
-         if (mCurrentDir.getParentId() == 0) {
-             ActionBar actionBar = getSupportActionBar();
+         
+         if(mCurrentDir.getParentId() == 0){
+             ActionBar actionBar = getSupportActionBar(); 
              actionBar.setDisplayHomeAsUpEnabled(false);
-         }
+         } 
      }
  
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
 -        Log.d(getClass().toString(), "onSaveInstanceState() start");
 +        Log_OC.d(getClass().toString(), "onSaveInstanceState() start");
          super.onSaveInstanceState(outState);
          outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir);
          if (mDualPane) {
-             FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+             FileFragment fragment = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
              if (fragment != null) {
-                 OCFile file = fragment.getDisplayedFile();
+                 OCFile file = fragment.getFile();
                  if (file != null) {
                      outState.putParcelable(FileDetailFragment.EXTRA_FILE, file);
                  }
              }
          }
 -        Log.d(getClass().toString(), "onSaveInstanceState() end");
+         outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
 +        Log_OC.d(getClass().toString(), "onSaveInstanceState() end");
      }
  
+     
      @Override
 -    public void onResume() {
 -        Log.d(getClass().toString(), "onResume() start");
 +    protected void onResume() {
 +        Log_OC.d(getClass().toString(), "onResume() start");
          super.onResume();
  
          if (AccountUtils.accountsAreSetup(this)) {
                  if (mDualPane) {
                      initFileDetailsInDualPane();
                  }
+                 mBackFromCreatingFirstAccount = true;
              }
              
              // Listen for sync messages
              registerReceiver(mUploadFinishReceiver, uploadIntentFilter);
              
              // Listen for download messages
-             IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+             IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+             downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
              mDownloadFinishReceiver = new DownloadFinishReceiver();
              registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
          
              showDialog(DIALOG_SETUP_ACCOUNT);
              
          }
 -        Log.d(getClass().toString(), "onResume() end");
 +        Log_OC.d(getClass().toString(), "onResume() end");
      }
  
      
      @Override
 -    public void onPause() {
 -        Log.d(getClass().toString(), "onPause() start");
 +    protected void onPause() {
 +        Log_OC.d(getClass().toString(), "onPause() start");
          super.onPause();
          if (mSyncBroadcastReceiver != null) {
              unregisterReceiver(mSyncBroadcastReceiver);
              dismissDialog(DIALOG_SETUP_ACCOUNT);
          }
          
 -        Log.d(getClass().toString(), "onPause() end");
 +        Log_OC.d(getClass().toString(), "onPause() end");
      }
  
      
              dialog = builder.create();
              break;
          }
 -        case DIALOG_ABOUT_APP: {
 -            builder = new AlertDialog.Builder(this);
 -            builder.setTitle(getString(R.string.about_title));
 -            PackageInfo pkg;
 -            try {
 -                pkg = getPackageManager().getPackageInfo(getPackageName(), 0);
 -                builder.setMessage(String.format(getString(R.string.about_message), getString(R.string.app_name), pkg.versionName));
 -                builder.setIcon(android.R.drawable.ic_menu_info_details);
 -                dialog = builder.create();
 -            } catch (NameNotFoundException e) {
 -                builder = null;
 -                dialog = null;
 -                Log.e(TAG, "Error while showing about dialog", e);
 -            }
 -            break;
 -        }
          case DIALOG_CREATE_DIR: {
              builder = new Builder(this);
              final EditText dirNameInput = new EditText(getBaseContext());
              builder.setTitle(R.string.uploader_info_dirname);
              int typed_color = getResources().getColor(R.color.setup_text_typed);
              dirNameInput.setTextColor(typed_color);
-             builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
-                 public void onClick(DialogInterface dialog, int which) {
-                     String directoryName = dirNameInput.getText().toString();
-                     if (directoryName.trim().length() == 0) {
-                         dialog.cancel();
-                         return;
-                     }
-                     // Figure out the path where the dir needs to be created
-                     String path;
-                     if (mCurrentDir == null) {
-                         // this is just a patch; we should ensure that
-                         // mCurrentDir never is null
-                         if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
-                             OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
-                             mStorageManager.saveFile(file);
+             builder.setPositiveButton(android.R.string.ok,
+                     new OnClickListener() {
+                         public void onClick(DialogInterface dialog, int which) {
+                             String directoryName = dirNameInput.getText().toString();
+                             if (directoryName.trim().length() == 0) {
+                                 dialog.cancel();
+                                 return;
+                             }
+     
+                             // Figure out the path where the dir needs to be created
+                             String path;
+                             if (mCurrentDir == null) {
+                                 // this is just a patch; we should ensure that mCurrentDir never is null
+                                 if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
+                                     OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
+                                     mStorageManager.saveFile(file);
+                                 }
+                                 mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+                             }
+                             path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
+                             
+                             // Create directory
+                             path += directoryName + OCFile.PATH_SEPARATOR;
+                             Thread thread = new Thread(new DirectoryCreator(path,  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
+                             thread.start();
+                             
+                             dialog.dismiss();
+                             
+                             showDialog(DIALOG_SHORT_WAIT);
                          }
-                         mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
-                     }
-                     path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
-                     // Create directory
-                     path += directoryName + OCFile.PATH_SEPARATOR;
-                     Thread thread = new Thread(new DirectoryCreator(path, AccountUtils
-                             .getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
-                     thread.start();
-                     dialog.dismiss();
-                     showDialog(DIALOG_SHORT_WAIT);
-                 }
-             });
-             builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
-                 public void onClick(DialogInterface dialog, int which) {
-                     dialog.cancel();
-                 }
-             });
+                     });
+             builder.setNegativeButton(R.string.common_cancel,
+                     new OnClickListener() {
+                         public void onClick(DialogInterface dialog, int which) {
+                             dialog.cancel();
+                         }
+                     });
              dialog = builder.create();
              break;
          }
          case DIALOG_SHORT_WAIT: {
              ProgressDialog working_dialog = new ProgressDialog(this);
-             working_dialog.setMessage(getResources().getString(R.string.wait_a_moment));
+             working_dialog.setMessage(getResources().getString(
+                     R.string.wait_a_moment));
              working_dialog.setIndeterminate(true);
              working_dialog.setCancelable(false);
              dialog = working_dialog;
              break;
          }
          case DIALOG_CHOOSE_UPLOAD_SOURCE: {
-             final String[] items = { getString(R.string.actionbar_upload_files),
-                     getString(R.string.actionbar_upload_from_apps), getString(R.string.actionbar_failed_instant_upload) };
+             
+             String[] items = null;
+             
+             String[] allTheItems = { getString(R.string.actionbar_upload_files),
+                                      getString(R.string.actionbar_upload_from_apps),
+                                      getString(R.string.actionbar_failed_instant_upload) };
+             
+             String[] commonItems = { getString(R.string.actionbar_upload_files),
+                                      getString(R.string.actionbar_upload_from_apps) };
+             
+             if (InstantUploadActivity.IS_ENABLED)
+                 items = allTheItems;
+             else 
+                 items = commonItems;
+             
              builder = new AlertDialog.Builder(this);
              builder.setTitle(R.string.actionbar_upload);
              builder.setItems(items, new DialogInterface.OnClickListener() {
                          action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
                          startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
                                  ACTION_SELECT_CONTENT_FROM_APPS);
-                     } else if (item == 2) {
+                     } else if (item == 2 && InstantUploadActivity.IS_ENABLED) {
                          Account account = AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this);
                          Intent action = new Intent(FileDisplayActivity.this, InstantUploadActivity.class);
                          action.putExtra(FileUploader.KEY_ACCOUNT, account);
              builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
              builder.setCancelable(false);
              builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
-                 @Override
-                 public void onClick(DialogInterface dialog, int which) {
-                     dialog.dismiss();
-                 };
-             });
+                     @Override
+                     public void onClick(DialogInterface dialog, int which) {
+                         dialog.dismiss();
+                     };
+                 });
              dialog = builder.create();
              break;
          }
          String[] projection = { MediaStore.Images.Media.DATA };
          Cursor cursor = managedQuery(uri, projection, null, null, null);
          if (cursor != null) {
-             int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+             int column_index = cursor
+                     .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
              cursor.moveToFirst();
              return cursor.getString(column_index);
-         }
+         } 
          return null;
      }
      
                      public void run() {
                          dismissDialog(DIALOG_SHORT_WAIT);
                          try {
-                             Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg,
-                                     Toast.LENGTH_LONG);
+                             Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG); 
                              msg.show();
                          
                          } catch (NotFoundException e) {
 -                            Log.e(TAG, "Error while trying to show fail message " , e);
 +                            Log_OC.e(TAG, "Error while trying to show fail message ", e);
                          }
                      }
                  });
      
          public View getView(int position, View convertView, ViewGroup parent) {
              View v = super.getView(position, convertView, parent);
-             ((TextView) v).setTextColor(getResources().getColorStateList(android.R.color.white));
+     
+             ((TextView) v).setTextColor(getResources().getColorStateList(
+                     android.R.color.white));
              return v;
          }
-         public View getDropDownView(int position, View convertView, ViewGroup parent) {
+     
+         public View getDropDownView(int position, View convertView,
+                 ViewGroup parent) {
              View v = super.getDropDownView(position, convertView, parent);
-             ((TextView) v).setTextColor(getResources().getColorStateList(android.R.color.white));
+     
+             ((TextView) v).setTextColor(getResources().getColorStateList(
+                     android.R.color.white));
+     
              return v;
          }
      
           */
          @Override
          public void onReceive(Context context, Intent intent) {
 -            boolean inProgress = intent.getBooleanExtra(
 -                    FileSyncService.IN_PROGRESS, false);
 -            String accountName = intent
 -                    .getStringExtra(FileSyncService.ACCOUNT_NAME);
 +            boolean inProgress = intent.getBooleanExtra(FileSyncService.IN_PROGRESS, false);
 +            String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
  
 -            Log.d("FileDisplay", "sync of account " + accountName
 -                    + " is in_progress: " + inProgress);
 +            Log_OC.d("FileDisplay", "sync of account " + accountName + " is in_progress: " + inProgress);
  
-             if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {
-                 String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
+             if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {  
+             
+                 String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH); 
+                  
                  boolean fillBlankRoot = false;
                  if (mCurrentDir == null) {
                      mCurrentDir = mStorageManager.getFileByPath("/");
                      fillBlankRoot = (mCurrentDir != null);
                  }
  
-                 if ((synchFolderRemotePath != null && mCurrentDir != null && (mCurrentDir.getRemotePath()
-                         .equals(synchFolderRemotePath))) || fillBlankRoot) {
-                     if (!fillBlankRoot)
+                 if ((synchFolderRemotePath != null && mCurrentDir != null && (mCurrentDir.getRemotePath().equals(synchFolderRemotePath)))
+                         || fillBlankRoot ) {
+                     if (!fillBlankRoot) 
                          mCurrentDir = getStorageManager().getFileByPath(synchFolderRemotePath);
                      OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
                              .findFragmentById(R.id.fileList);
                  }
                  
                  setSupportProgressBarIndeterminateVisibility(inProgress);
+                 if (mBackFromCreatingFirstAccount) {
+                     // awful patch to fix problem with visibility of progress circle with the first refresh of the first account
+                     // TODO - kill this Activity when the first account has to be created instead of stack the account creation on it
+                     getSupportActionBar().hide();
+                     getSupportActionBar().show();
+                     mBackFromCreatingFirstAccount = false;
+                 }
                  removeStickyBroadcast(intent);
                  
              }
-             RemoteOperationResult synchResult = (RemoteOperationResult) intent
-                     .getSerializableExtra(FileSyncService.SYNC_RESULT);
+             
+             RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
              if (synchResult != null) {
                  if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
                      mLastSslUntrustedServerResult = synchResult;
-                     showDialog(DIALOG_SSL_VALIDATOR);
+                     showDialog(DIALOG_SSL_VALIDATOR); 
                  }
              }
          }
              String uploadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
              String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
              boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
-             boolean isDescendant = (mCurrentDir != null) && (uploadedRemotePath != null)
-                     && (uploadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+             boolean isDescendant = (mCurrentDir != null) && (uploadedRemotePath != null) && (uploadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
              if (sameAccount && isDescendant) {
-                 OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
-                         .findFragmentById(R.id.fileList);
-                 if (fileListFragment != null) {
+                 OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+                 if (fileListFragment != null) { 
                      fileListFragment.listDirectory();
                  }
              }
      
      
      /**
-      * Once the file download has finished -> update view
+      * Class waiting for broadcast events from the {@link FielDownloader} service.
+      * 
+      * Updates the UI when a download is started or finished, provided that it is relevant for the
+      * current folder.
       */
      private class DownloadFinishReceiver extends BroadcastReceiver {
          @Override
          public void onReceive(Context context, Intent intent) {
+             boolean sameAccount = isSameAccount(context, intent);
              String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
-             String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
-             boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
-             boolean isDescendant = (mCurrentDir != null) && (downloadedRemotePath != null)
-                     && (downloadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+             boolean isDescendant = isDescendant(downloadedRemotePath);
+             
              if (sameAccount && isDescendant) {
-                 OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
-                         .findFragmentById(R.id.fileList);
-                 if (fileListFragment != null) {
-                     fileListFragment.listDirectory();
+                 updateLeftPanel();
+                 if (mDualPane) {
+                     updateRightPanel(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
                  }
              }
+             
+             removeStickyBroadcast(intent);
+         }
+         private boolean isDescendant(String downloadedRemotePath) {
+             return (mCurrentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+         }
+         private boolean isSameAccount(Context context, Intent intent) {
+             String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
+             return (accountName != null && accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name));
          }
      }
      
      
-     
-     
+     protected void updateLeftPanel() {
+         OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+         if (fileListFragment != null) { 
+             fileListFragment.listDirectory();
+         }
+     }
+     protected void updateRightPanel(String downloadEvent, String downloadedRemotePath, boolean success) {
+         Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+         boolean waitedPreview = (mWaitingToPreview != null && mWaitingToPreview.getRemotePath().equals(downloadedRemotePath));
+         if (fragment != null && fragment instanceof FileDetailFragment) {
+             FileDetailFragment detailsFragment = (FileDetailFragment) fragment;
+             OCFile fileInFragment = detailsFragment.getFile();
+             if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) {
+                 // the user browsed to other file ; forget the automatic preview 
+                 mWaitingToPreview = null;
+                 
+             } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
+                 // grant that the right panel updates the progress bar
+                 detailsFragment.listenForTransferProgress();
+                 detailsFragment.updateFileDetails(true, false);
+                 
+             } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+                 //  update the right panel 
+                 if (success && waitedPreview) {
+                     mWaitingToPreview = mStorageManager.getFileById(mWaitingToPreview.getFileId());   // update the file from database, for the local storage path
+                     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+                     transaction.replace(R.id.file_details_container, new PreviewMediaFragment(mWaitingToPreview, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+                     transaction.commit();
+                     mWaitingToPreview = null;
+                     
+                 } else {
+                     detailsFragment.updateFileDetails(false, (success));
+                 }
+             }
+         }
+     }
      /**
       * {@inheritDoc}
       */
          return mStorageManager;
      }
      
-     
      /**
       * {@inheritDoc}
       */
          
          if (mDualPane) {
              // Resets the FileDetailsFragment on Tablets so that it always displays
-             FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
-             if (fileDetails != null && !fileDetails.isEmpty()) {
+             Fragment fileFragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+             if (fileFragment != null && (fileFragment instanceof PreviewMediaFragment || !((FileDetailFragment) fileFragment).isEmpty())) {
                  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                 transaction.remove(fileDetails);
-                 transaction.add(R.id.file_details_container, new FileDetailFragment(null, null),
-                         FileDetailFragment.FTAG);
+                 transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment                
                  transaction.commit();
              }
          }
       */
      @Override
      public void onFileClick(OCFile file) {
-         
-         // If we are on a large device -> update fragment
+         if (file != null && PreviewImageFragment.canBePreviewed(file)) {
+             // preview image - it handles the download, if needed
+             startPreviewImage(file);
+             
+         } else if (file != null && PreviewMediaFragment.canBePreviewed(file)) {
+             if (file.isDown()) {
+                 // general preview
+                 startMediaPreview(file);
+                 
+             } else {
+                 // automatic download, preview on finish
+                 startDownloadForPreview(file);
+                 
+             }
+         } else {
+             // details view
+             startDetails(file);
+         }
+     }
+     private void startPreviewImage(OCFile file) {
+         Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+         showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+         showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+         startActivity(showDetailsIntent);
+     }
+     
+     private void startMediaPreview(OCFile file) {
          if (mDualPane) {
-             // buttons in the details view are problematic when trying to reuse an existing fragment; create always a new one solves some of them, BUT no all; downloads are 'dangerous'
              FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-             transaction
-                     .replace(R.id.file_details_container,
-                             new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)),
-                             FileDetailFragment.FTAG);
-             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+             transaction.replace(R.id.file_details_container, new PreviewMediaFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
              transaction.commit();
-         } else { // small or medium screen device -> new Activity
+             
+         } else {
              Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
              showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
              showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
          }
      }
      
+     private void startDownloadForPreview(OCFile file) {
+         if (mDualPane) {
+             FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+             transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+             transaction.commit();
+             mWaitingToPreview = file;
+             requestForDownload();
+             
+         } else {
+             Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+             startActivity(showDetailsIntent);
+         }
+     }
      
+     private void startDetails(OCFile file) {
+         if (mDualPane && !file.isImage()) {
+             FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+             transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+             transaction.commit();
+         } else {
+             Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+             startActivity(showDetailsIntent);
+         }
+     }
      /**
       * {@inheritDoc}
       */
       */
      @Override
      public void onFileStateChanged() {
-         OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(
-                 R.id.fileList);
-         if (fileListFragment != null) {
+         OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+         if (fileListFragment != null) { 
              fileListFragment.listDirectory();
          }
      }
          @Override
          public void onServiceConnected(ComponentName component, IBinder service) {
              if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
 -                Log.d(TAG, "Download service connected");
 +                Log_OC.d(TAG, "Download service connected");
                  mDownloaderBinder = (FileDownloaderBinder) service;
+                 if (mWaitingToPreview != null) {
+                     requestForDownload();
+                 }
+                 
              } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
 -                Log.d(TAG, "Upload service connected");
 +                Log_OC.d(TAG, "Upload service connected");
                  mUploaderBinder = (FileUploaderBinder) service;
              } else {
                  return;
              if (mFileList != null)
                  mFileList.listDirectory();
              if (mDualPane) {
-                 FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
-                         FileDetailFragment.FTAG);
-                 if (fragment != null)
-                     fragment.updateFileDetails(false);
+                 Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+                 if (fragment != null && fragment instanceof FileDetailFragment) {
+                     FileDetailFragment detailFragment = (FileDetailFragment)fragment;
+                     detailFragment.listenForTransferProgress();
+                     detailFragment.updateFileDetails(false, false);
+                 }
              }
          }
  
          @Override
          public void onServiceDisconnected(ComponentName component) {
              if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
 -                Log.d(TAG, "Download service disconnected");
 +                Log_OC.d(TAG, "Download service disconnected");
                  mDownloaderBinder = null;
              } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
 -                Log.d(TAG, "Upload service disconnected");
 +                Log_OC.d(TAG, "Upload service disconnected");
                  mUploaderBinder = null;
              }
          }
          startSynchronization();                
      }
  
      @Override
      public void onFailedSavingCertificate() {
          showDialog(DIALOG_CERT_NOT_SAVED);
      @Override
      public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
          if (operation instanceof RemoveFileOperation) {
-             onRemoveFileOperationFinish((RemoveFileOperation) operation, result);
+             onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
+                 
          } else if (operation instanceof RenameFileOperation) {
-             onRenameFileOperationFinish((RenameFileOperation) operation, result);
+             onRenameFileOperationFinish((RenameFileOperation)operation, result);
+             
          } else if (operation instanceof SynchronizeFileOperation) {
-             onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
+             onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
          }
      }
  
              msg.show();
              OCFile removedFile = operation.getFile();
              if (mDualPane) {
-                 FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
-                         FileDetailFragment.FTAG);
-                 if (details != null && removedFile.equals(details.getDisplayedFile())) {
+                 FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+                 if (details != null && removedFile.equals(details.getFile())) {
                      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                     transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty
-                                                                                                           // FileDetailFragment
+                     transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment
                      transaction.commit();
                  }
              }
              }
                  
          } else {
-             Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG);
+             Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG); 
              msg.show();
              if (result.isSslRecoverableException()) {
                  mLastSslUntrustedServerResult = result;
-                 showDialog(DIALOG_SSL_VALIDATOR);
+                 showDialog(DIALOG_SSL_VALIDATOR); 
              }
          }
      }
          OCFile renamedFile = operation.getFile();
          if (result.isSuccess()) {
              if (mDualPane) {
-                 FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
-                         FileDetailFragment.FTAG);
-                 if (details != null && renamedFile.equals(details.getDisplayedFile())) {
-                     details.updateFileDetails(renamedFile, AccountUtils.getCurrentOwnCloudAccount(this));
+                 FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+                 if (details != null && details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) {
+                     ((FileDetailFragment) details).updateFileDetails(renamedFile, AccountUtils.getCurrentOwnCloudAccount(this));
                  }
              }
              if (mStorageManager.getFileById(renamedFile.getParentId()).equals(mCurrentDir)) {
              
          } else {
              if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) {
-                 Toast msg = Toast.makeText(this, R.string.rename_local_fail_msg, Toast.LENGTH_LONG);
+                 Toast msg = Toast.makeText(this, R.string.rename_local_fail_msg, Toast.LENGTH_LONG); 
                  msg.show();
                  // TODO throw again the new rename dialog
              } else {
-                 Toast msg = Toast.makeText(this, R.string.rename_server_fail_msg, Toast.LENGTH_LONG);
+                 Toast msg = Toast.makeText(this, R.string.rename_server_fail_msg, Toast.LENGTH_LONG); 
                  msg.show();
                  if (result.isSslRecoverableException()) {
                      mLastSslUntrustedServerResult = result;
-                     showDialog(DIALOG_SSL_VALIDATOR);
+                     showDialog(DIALOG_SSL_VALIDATOR); 
                  }
              }
          }
      }
  
      private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {
          dismissDialog(DIALOG_SHORT_WAIT);
          OCFile syncedFile = operation.getLocalFile();
                  startActivity(i);
                  
              } else {
-                 Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG);
+                 Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG); 
                  msg.show();
              }
              
                  onTransferStateChanged(syncedFile, true, true);
                  
              } else {
-                 Toast msg = Toast.makeText(this, R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG);
+                 Toast msg = Toast.makeText(this, R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); 
                  msg.show();
              }
          }
              fileListFragment.listDirectory();
          }*/
          if (mDualPane) {
-             FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
-                     FileDetailFragment.FTAG);
-             if (details != null && file.equals(details.getDisplayedFile())) {
+             FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+             if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) {
                  if (downloading || uploading) {
-                     details.updateFileDetails(file, AccountUtils.getCurrentOwnCloudAccount(this));
+                     ((FileDetailFragment)details).updateFileDetails(file, AccountUtils.getCurrentOwnCloudAccount(this));
                  } else {
-                     details.updateFileDetails(downloading || uploading);
+                     ((FileDetailFragment)details).updateFileDetails(false, true);
                  }
              }
          }
      }
  
  
-     
+     @Override
+     public void showFragmentWithDetails(OCFile file) {
+         if (mDualPane) {
+             FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+             transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG); 
+             transaction.commit();
+             
+         } else {
+             Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+             showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+             showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+             startActivity(showDetailsIntent);
+         }
+     }
  
+     public void onDismiss(EditNameDialog dialog) {
+         //dialog.dismiss();
+         if (dialog.getResult()) {
+             String newDirectoryName = dialog.getNewFilename().trim();
+             Log.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
+             if (newDirectoryName.length() > 0) {
+                 String path;
+                 if (mCurrentDir == null) {
+                     // this is just a patch; we should ensure that mCurrentDir never is null
+                     if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
+                         OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
+                         mStorageManager.saveFile(file);
+                     }
+                     mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+                 }
+                 path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
+                 
+                 // Create directory
+                 path += newDirectoryName + OCFile.PATH_SEPARATOR;
+                 Thread thread = new Thread(new DirectoryCreator(path,  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
+                 thread.start();
+                 
+                 showDialog(DIALOG_SHORT_WAIT);
+             }
+         }
+     }
+     private void requestForDownload() {
+         Account account = AccountUtils.getCurrentOwnCloudAccount(this);
+         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
+             Intent i = new Intent(this, FileDownloader.class);
+             i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
+             i.putExtra(FileDownloader.EXTRA_FILE, mWaitingToPreview);
+             startService(i);
+         }
+     }
  
+     
  }
@@@ -32,6 -32,7 +32,7 @@@ import android.util.SparseArray
  import android.view.Gravity;
  import android.view.View;
  import android.view.View.OnClickListener;
+ import android.view.View.OnLongClickListener;
  import android.view.ViewGroup;
  import android.widget.Button;
  import android.widget.CheckBox;
@@@ -39,23 -40,23 +40,24 @@@ import android.widget.CompoundButton
  import android.widget.CompoundButton.OnCheckedChangeListener;
  import android.widget.ImageButton;
  import android.widget.LinearLayout;
+ import android.widget.TextView;
  import android.widget.Toast;
  
  import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.R;
  import com.owncloud.android.db.DbHandler;
  import com.owncloud.android.files.InstantUploadBroadcastReceiver;
  import com.owncloud.android.files.services.FileUploader;
- import com.owncloud.android.files.services.InstantUploadService;
+ import com.owncloud.android.utils.FileStorageUtils;
  
  /**
   * This Activity is used to display a list with images they could not be
   * uploaded instantly. The images can be selected for delete or for a try again
   * upload
   * 
-  * The entrypoint for this activity is the 'Failed upload Notification" and a
-  * submenue underneath the 'Upload' menuentry
+  * The entry-point for this activity is the 'Failed upload Notification" and a
+  * sub-menu underneath the 'Upload' menu-item
   * 
   * @author andomaex / Matthias Baumann
   * 
@@@ -74,10 -75,12 +76,12 @@@ public class InstantUploadActivity exte
      private static final String LOG_TAG = InstantUploadActivity.class.getSimpleName();
      private LinearLayout listView;
      private static final String retry_chexbox_tag = "retry_chexbox_tag";
+     public static final boolean IS_ENABLED = false;
      private static int MAX_LOAD_IMAGES = 5;
      private int lastLoadImageIdx = 0;
  
      private SparseArray<String> fileList = null;
+     CheckBox failed_upload_all_cb;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
@@@ -88,7 -91,7 +92,7 @@@
          delete_all_btn.setOnClickListener(getDeleteListner());
          Button retry_all_btn = (Button) findViewById(R.id.failed_upload_retry_all_btn);
          retry_all_btn.setOnClickListener(getRetryListner());
-         CheckBox failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb);
+         this.failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb);
          failed_upload_all_cb.setOnCheckedChangeListener(getCheckAllListener());
          listView = (LinearLayout) findViewById(R.id.failed_upload_scrollviewlayout);
  
  
                      lastLoadImageIdx++;
                      String imp_path = c.getString(1);
+                     String message = c.getString(4);
                      fileList.put(lastLoadImageIdx, imp_path);
-                     LinearLayout rowLayout = getLinearLayout(lastLoadImageIdx);
+                     LinearLayout rowLayout = getHorizontalLinearLayout(lastLoadImageIdx);
                      rowLayout.addView(getFileCheckbox(lastLoadImageIdx));
                      rowLayout.addView(getImageButton(imp_path, lastLoadImageIdx));
-                     rowLayout.addView(getFileButton(imp_path, lastLoadImageIdx));
+                     rowLayout.addView(getFileButton(imp_path, message, lastLoadImageIdx));
                      listView.addView(rowLayout);
 -                    Log.d(LOG_TAG, imp_path + " on idx: " + lastLoadImageIdx);
 +                    Log_OC.d(LOG_TAG, imp_path + " on idx: " + lastLoadImageIdx);
                      if (lastLoadImageIdx % MAX_LOAD_IMAGES == 0) {
                          break;
                      }
      private List<CheckBox> getCheckboxList() {
          List<CheckBox> list = new ArrayList<CheckBox>();
          for (int i = 0; i < listView.getChildCount(); i++) {
 -            Log.d(LOG_TAG, "ListView has Childs: " + listView.getChildCount());
 +            Log_OC.d(LOG_TAG, "ListView has Childs: " + listView.getChildCount());
              View childView = listView.getChildAt(i);
              if (childView != null && childView instanceof ViewGroup) {
                  View checkboxView = getChildViews((ViewGroup) childView);
                  if (checkboxView != null && checkboxView instanceof CheckBox) {
 -                    Log.d(LOG_TAG, "found Child: " + checkboxView.getId() + " " + checkboxView.getClass());
 +                    Log_OC.d(LOG_TAG, "found Child: " + checkboxView.getId() + " " + checkboxView.getClass());
                      list.add((CheckBox) checkboxView);
                  }
              }
              public void onClick(View v) {
  
                  try {
                      List<CheckBox> list = getCheckboxList();
                      for (CheckBox checkbox : list) {
                          boolean to_retry = checkbox.isChecked();
  
 -                        Log.d(LOG_TAG, "Checkbox for " + checkbox.getId() + " was checked: " + to_retry);
 +                        Log_OC.d(LOG_TAG, "Checkbox for " + checkbox.getId() + " was checked: " + to_retry);
                          String img_path = fileList.get(checkbox.getId());
                          if (to_retry) {
  
                              final String msg = "Image-Path " + checkbox.getId() + " was checked: " + img_path;
 -                            Log.d(LOG_TAG, msg);
 +                            Log_OC.d(LOG_TAG, msg);
                              startUpload(img_path);
                          }
  
                      // refresh the List
                      listView.removeAllViews();
                      loadListView(true);
+                     if (failed_upload_all_cb != null) {
+                         failed_upload_all_cb.setChecked(false);
+                     }
                  }
  
              }
  
              @Override
              public void onClick(View v) {
                  final DbHandler dbh = new DbHandler(getApplicationContext());
                  try {
                      List<CheckBox> list = getCheckboxList();
                      for (CheckBox checkbox : list) {
                          boolean to_be_delete = checkbox.isChecked();
  
 -                        Log.d(LOG_TAG, "Checkbox for " + checkbox.getId() + " was checked: " + to_be_delete);
 +                        Log_OC.d(LOG_TAG, "Checkbox for " + checkbox.getId() + " was checked: " + to_be_delete);
                          String img_path = fileList.get(checkbox.getId());
 -                        Log.d(LOG_TAG, "Image-Path " + checkbox.getId() + " was checked: " + img_path);
 +                        Log_OC.d(LOG_TAG, "Image-Path " + checkbox.getId() + " was checked: " + img_path);
                          if (to_be_delete) {
                              boolean deleted = dbh.removeIUPendingFile(img_path);
 -                            Log.d(LOG_TAG, "removing " + checkbox.getId() + " was : " + deleted);
 +                            Log_OC.d(LOG_TAG, "removing " + checkbox.getId() + " was : " + deleted);
  
                          }
  
                      // refresh the List
                      listView.removeAllViews();
                      loadListView(true);
+                     if (failed_upload_all_cb != null) {
+                         failed_upload_all_cb.setChecked(false);
+                     }
                  }
  
              }
          };
      }
  
-     private LinearLayout getLinearLayout(int id) {
+     private LinearLayout getHorizontalLinearLayout(int id) {
          LinearLayout linearLayout = new LinearLayout(getApplicationContext());
          linearLayout.setId(id);
          linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
          return linearLayout;
      }
  
-     private Button getFileButton(final String img_path, int id) {
-         Button retryButton = new Button(this);
+     private LinearLayout getVerticalLinearLayout() {
+         LinearLayout linearLayout = new LinearLayout(getApplicationContext());
+         linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+                 LinearLayout.LayoutParams.MATCH_PARENT));
+         linearLayout.setGravity(Gravity.TOP);
+         linearLayout.setOrientation(LinearLayout.VERTICAL);
+         return linearLayout;
+     }
+     private View getFileButton(final String img_path, String message, int id) {
+         TextView failureTextView = new TextView(this);
+         failureTextView.setText(getString(R.string.failed_upload_failure_text) + message);
+         failureTextView.setBackgroundResource(R.color.owncloud_white);
+         failureTextView.setTextSize(8);
+         failureTextView.setOnLongClickListener(getOnLongClickListener(message));
+         failureTextView.setPadding(5, 5, 5, 10);
+         TextView retryButton = new TextView(this);
          retryButton.setId(id);
          retryButton.setText(img_path);
          retryButton.setBackgroundResource(R.color.owncloud_white);
          retryButton.setTextSize(8);
          retryButton.setOnClickListener(getImageButtonOnClickListener(img_path));
-         return retryButton;
+         retryButton.setOnLongClickListener(getOnLongClickListener(message));
+         retryButton.setPadding(5, 5, 5, 10);
+         LinearLayout verticalLayout = getVerticalLinearLayout();
+         verticalLayout.addView(retryButton);
+         verticalLayout.addView(failureTextView);
+         return verticalLayout;
+     }
+     private OnLongClickListener getOnLongClickListener(final String message) {
+         return new OnLongClickListener() {
+             @Override
+             public boolean onLongClick(View v) {
+                 Log.d(LOG_TAG, message);
+                 Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
+                         + message, Toast.LENGTH_LONG);
+                 toast.show();
+                 return true;
+             }
+         };
      }
  
      private CheckBox getFileCheckbox(int id) {
          // scale and add a thumbnail to the imagebutton
          int base_scale_size = 32;
          if (img_path != null) {
 -            Log.d(LOG_TAG, "add " + img_path + " to Image Button");
 +            Log_OC.d(LOG_TAG, "add " + img_path + " to Image Button");
              BitmapFactory.Options options = new BitmapFactory.Options();
              options.inJustDecodeBounds = true;
              Bitmap bitmap = BitmapFactory.decodeFile(img_path, options);
                  scale++;
              }
  
 -            Log.d(LOG_TAG, "scale Imgae with: " + scale);
 +            Log_OC.d(LOG_TAG, "scale Imgae with: " + scale);
              BitmapFactory.Options options2 = new BitmapFactory.Options();
              options2.inSampleSize = scale;
              bitmap = BitmapFactory.decodeFile(img_path, options2);
  
              if (bitmap != null) {
 -                Log.d(LOG_TAG, "loaded Bitmap Bytes: " + bitmap.getRowBytes());
 +                Log_OC.d(LOG_TAG, "loaded Bitmap Bytes: " + bitmap.getRowBytes());
                  imageButton.setImageBitmap(bitmap);
              } else {
 -                Log.d(LOG_TAG, "could not load imgage: " + img_path);
 +                Log_OC.d(LOG_TAG, "could not load imgage: " + img_path);
              }
          }
          return imageButton;
       */
      private void startUpload(String img_path) {
          // extract filename
-         String filename = img_path.substring(img_path.lastIndexOf('/'), img_path.length());
+         String filename = FileStorageUtils.getInstantUploadFilePath(img_path);
          if (canInstantUpload()) {
              Account account = AccountUtils.getCurrentOwnCloudAccount(InstantUploadActivity.this);
              // add file again to upload queue
              DbHandler db = new DbHandler(InstantUploadActivity.this);
              try {
-                 db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER);
+                 db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER, null);
              } finally {
                  db.close();
              }
              Intent i = new Intent(InstantUploadActivity.this, FileUploader.class);
              i.putExtra(FileUploader.KEY_ACCOUNT, account);
              i.putExtra(FileUploader.KEY_LOCAL_FILE, img_path);
-             i.putExtra(FileUploader.KEY_REMOTE_FILE, InstantUploadService.INSTANT_UPLOAD_DIR + "/" + filename);
+             i.putExtra(FileUploader.KEY_REMOTE_FILE, filename);
              i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
              i.putExtra(com.owncloud.android.files.services.FileUploader.KEY_INSTANT_UPLOAD, true);
  
              final String msg = "try to upload file with name :" + filename;
 -            Log.d(LOG_TAG, msg);
 +            Log_OC.d(LOG_TAG, msg);
              Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
                      + filename, Toast.LENGTH_LONG);
              toast.show();
@@@ -44,7 -44,6 +44,7 @@@ import com.owncloud.android.ui.fragment
  import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
  import com.owncloud.android.utils.FileStorageUtils;
  
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.R;
  
  /**
@@@ -79,7 -78,7 +79,7 @@@ public class UploadFilesActivity extend
      
      @Override
      public void onCreate(Bundle savedInstanceState) {
 -        Log.d(TAG, "onCreate() start");
 +        Log_OC.d(TAG, "onCreate() start");
          super.onCreate(savedInstanceState);
  
          if(savedInstanceState != null) {
              mCurrentDialog = null;
          }
              
 -        Log.d(TAG, "onCreate() end");
 +        Log_OC.d(TAG, "onCreate() end");
      }
  
  
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
 -        Log.d(TAG, "onSaveInstanceState() start");
 +        Log_OC.d(TAG, "onSaveInstanceState() start");
          super.onSaveInstanceState(outState);
          outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath());
 -        Log.d(TAG, "onSaveInstanceState() end");
 +        Log_OC.d(TAG, "onSaveInstanceState() end");
      }
  
      
                  String[] args = {getString(R.string.app_name)};
                  ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no);
                  dialog.setOnConfirmationListener(UploadFilesActivity.this);
-                 mCurrentDialog = dialog;
-                 mCurrentDialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG);
+                 dialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG);
              }
          }
      }
  
      @Override
      public void onConfirmation(String callerTag) {
 -        Log.d(TAG, "Positive button in dialog was clicked; dialog tag is " + callerTag);
 +        Log_OC.d(TAG, "Positive button in dialog was clicked; dialog tag is " + callerTag);
          if (callerTag.equals(QUERY_TO_MOVE_DIALOG_TAG)) {
              // return the list of selected files to the caller activity (success), signaling that they should be moved to the ownCloud folder, instead of copied
              Intent data = new Intent();
              setResult(RESULT_OK_AND_MOVE, data);
              finish();
          }
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
      }
  
  
      @Override
      public void onNeutral(String callerTag) {
 -        Log.d(TAG, "Phantom neutral button in dialog was clicked; dialog tag is " + callerTag);
 +        Log_OC.d(TAG, "Phantom neutral button in dialog was clicked; dialog tag is " + callerTag);
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
      }
  
  
      @Override
      public void onCancel(String callerTag) {
          /// nothing to do; don't finish, let the user change the selection
 -        Log.d(TAG, "Negative button in dialog was clicked; dialog tag is " + callerTag);
 +        Log_OC.d(TAG, "Negative button in dialog was clicked; dialog tag is " + callerTag);
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
      }    
  
      
@@@ -26,7 -26,6 +26,7 @@@ import android.os.Bundle
  import android.util.Log;
  
  import com.actionbarsherlock.app.SherlockDialogFragment;
 +import com.owncloud.android.Log_OC;
  
  public class ConfirmationDialogFragment extends SherlockDialogFragment {
  
@@@ -37,6 -36,8 +37,8 @@@
      public final static String ARG_NEUTRAL_BTN_RES = "neutral_btn_res";
      public final static String ARG_NEGATIVE_BTN_RES = "negative_btn_res";
      
+     public static final String FTAG_CONFIRMATION = "CONFIRMATION_FRAGMENT";
      private ConfirmationDialogFragmentListener mListener;
      
      /**
@@@ -74,7 -75,7 +76,7 @@@
          int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1);
          
          if (confirmationTarget == null || resourceId == -1) {
 -            Log.wtf(getTag(), "Calling confirmation dialog without resource or arguments");
 +            Log_OC.wtf(getTag(), "Calling confirmation dialog without resource or arguments");
              return null;
          }
  
@@@ -91,6 -92,7 +93,7 @@@
                      new DialogInterface.OnClickListener() {
                          public void onClick(DialogInterface dialog, int whichButton) {
                              mListener.onConfirmation(getTag()); 
+                             dialog.dismiss();
                          }
                      });
          if (neuBtn != -1)
                      new DialogInterface.OnClickListener() {
                          public void onClick(DialogInterface dialog, int whichButton) {
                              mListener.onNeutral(getTag()); 
+                             dialog.dismiss();
                          }
                      });
          if (negBtn != -1)
                          @Override
                          public void onClick(DialogInterface dialog, int which) {
                              mListener.onCancel(getTag());
+                             dialog.dismiss();
                          }
                      });
        return builder.create();
 -/* ownCloud Android client application\r
 - *   Copyright (C) 2011  Bartek Przybylski\r
 - *   Copyright (C) 2012-2013 ownCloud Inc.\r
 - *\r
 - *   This program is free software: you can redistribute it and/or modify\r
 - *   it under the terms of the GNU General Public License as published by\r
 - *   the Free Software Foundation, either version 2 of the License, or\r
 - *   (at your option) any later version.\r
 - *\r
 - *   This program is distributed in the hope that it will be useful,\r
 - *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 - *   GNU General Public License for more details.\r
 - *\r
 - *   You should have received a copy of the GNU General Public License\r
 - *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - *\r
 - */\r
 -package com.owncloud.android.ui.fragment;\r
 -\r
 -import java.io.File;\r
 -import java.lang.ref.WeakReference;\r
 -import java.util.ArrayList;\r
 -import java.util.List;\r
 -\r
 -import org.apache.commons.httpclient.methods.GetMethod;\r
 -import org.apache.commons.httpclient.methods.PostMethod;\r
 -import org.apache.commons.httpclient.methods.StringRequestEntity;\r
 -import org.apache.commons.httpclient.params.HttpConnectionManagerParams;\r
 -import org.apache.http.HttpStatus;\r
 -import org.apache.http.NameValuePair;\r
 -import org.apache.http.client.utils.URLEncodedUtils;\r
 -import org.apache.http.message.BasicNameValuePair;\r
 -import org.apache.http.protocol.HTTP;\r
 -import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;\r
 -import org.json.JSONObject;\r
 -\r
 -import android.accounts.Account;\r
 -import android.accounts.AccountManager;\r
 -import android.app.Activity;\r
 -import android.content.ActivityNotFoundException;\r
 -import android.content.BroadcastReceiver;\r
 -import android.content.Context;\r
 -import android.content.Intent;\r
 -import android.content.IntentFilter;\r
 -import android.net.Uri;\r
 -import android.os.Bundle;\r
 -import android.os.Handler;\r
 -import android.support.v4.app.FragmentTransaction;\r
 -import android.util.Log;\r
 -import android.view.LayoutInflater;\r
 -import android.view.View;\r
 -import android.view.View.OnClickListener;\r
 -import android.view.ViewGroup;\r
 -import android.webkit.MimeTypeMap;\r
 -import android.widget.Button;\r
 -import android.widget.CheckBox;\r
 -import android.widget.ImageView;\r
 -import android.widget.ProgressBar;\r
 -import android.widget.TextView;\r
 -import android.widget.Toast;\r
 -\r
 -import com.actionbarsherlock.app.SherlockFragment;\r
 -import com.owncloud.android.AccountUtils;\r
 -import com.owncloud.android.DisplayUtils;\r
 -import com.owncloud.android.authenticator.AccountAuthenticator;\r
 -import com.owncloud.android.datamodel.FileDataStorageManager;\r
 -import com.owncloud.android.datamodel.OCFile;\r
 -import com.owncloud.android.files.services.FileObserverService;\r
 -import com.owncloud.android.files.services.FileUploader;\r
 -import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 -import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
 -import com.owncloud.android.network.OwnCloudClientUtils;\r
 -import com.owncloud.android.operations.OnRemoteOperationListener;\r
 -import com.owncloud.android.operations.RemoteOperation;\r
 -import com.owncloud.android.operations.RemoteOperationResult;\r
 -import com.owncloud.android.operations.RemoteOperationResult.ResultCode;\r
 -import com.owncloud.android.operations.RemoveFileOperation;\r
 -import com.owncloud.android.operations.RenameFileOperation;\r
 -import com.owncloud.android.operations.SynchronizeFileOperation;\r
 -import com.owncloud.android.ui.activity.ConflictsResolveActivity;\r
 -import com.owncloud.android.ui.activity.FileDetailActivity;\r
 -import com.owncloud.android.ui.activity.FileDisplayActivity;\r
 -import com.owncloud.android.ui.dialog.EditNameDialog;\r
 -import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;\r
 -import com.owncloud.android.utils.OwnCloudVersion;\r
 -\r
 -import com.owncloud.android.R;\r
 -\r
 -import eu.alefzero.webdav.OnDatatransferProgressListener;\r
 -import eu.alefzero.webdav.WebdavClient;\r
 -import eu.alefzero.webdav.WebdavUtils;\r
 -\r
 -/**\r
 - * This Fragment is used to display the details about a file.\r
 - * \r
 - * @author Bartek Przybylski\r
 - * @author David A. Velasco\r
 - */\r
 -public class FileDetailFragment extends SherlockFragment implements\r
 -        OnClickListener, \r
 -        ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener,\r
 -        FileFragment {\r
 -\r
 -    public static final String EXTRA_FILE = "FILE";\r
 -    public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
 -\r
 -    private FileFragment.ContainerActivity mContainerActivity;\r
 -    \r
 -    private int mLayout;\r
 -    private View mView;\r
 -    private OCFile mFile;\r
 -    private Account mAccount;\r
 -    private FileDataStorageManager mStorageManager;\r
 -    \r
 -    private UploadFinishReceiver mUploadFinishReceiver;\r
 -    public ProgressListener mProgressListener;\r
 -    \r
 -    private Handler mHandler;\r
 -    private RemoteOperation mLastRemoteOperation;\r
 -    \r
 -    private static final String TAG = FileDetailFragment.class.getSimpleName();\r
 -    public static final String FTAG = "FileDetails"; \r
 -    public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";\r
 -\r
 -    \r
 -    /**\r
 -     * Creates an empty details fragment.\r
 -     * \r
 -     * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically. \r
 -     */\r
 -    public FileDetailFragment() {\r
 -        mFile = null;\r
 -        mAccount = null;\r
 -        mStorageManager = null;\r
 -        mLayout = R.layout.file_details_empty;\r
 -        mProgressListener = null;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Creates a details fragment.\r
 -     * \r
 -     * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).\r
 -     * \r
 -     * @param fileToDetail      An {@link OCFile} to show in the fragment\r
 -     * @param ocAccount         An ownCloud account; needed to start downloads\r
 -     */\r
 -    public FileDetailFragment(OCFile fileToDetail, Account ocAccount) {\r
 -        mFile = fileToDetail;\r
 -        mAccount = ocAccount;\r
 -        mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment \r
 -        mLayout = R.layout.file_details_empty;\r
 -        mProgressListener = null;\r
 -    }\r
 -    \r
 -    \r
 -    @Override\r
 -    public void onCreate(Bundle savedInstanceState) {\r
 -        super.onCreate(savedInstanceState);\r
 -        mHandler = new Handler();\r
 -    }\r
 -    \r
 -\r
 -    @Override\r
 -    public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
 -            Bundle savedInstanceState) {\r
 -        super.onCreateView(inflater, container, savedInstanceState);\r
 -        \r
 -        if (savedInstanceState != null) {\r
 -            mFile = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);\r
 -            mAccount = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_ACCOUNT);\r
 -        }\r
 -        \r
 -        if(mFile != null && mAccount != null) {\r
 -            mLayout = R.layout.file_details_fragment;\r
 -        }\r
 -        \r
 -        View view = null;\r
 -        view = inflater.inflate(mLayout, container, false);\r
 -        mView = view;\r
 -        \r
 -        if (mLayout == R.layout.file_details_fragment) {\r
 -            mView.findViewById(R.id.fdKeepInSync).setOnClickListener(this);\r
 -            mView.findViewById(R.id.fdRenameBtn).setOnClickListener(this);\r
 -            mView.findViewById(R.id.fdDownloadBtn).setOnClickListener(this);\r
 -            mView.findViewById(R.id.fdOpenBtn).setOnClickListener(this);\r
 -            mView.findViewById(R.id.fdRemoveBtn).setOnClickListener(this);\r
 -            //mView.findViewById(R.id.fdShareBtn).setOnClickListener(this);\r
 -            ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);\r
 -            mProgressListener = new ProgressListener(progressBar);\r
 -        }\r
 -        \r
 -        updateFileDetails(false, false);\r
 -        return view;\r
 -    }\r
 -    \r
 -\r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    @Override\r
 -    public void onAttach(Activity activity) {\r
 -        super.onAttach(activity);\r
 -        try {\r
 -            mContainerActivity = (ContainerActivity) activity;\r
 -            \r
 -        } catch (ClassCastException e) {\r
 -            throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName());\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    @Override\r
 -    public void onActivityCreated(Bundle savedInstanceState) {\r
 -        super.onActivityCreated(savedInstanceState);\r
 -        if (mAccount != null) {\r
 -            mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
 -        }\r
 -    }\r
 -        \r
 -\r
 -    @Override\r
 -    public void onSaveInstanceState(Bundle outState) {\r
 -        super.onSaveInstanceState(outState);\r
 -        outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);\r
 -        outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);\r
 -    }\r
 -\r
 -    @Override\r
 -    public void onStart() {\r
 -        super.onStart();\r
 -        listenForTransferProgress();\r
 -    }\r
 -    \r
 -    @Override\r
 -    public void onResume() {\r
 -        super.onResume();\r
 -        mUploadFinishReceiver = new UploadFinishReceiver();\r
 -        IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
 -        getActivity().registerReceiver(mUploadFinishReceiver, filter);\r
 -\r
 -    }\r
 -\r
 -\r
 -    @Override\r
 -    public void onPause() {\r
 -        super.onPause();\r
 -        if (mUploadFinishReceiver != null) {\r
 -            getActivity().unregisterReceiver(mUploadFinishReceiver);\r
 -            mUploadFinishReceiver = null;\r
 -        }\r
 -    }\r
 -\r
 -    \r
 -    @Override\r
 -    public void onStop() {\r
 -        super.onStop();\r
 -        leaveTransferProgress();\r
 -    }\r
 -\r
 -    \r
 -    @Override\r
 -    public View getView() {\r
 -        return super.getView() == null ? mView : super.getView();\r
 -    }\r
 -\r
 -    \r
 -    @Override\r
 -    public void onClick(View v) {\r
 -        switch (v.getId()) {\r
 -            case R.id.fdDownloadBtn: {\r
 -                FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
 -                FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
 -                if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {\r
 -                    downloaderBinder.cancel(mAccount, mFile);\r
 -                    if (mFile.isDown()) {\r
 -                        setButtonsForDown();\r
 -                    } else {\r
 -                        setButtonsForRemote();\r
 -                    }\r
 -\r
 -                } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {\r
 -                    uploaderBinder.cancel(mAccount, mFile);\r
 -                    if (!mFile.fileExists()) {\r
 -                        // TODO make something better\r
 -                        if (getActivity() instanceof FileDisplayActivity) {\r
 -                            // double pane\r
 -                            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();\r
 -                            transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment\r
 -                            transaction.commit();\r
 -                            mContainerActivity.onFileStateChanged();\r
 -                        } else {\r
 -                            getActivity().finish();\r
 -                        }\r
 -                        \r
 -                    } else if (mFile.isDown()) {\r
 -                        setButtonsForDown();\r
 -                    } else {\r
 -                        setButtonsForRemote();\r
 -                    }\r
 -                    \r
 -                } else {\r
 -                    mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());\r
 -                    WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
 -                    mLastRemoteOperation.execute(wc, this, mHandler);\r
 -                \r
 -                    // update ui \r
 -                    boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -                    getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -                    \r
 -                }\r
 -                break;\r
 -            }\r
 -            case R.id.fdKeepInSync: {\r
 -                CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);\r
 -                mFile.setKeepInSync(cb.isChecked());\r
 -                mStorageManager.saveFile(mFile);\r
 -                \r
 -                /// register the OCFile instance in the observer service to monitor local updates;\r
 -                /// if necessary, the file is download \r
 -                Intent intent = new Intent(getActivity().getApplicationContext(),\r
 -                                           FileObserverService.class);\r
 -                intent.putExtra(FileObserverService.KEY_FILE_CMD,\r
 -                           (cb.isChecked()?\r
 -                                   FileObserverService.CMD_ADD_OBSERVED_FILE:\r
 -                                   FileObserverService.CMD_DEL_OBSERVED_FILE));\r
 -                intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);\r
 -                intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);\r
 -                getActivity().startService(intent);\r
 -                \r
 -                if (mFile.keepInSync()) {\r
 -                    onClick(getView().findViewById(R.id.fdDownloadBtn));    // force an immediate synchronization\r
 -                }\r
 -                break;\r
 -            }\r
 -            case R.id.fdRenameBtn: {\r
 -                EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mFile.getFileName(), this);\r
 -                dialog.show(getFragmentManager(), "nameeditdialog");\r
 -                break;\r
 -            }   \r
 -            case R.id.fdRemoveBtn: {\r
 -                ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(\r
 -                        R.string.confirmation_remove_alert,\r
 -                        new String[]{mFile.getFileName()},\r
 -                        mFile.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote,\r
 -                        mFile.isDown() ? R.string.confirmation_remove_local : -1,\r
 -                        R.string.common_cancel);\r
 -                confDialog.setOnConfirmationListener(this);\r
 -                confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);\r
 -                break;\r
 -            }\r
 -            case R.id.fdOpenBtn: {\r
 -                openFile();\r
 -                break;\r
 -            }\r
 -            default:\r
 -                Log.e(TAG, "Incorrect view clicked!");\r
 -        }\r
 -        \r
 -        /* else if (v.getId() == R.id.fdShareBtn) {\r
 -            Thread t = new Thread(new ShareRunnable(mFile.getRemotePath()));\r
 -            t.start();\r
 -        }*/\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Opens mFile.\r
 -     */\r
 -    private void openFile() {\r
 -        \r
 -        String storagePath = mFile.getStoragePath();\r
 -        String encodedStoragePath = WebdavUtils.encodePath(storagePath);\r
 -        try {\r
 -            Intent i = new Intent(Intent.ACTION_VIEW);\r
 -            i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());\r
 -            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
 -            startActivity(i);\r
 -            \r
 -        } catch (Throwable t) {\r
 -            Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());\r
 -            boolean toastIt = true; \r
 -            String mimeType = "";\r
 -            try {\r
 -                Intent i = new Intent(Intent.ACTION_VIEW);\r
 -                mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));\r
 -                if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {\r
 -                    if (mimeType != null) {\r
 -                        i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);\r
 -                    } else {\r
 -                        // desperate try\r
 -                        i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");\r
 -                    }\r
 -                    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\r
 -                    startActivity(i);\r
 -                    toastIt = false;\r
 -                }\r
 -                \r
 -            } catch (IndexOutOfBoundsException e) {\r
 -                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);\r
 -                \r
 -            } catch (ActivityNotFoundException e) {\r
 -                Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");\r
 -                \r
 -            } catch (Throwable th) {\r
 -                Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);\r
 -                \r
 -            } finally {\r
 -                if (toastIt) {\r
 -                    Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();\r
 -                }\r
 -            }\r
 -            \r
 -        }\r
 -    }\r
 -\r
 -\r
 -    @Override\r
 -    public void onConfirmation(String callerTag) {\r
 -        if (callerTag.equals(FTAG_CONFIRMATION)) {\r
 -            if (mStorageManager.getFileById(mFile.getFileId()) != null) {\r
 -                mLastRemoteOperation = new RemoveFileOperation( mFile, \r
 -                                                                true, \r
 -                                                                mStorageManager);\r
 -                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
 -                mLastRemoteOperation.execute(wc, this, mHandler);\r
 -                \r
 -                boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -                getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    @Override\r
 -    public void onNeutral(String callerTag) {\r
 -        File f = null;\r
 -        if (mFile.isDown() && (f = new File(mFile.getStoragePath())).exists()) {\r
 -            f.delete();\r
 -            mFile.setStoragePath(null);\r
 -            mStorageManager.saveFile(mFile);\r
 -            updateFileDetails(mFile, mAccount);\r
 -        }\r
 -    }\r
 -    \r
 -    @Override\r
 -    public void onCancel(String callerTag) {\r
 -        Log.d(TAG, "REMOVAL CANCELED");\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.\r
 -     * \r
 -     * @return  True when the fragment was created with the empty layout.\r
 -     */\r
 -    public boolean isEmpty() {\r
 -        return (mLayout == R.layout.file_details_empty || mFile == null || mAccount == null);\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    public OCFile getFile(){\r
 -        return mFile;\r
 -    }\r
 -    \r
 -    /**\r
 -     * Use this method to signal this Activity that it shall update its view.\r
 -     * \r
 -     * @param file : An {@link OCFile}\r
 -     */\r
 -    public void updateFileDetails(OCFile file, Account ocAccount) {\r
 -        mFile = file;\r
 -        if (ocAccount != null && ( \r
 -                mStorageManager == null || \r
 -                (mAccount != null && !mAccount.equals(ocAccount))\r
 -           )) {\r
 -            mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());\r
 -        }\r
 -        mAccount = ocAccount;\r
 -        updateFileDetails(false, false);\r
 -    }\r
 -    \r
 -\r
 -    /**\r
 -     * Updates the view with all relevant details about that file.\r
 -     *\r
 -     * TODO Remove parameter when the transferring state of files is kept in database. \r
 -     * \r
 -     * TODO REFACTORING! this method called 5 times before every time the fragment is shown! \r
 -     * \r
 -     * @param transferring      Flag signaling if the file should be considered as downloading or uploading, \r
 -     *                          although {@link FileDownloaderBinder#isDownloading(Account, OCFile)}  and \r
 -     *                          {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.\r
 -     *                          \r
 -     * @param refresh           If 'true', try to refresh the hold file from the database\r
 -     */\r
 -    public void updateFileDetails(boolean transferring, boolean refresh) {\r
 -\r
 -        if (readyToShow()) {\r
 -            \r
 -            if (refresh && mStorageManager != null) {\r
 -                mFile = mStorageManager.getFileByPath(mFile.getRemotePath());\r
 -            }\r
 -            \r
 -            // set file details\r
 -            setFilename(mFile.getFileName());\r
 -            setFiletype(mFile.getMimetype());\r
 -            setFilesize(mFile.getFileLength());\r
 -            if(ocVersionSupportsTimeCreated()){\r
 -                setTimeCreated(mFile.getCreationTimestamp());\r
 -            }\r
 -           \r
 -            setTimeModified(mFile.getModificationTimestamp());\r
 -            \r
 -            CheckBox cb = (CheckBox)getView().findViewById(R.id.fdKeepInSync);\r
 -            cb.setChecked(mFile.keepInSync());\r
 -\r
 -            // configure UI for depending upon local state of the file\r
 -            //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {\r
 -            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
 -            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
 -            if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))) {\r
 -                setButtonsForTransferring();\r
 -                \r
 -            } else if (mFile.isDown()) {\r
 -                \r
 -                setButtonsForDown();\r
 -                \r
 -            } else {\r
 -                // TODO load default preview image; when the local file is removed, the preview remains there\r
 -                setButtonsForRemote();\r
 -            }\r
 -        }\r
 -        getView().invalidate();\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Checks if the fragment is ready to show details of a OCFile\r
 -     *  \r
 -     * @return  'True' when the fragment is ready to show details of a file\r
 -     */\r
 -    private boolean readyToShow() {\r
 -        return (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment);        \r
 -    }\r
 -\r
 -\r
 -\r
 -    /**\r
 -     * Updates the filename in view\r
 -     * @param filename to set\r
 -     */\r
 -    private void setFilename(String filename) {\r
 -        TextView tv = (TextView) getView().findViewById(R.id.fdFilename);\r
 -        if (tv != null)\r
 -            tv.setText(filename);\r
 -    }\r
 -\r
 -    /**\r
 -     * Updates the MIME type in view\r
 -     * @param mimetype to set\r
 -     */\r
 -    private void setFiletype(String mimetype) {\r
 -        TextView tv = (TextView) getView().findViewById(R.id.fdType);\r
 -        if (tv != null) {\r
 -            String printableMimetype = DisplayUtils.convertMIMEtoPrettyPrint(mimetype);;        \r
 -            tv.setText(printableMimetype);\r
 -        }\r
 -        ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);\r
 -        if (iv != null) {\r
 -            iv.setImageResource(DisplayUtils.getResourceId(mimetype));\r
 -        }\r
 -    }\r
 -\r
 -    /**\r
 -     * Updates the file size in view\r
 -     * @param filesize in bytes to set\r
 -     */\r
 -    private void setFilesize(long filesize) {\r
 -        TextView tv = (TextView) getView().findViewById(R.id.fdSize);\r
 -        if (tv != null)\r
 -            tv.setText(DisplayUtils.bytesToHumanReadable(filesize));\r
 -    }\r
 -    \r
 -    /**\r
 -     * Updates the time that the file was created in view\r
 -     * @param milliseconds Unix time to set\r
 -     */\r
 -    private void setTimeCreated(long milliseconds){\r
 -        TextView tv = (TextView) getView().findViewById(R.id.fdCreated);\r
 -        TextView tvLabel = (TextView) getView().findViewById(R.id.fdCreatedLabel);\r
 -        if(tv != null){\r
 -            tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));\r
 -            tv.setVisibility(View.VISIBLE);\r
 -            tvLabel.setVisibility(View.VISIBLE);\r
 -        }\r
 -    }\r
 -    \r
 -    /**\r
 -     * Updates the time that the file was last modified\r
 -     * @param milliseconds Unix time to set\r
 -     */\r
 -    private void setTimeModified(long milliseconds){\r
 -        TextView tv = (TextView) getView().findViewById(R.id.fdModified);\r
 -        if(tv != null){\r
 -            tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));\r
 -        }\r
 -    }\r
 -    \r
 -    /**\r
 -     * Enables or disables buttons for a file being downloaded\r
 -     */\r
 -    private void setButtonsForTransferring() {\r
 -        if (!isEmpty()) {\r
 -            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
 -            downloadButton.setText(R.string.common_cancel);\r
 -            //downloadButton.setEnabled(false);\r
 -        \r
 -            // let's protect the user from himself ;)\r
 -            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);\r
 -            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);\r
 -            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);\r
 -            getView().findViewById(R.id.fdKeepInSync).setEnabled(false);\r
 -            \r
 -            // show the progress bar for the transfer\r
 -            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
 -            progressBar.setVisibility(View.VISIBLE);\r
 -            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
 -            progressText.setVisibility(View.VISIBLE);\r
 -            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();\r
 -            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();\r
 -            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {\r
 -                progressText.setText(R.string.downloader_download_in_progress_ticker);\r
 -            } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {\r
 -                progressText.setText(R.string.uploader_upload_in_progress_ticker);\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -\r
 -    /**\r
 -     * Enables or disables buttons for a file locally available \r
 -     */\r
 -    private void setButtonsForDown() {\r
 -        if (!isEmpty()) {\r
 -            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
 -            downloadButton.setText(R.string.filedetails_sync_file);\r
 -        \r
 -            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);\r
 -            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
 -            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
 -            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
 -            \r
 -            // hides the progress bar\r
 -            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
 -            progressBar.setVisibility(View.GONE);\r
 -            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
 -            progressText.setVisibility(View.GONE);\r
 -        }\r
 -    }\r
 -\r
 -    /**\r
 -     * Enables or disables buttons for a file not locally available \r
 -     */\r
 -    private void setButtonsForRemote() {\r
 -        if (!isEmpty()) {\r
 -            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
 -            downloadButton.setText(R.string.filedetails_download);\r
 -            \r
 -            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);\r
 -            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);\r
 -            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);\r
 -            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);\r
 -            \r
 -            // hides the progress bar\r
 -            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);\r
 -            progressBar.setVisibility(View.GONE);\r
 -            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);\r
 -            progressText.setVisibility(View.GONE);\r
 -        }\r
 -    }\r
 -    \r
 -\r
 -    /**\r
 -     * In ownCloud 3.X.X and 4.X.X there is a bug that SabreDAV does not return\r
 -     * the time that the file was created. There is a chance that this will\r
 -     * be fixed in future versions. Use this method to check if this version of\r
 -     * ownCloud has this fix.\r
 -     * @return True, if ownCloud the ownCloud version is supporting creation time\r
 -     */\r
 -    private boolean ocVersionSupportsTimeCreated(){\r
 -        /*if(mAccount != null){\r
 -            AccountManager accManager = (AccountManager) getActivity().getSystemService(Context.ACCOUNT_SERVICE);\r
 -            OwnCloudVersion ocVersion = new OwnCloudVersion(accManager\r
 -                    .getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION));\r
 -            if(ocVersion.compareTo(new OwnCloudVersion(0x030000)) < 0) {\r
 -                return true;\r
 -            }\r
 -        }*/\r
 -        return false;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Once the file upload has finished -> update view\r
 -     * \r
 -     * Being notified about the finish of an upload is necessary for the next sequence:\r
 -     *   1. Upload a big file.\r
 -     *   2. Force a synchronization; if it finished before the upload, the file in transfer will be included in the local database and in the file list\r
 -     *      of its containing folder; the the server includes it in the PROPFIND requests although it's not fully upload. \r
 -     *   3. Click the file in the list to see its details.\r
 -     *   4. Wait for the upload finishes; at this moment, the details view must be refreshed to enable the action buttons.\r
 -     */\r
 -    private class UploadFinishReceiver extends BroadcastReceiver {\r
 -        @Override\r
 -        public void onReceive(Context context, Intent intent) {\r
 -            String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);\r
 -\r
 -            if (!isEmpty() && accountName.equals(mAccount.name)) {\r
 -                boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);\r
 -                String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);\r
 -                boolean renamedInUpload = mFile.getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));\r
 -                if (mFile.getRemotePath().equals(uploadRemotePath) ||\r
 -                    renamedInUpload) {\r
 -                    if (uploadWasFine) {\r
 -                        mFile = mStorageManager.getFileByPath(uploadRemotePath);\r
 -                    }\r
 -                    if (renamedInUpload) {\r
 -                        String newName = (new File(uploadRemotePath)).getName();\r
 -                        Toast msg = Toast.makeText(getActivity().getApplicationContext(), String.format(getString(R.string.filedetails_renamed_in_upload_msg), newName), Toast.LENGTH_LONG);\r
 -                        msg.show();\r
 -                    }\r
 -                    getSherlockActivity().removeStickyBroadcast(intent);    // not the best place to do this; a small refactorization of BroadcastReceivers should be done\r
 -                    updateFileDetails(false, false);    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server\r
 -                }\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -\r
 -    // this is a temporary class for sharing purposes, it need to be replaced in transfer service\r
 -    @SuppressWarnings("unused")\r
 -    private class ShareRunnable implements Runnable {\r
 -        private String mPath;\r
 -\r
 -        public ShareRunnable(String path) {\r
 -            mPath = path;\r
 -        }\r
 -        \r
 -        public void run() {\r
 -            AccountManager am = AccountManager.get(getActivity());\r
 -            Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());\r
 -            OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));\r
 -            String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);\r
 -\r
 -            Log.d("share", "sharing for version " + ocv.toString());\r
 -\r
 -            if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {\r
 -                String APPS_PATH = "/apps/files_sharing/";\r
 -                String SHARE_PATH = "ajax/share.php";\r
 -\r
 -                String SHARED_PATH = "/apps/files_sharing/get.php?token=";\r
 -                \r
 -                final String WEBDAV_SCRIPT = "webdav.php";\r
 -                final String WEBDAV_FILES_LOCATION = "/files/";\r
 -                \r
 -                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());\r
 -                HttpConnectionManagerParams params = new HttpConnectionManagerParams();\r
 -                params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);\r
 -\r
 -                //wc.getParams().setParameter("http.protocol.single-cookie-header", true);\r
 -                //wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);\r
 -\r
 -                PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);\r
 -\r
 -                post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );\r
 -                post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));\r
 -                List<NameValuePair> formparams = new ArrayList<NameValuePair>();\r
 -                Log.d("share", mPath+"");\r
 -                formparams.add(new BasicNameValuePair("sources",mPath));\r
 -                formparams.add(new BasicNameValuePair("uid_shared_with", "public"));\r
 -                formparams.add(new BasicNameValuePair("permissions", "0"));\r
 -                post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));\r
 -\r
 -                int status;\r
 -                try {\r
 -                    PropFindMethod find = new PropFindMethod(url+"/");\r
 -                    find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));\r
 -                    Log.d("sharer", ""+ url+"/");\r
 -                    \r
 -                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {\r
 -                        Log.d("sharer-h", a.getName() + ":"+a.getValue());\r
 -                    }\r
 -                    \r
 -                    int status2 = wc.executeMethod(find);\r
 -\r
 -                    Log.d("sharer", "propstatus "+status2);\r
 -                    \r
 -                    GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");\r
 -                    get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));\r
 -                    \r
 -                    status2 = wc.executeMethod(get);\r
 -\r
 -                    Log.d("sharer", "getstatus "+status2);\r
 -                    Log.d("sharer", "" + get.getResponseBodyAsString());\r
 -                    \r
 -                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {\r
 -                        Log.d("sharer", a.getName() + ":"+a.getValue());\r
 -                    }\r
 -\r
 -                    status = wc.executeMethod(post);\r
 -                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {\r
 -                        Log.d("sharer-h", a.getName() + ":"+a.getValue());\r
 -                    }\r
 -                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {\r
 -                        Log.d("sharer", a.getName() + ":"+a.getValue());\r
 -                    }\r
 -                    String resp = post.getResponseBodyAsString();\r
 -                    Log.d("share", ""+post.getURI().toString());\r
 -                    Log.d("share", "returned status " + status);\r
 -                    Log.d("share", " " +resp);\r
 -                    \r
 -                    if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {\r
 -                        return;\r
 -                     }\r
 -\r
 -                    JSONObject jsonObject = new JSONObject (resp);\r
 -                    String jsonStatus = jsonObject.getString("status");\r
 -                    if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");\r
 -                    \r
 -                    String token = jsonObject.getString("data");\r
 -                    String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token; \r
 -                    Log.d("Actions:shareFile ok", "url: " + uri);   \r
 -                    \r
 -                } catch (Exception e) {\r
 -                    e.printStackTrace();\r
 -                }\r
 -                \r
 -            } else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {\r
 -                \r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    public void onDismiss(EditNameDialog dialog) {\r
 -        if (dialog.getResult()) {\r
 -            String newFilename = dialog.getNewFilename();\r
 -            Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);\r
 -            mLastRemoteOperation = new RenameFileOperation( mFile, \r
 -                                                            mAccount, \r
 -                                                            newFilename, \r
 -                                                            new FileDataStorageManager(mAccount, getActivity().getContentResolver()));\r
 -            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
 -            mLastRemoteOperation.execute(wc, this, mHandler);\r
 -            boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -            getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * {@inheritDoc}\r
 -     */\r
 -    @Override\r
 -    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {\r
 -        if (operation.equals(mLastRemoteOperation)) {\r
 -            if (operation instanceof RemoveFileOperation) {\r
 -                onRemoveFileOperationFinish((RemoveFileOperation)operation, result);\r
 -                \r
 -            } else if (operation instanceof RenameFileOperation) {\r
 -                onRenameFileOperationFinish((RenameFileOperation)operation, result);\r
 -                \r
 -            } else if (operation instanceof SynchronizeFileOperation) {\r
 -                onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {\r
 -        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -        \r
 -        if (result.isSuccess()) {\r
 -            Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);\r
 -            msg.show();\r
 -            if (inDisplayActivity) {\r
 -                // double pane\r
 -                FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();\r
 -                transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment\r
 -                transaction.commit();\r
 -                mContainerActivity.onFileStateChanged();\r
 -            } else {\r
 -                getActivity().finish();\r
 -            }\r
 -                \r
 -        } else {\r
 -            Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); \r
 -            msg.show();\r
 -            if (result.isSslRecoverableException()) {\r
 -                // TODO show the SSL warning dialog\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) {\r
 -        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -        \r
 -        if (result.isSuccess()) {\r
 -            updateFileDetails(((RenameFileOperation)operation).getFile(), mAccount);\r
 -            mContainerActivity.onFileStateChanged();\r
 -            \r
 -        } else {\r
 -            if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) {\r
 -                Toast msg = Toast.makeText(getActivity(), R.string.rename_local_fail_msg, Toast.LENGTH_LONG); \r
 -                msg.show();\r
 -                // TODO throw again the new rename dialog\r
 -            } else {\r
 -                Toast msg = Toast.makeText(getActivity(), R.string.rename_server_fail_msg, Toast.LENGTH_LONG); \r
 -                msg.show();\r
 -                if (result.isSslRecoverableException()) {\r
 -                    // TODO show the SSL warning dialog\r
 -                }\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {\r
 -        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
 -        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
 -\r
 -        if (!result.isSuccess()) {\r
 -            if (result.getCode() == ResultCode.SYNC_CONFLICT) {\r
 -                Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);\r
 -                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, mFile);\r
 -                i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);\r
 -                startActivity(i);\r
 -                \r
 -            } else {\r
 -                Toast msg = Toast.makeText(getActivity(), R.string.sync_file_fail_msg, Toast.LENGTH_LONG); \r
 -                msg.show();\r
 -            }\r
 -            \r
 -            if (mFile.isDown()) {\r
 -                setButtonsForDown();\r
 -                \r
 -            } else {\r
 -                setButtonsForRemote();\r
 -            }\r
 -            \r
 -        } else {\r
 -            if (operation.transferWasRequested()) {\r
 -                setButtonsForTransferring();\r
 -                mContainerActivity.onFileStateChanged();    // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so \r
 -                                                            // checking the service to see if the file is downloading results in FALSE\r
 -            } else {\r
 -                Toast msg = Toast.makeText(getActivity(), R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); \r
 -                msg.show();\r
 -                if (mFile.isDown()) {\r
 -                    setButtonsForDown();\r
 -                    \r
 -                } else {\r
 -                    setButtonsForRemote();\r
 -                }\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    public void listenForTransferProgress() {\r
 -        if (mProgressListener != null) {\r
 -            if (mContainerActivity.getFileDownloaderBinder() != null) {\r
 -                mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
 -            }\r
 -            if (mContainerActivity.getFileUploaderBinder() != null) {\r
 -                mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
 -            }\r
 -        }\r
 -    }\r
 -    \r
 -    \r
 -    public void leaveTransferProgress() {\r
 -        if (mProgressListener != null) {\r
 -            if (mContainerActivity.getFileDownloaderBinder() != null) {\r
 -                mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
 -            }\r
 -            if (mContainerActivity.getFileUploaderBinder() != null) {\r
 -                mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);\r
 -            }\r
 -        }\r
 -    }\r
 -\r
 -\r
 -    \r
 -    /**\r
 -     * Helper class responsible for updating the progress bar shown for file uploading or downloading  \r
 -     * \r
 -     * @author David A. Velasco\r
 -     */\r
 -    private class ProgressListener implements OnDatatransferProgressListener {\r
 -        int mLastPercent = 0;\r
 -        WeakReference<ProgressBar> mProgressBar = null;\r
 -        \r
 -        ProgressListener(ProgressBar progressBar) {\r
 -            mProgressBar = new WeakReference<ProgressBar>(progressBar);\r
 -        }\r
 -        \r
 -        @Override\r
 -        public void onTransferProgress(long progressRate) {\r
 -            // old method, nothing here\r
 -        };\r
 -\r
 -        @Override\r
 -        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {\r
 -            int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));\r
 -            if (percent != mLastPercent) {\r
 -                ProgressBar pb = mProgressBar.get();\r
 -                if (pb != null) {\r
 -                    pb.setProgress(percent);\r
 -                    pb.postInvalidate();\r
 -                }\r
 -            }\r
 -            mLastPercent = percent;\r
 -        }\r
 -\r
 -    };\r
 -    \r
 -\r
 -\r
 -}\r
 +/* ownCloud Android client application
 + *   Copyright (C) 2011  Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License as published by
 + *   the Free Software Foundation, either version 2 of the License, or
 + *   (at your option) any later version.
 + *
 + *   This program is distributed in the hope that it will be useful,
 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *   GNU General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +package com.owncloud.android.ui.fragment;
 +
 +import java.io.File;
++import java.lang.ref.WeakReference;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import org.apache.commons.httpclient.methods.GetMethod;
 +import org.apache.commons.httpclient.methods.PostMethod;
 +import org.apache.commons.httpclient.methods.StringRequestEntity;
 +import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
 +import org.apache.http.HttpStatus;
 +import org.apache.http.NameValuePair;
 +import org.apache.http.client.utils.URLEncodedUtils;
 +import org.apache.http.message.BasicNameValuePair;
 +import org.apache.http.protocol.HTTP;
 +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 +import org.json.JSONObject;
 +
 +import android.accounts.Account;
 +import android.accounts.AccountManager;
- import android.annotation.SuppressLint;
++//import android.annotation.SuppressLint;
 +import android.app.Activity;
 +import android.content.ActivityNotFoundException;
 +import android.content.BroadcastReceiver;
 +import android.content.Context;
 +import android.content.Intent;
 +import android.content.IntentFilter;
++import android.net.Uri;
++import android.os.Bundle;
++import android.os.Handler;
++import android.support.v4.app.FragmentTransaction;
++import android.util.Log;
++import android.view.LayoutInflater;
++import android.view.View;
++import android.view.View.OnClickListener;
++import android.view.ViewGroup;
++import android.webkit.MimeTypeMap;
++import android.widget.Button;
++import android.widget.CheckBox;
++import android.widget.ImageView;
++import android.widget.ProgressBar;
++import android.widget.TextView;
++import android.widget.Toast;
++
 +import android.graphics.Bitmap;
 +import android.graphics.BitmapFactory;
 +import android.graphics.BitmapFactory.Options;
 +import android.graphics.Point;
 +import android.net.Uri;
 +import android.os.AsyncTask;
 +import android.os.Bundle;
 +import android.os.Handler;
 +import android.support.v4.app.DialogFragment;
 +import android.support.v4.app.FragmentTransaction;
 +import android.util.Log;
 +import android.view.Display;
 +import android.view.LayoutInflater;
 +import android.view.View;
 +import android.view.View.OnClickListener;
 +import android.view.ViewGroup;
 +import android.webkit.MimeTypeMap;
 +import android.widget.Button;
 +import android.widget.CheckBox;
 +import android.widget.ImageView;
 +import android.widget.TextView;
 +import android.widget.Toast;
 +
++
 +import com.actionbarsherlock.app.SherlockFragment;
 +import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.DisplayUtils;
 +import com.owncloud.android.Log_OC;
 +import com.owncloud.android.authenticator.AccountAuthenticator;
 +import com.owncloud.android.datamodel.FileDataStorageManager;
 +import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.files.services.FileDownloader;
 +import com.owncloud.android.files.services.FileObserverService;
 +import com.owncloud.android.files.services.FileUploader;
 +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 +import com.owncloud.android.network.OwnCloudClientUtils;
 +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.ui.activity.ConflictsResolveActivity;
 +import com.owncloud.android.ui.activity.FileDetailActivity;
 +import com.owncloud.android.ui.activity.FileDisplayActivity;
- import com.owncloud.android.ui.activity.TransferServiceGetter;
 +import com.owncloud.android.ui.dialog.EditNameDialog;
 +import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
 +import com.owncloud.android.utils.OwnCloudVersion;
 +
 +import com.owncloud.android.R;
++
++import eu.alefzero.webdav.OnDatatransferProgressListener;
 +import eu.alefzero.webdav.WebdavClient;
 +import eu.alefzero.webdav.WebdavUtils;
 +
++
 +/**
 + * This Fragment is used to display the details about a file.
 + * 
 + * @author Bartek Przybylski
-  * 
++ * @author David A. Velasco
 + */
 +public class FileDetailFragment extends SherlockFragment implements
-         OnClickListener, ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener {
++        OnClickListener, 
++        ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener,
++        FileFragment {
 +
 +    public static final String EXTRA_FILE = "FILE";
 +    public static final String EXTRA_ACCOUNT = "ACCOUNT";
 +
-     private FileDetailFragment.ContainerActivity mContainerActivity;
++    private FileFragment.ContainerActivity mContainerActivity;
 +    
 +    private int mLayout;
 +    private View mView;
 +    private OCFile mFile;
 +    private Account mAccount;
 +    private FileDataStorageManager mStorageManager;
-     private ImageView mPreview;
 +    
-     private DownloadFinishReceiver mDownloadFinishReceiver;
 +    private UploadFinishReceiver mUploadFinishReceiver;
++    public ProgressListener mProgressListener;
 +    
 +    private Handler mHandler;
 +    private RemoteOperation mLastRemoteOperation;
-     private DialogFragment mCurrentDialog;
++    
 +    private static final String TAG = FileDetailFragment.class.getSimpleName();
 +    public static final String FTAG = "FileDetails"; 
 +    public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
 +    
++
 +    /**
 +     * Creates an empty details fragment.
 +     * 
 +     * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically. 
 +     */
 +    public FileDetailFragment() {
 +        mFile = null;
 +        mAccount = null;
 +        mStorageManager = null;
 +        mLayout = R.layout.file_details_empty;
++        mProgressListener = null;
 +    }
 +    
 +    
 +    /**
 +     * Creates a details fragment.
 +     * 
 +     * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).
 +     * 
 +     * @param fileToDetail      An {@link OCFile} to show in the fragment
 +     * @param ocAccount         An ownCloud account; needed to start downloads
 +     */
 +    public FileDetailFragment(OCFile fileToDetail, Account ocAccount) {
 +        mFile = fileToDetail;
 +        mAccount = ocAccount;
 +        mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment 
 +        mLayout = R.layout.file_details_empty;
++        mProgressListener = null;
 +    }
 +    
 +    
 +    @Override
 +    public void onCreate(Bundle savedInstanceState) {
 +        super.onCreate(savedInstanceState);
 +        mHandler = new Handler();
 +    }
 +    
 +
 +    @Override
 +    public View onCreateView(LayoutInflater inflater, ViewGroup container,
 +            Bundle savedInstanceState) {
 +        super.onCreateView(inflater, container, savedInstanceState);
 +        
 +        if (savedInstanceState != null) {
 +            mFile = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);
 +            mAccount = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_ACCOUNT);
 +        }
 +        
 +        if(mFile != null && mAccount != null) {
 +            mLayout = R.layout.file_details_fragment;
 +        }
 +        
 +        View view = null;
 +        view = inflater.inflate(mLayout, container, false);
 +        mView = view;
 +        
 +        if (mLayout == R.layout.file_details_fragment) {
 +            mView.findViewById(R.id.fdKeepInSync).setOnClickListener(this);
 +            mView.findViewById(R.id.fdRenameBtn).setOnClickListener(this);
 +            mView.findViewById(R.id.fdDownloadBtn).setOnClickListener(this);
 +            mView.findViewById(R.id.fdOpenBtn).setOnClickListener(this);
 +            mView.findViewById(R.id.fdRemoveBtn).setOnClickListener(this);
 +            //mView.findViewById(R.id.fdShareBtn).setOnClickListener(this);
-             mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
++            ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
++            mProgressListener = new ProgressListener(progressBar);
 +        }
 +        
-         updateFileDetails(false);
++        updateFileDetails(false, false);
 +        return view;
 +    }
 +    
 +
 +    /**
 +     * {@inheritDoc}
 +     */
 +    @Override
 +    public void onAttach(Activity activity) {
 +        super.onAttach(activity);
 +        try {
 +            mContainerActivity = (ContainerActivity) activity;
++            
 +        } catch (ClassCastException e) {
 +            throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName());
 +        }
 +    }
 +    
 +    
 +    /**
 +     * {@inheritDoc}
 +     */
 +    @Override
 +    public void onActivityCreated(Bundle savedInstanceState) {
 +        super.onActivityCreated(savedInstanceState);
 +        if (mAccount != null) {
-             mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
++            mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
 +        }
 +    }
 +        
 +
 +    @Override
 +    public void onSaveInstanceState(Bundle outState) {
-         Log_OC.i(getClass().toString(), "onSaveInstanceState() start");
 +        super.onSaveInstanceState(outState);
 +        outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);
 +        outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
-         Log_OC.i(getClass().toString(), "onSaveInstanceState() end");
 +    }
 +
++    @Override
++    public void onStart() {
++        super.onStart();
++        listenForTransferProgress();
++    }
 +    
 +    @Override
 +    public void onResume() {
 +        super.onResume();
-         
-         mDownloadFinishReceiver = new DownloadFinishReceiver();
-         IntentFilter filter = new IntentFilter(
-                 FileDownloader.DOWNLOAD_FINISH_MESSAGE);
-         getActivity().registerReceiver(mDownloadFinishReceiver, filter);
-         
 +        mUploadFinishReceiver = new UploadFinishReceiver();
-         filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
++        IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
 +        getActivity().registerReceiver(mUploadFinishReceiver, filter);
-         
-         mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
++
 +    }
 +
++
 +    @Override
 +    public void onPause() {
 +        super.onPause();
-         
-         getActivity().unregisterReceiver(mDownloadFinishReceiver);
-         mDownloadFinishReceiver = null;
-         
-         getActivity().unregisterReceiver(mUploadFinishReceiver);
-         mUploadFinishReceiver = null;
-         
-         if (mPreview != null) {
-             mPreview = null;
++        if (mUploadFinishReceiver != null) {
++            getActivity().unregisterReceiver(mUploadFinishReceiver);
++            mUploadFinishReceiver = null;
 +        }
 +    }
 +
++    
++    @Override
++    public void onStop() {
++        super.onStop();
++        leaveTransferProgress();
++    }
++
++    
 +    @Override
 +    public View getView() {
 +        return super.getView() == null ? mView : super.getView();
 +    }
 +
-     
-     
 +    @Override
 +    public void onClick(View v) {
 +        switch (v.getId()) {
 +            case R.id.fdDownloadBtn: {
 +                FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
 +                FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
 +                if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
 +                    downloaderBinder.cancel(mAccount, mFile);
 +                    if (mFile.isDown()) {
 +                        setButtonsForDown();
 +                    } else {
 +                        setButtonsForRemote();
 +                    }
 +
 +                } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
 +                    uploaderBinder.cancel(mAccount, mFile);
 +                    if (!mFile.fileExists()) {
 +                        // TODO make something better
 +                        if (getActivity() instanceof FileDisplayActivity) {
 +                            // double pane
 +                            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
 +                            transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FTAG); // empty FileDetailFragment
 +                            transaction.commit();
 +                            mContainerActivity.onFileStateChanged();
 +                        } else {
 +                            getActivity().finish();
 +                        }
 +                        
 +                    } else if (mFile.isDown()) {
 +                        setButtonsForDown();
 +                    } else {
 +                        setButtonsForRemote();
 +                    }
 +                    
 +                } else {
 +                    mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
 +                    WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
 +                    mLastRemoteOperation.execute(wc, this, mHandler);
 +                
 +                    // update ui 
 +                    boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +                    getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
-                     setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference
 +                    
 +                }
 +                break;
 +            }
 +            case R.id.fdKeepInSync: {
 +                CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
 +                mFile.setKeepInSync(cb.isChecked());
 +                mStorageManager.saveFile(mFile);
 +                
 +                /// register the OCFile instance in the observer service to monitor local updates;
 +                /// if necessary, the file is download 
 +                Intent intent = new Intent(getActivity().getApplicationContext(),
 +                                           FileObserverService.class);
 +                intent.putExtra(FileObserverService.KEY_FILE_CMD,
 +                           (cb.isChecked()?
 +                                   FileObserverService.CMD_ADD_OBSERVED_FILE:
 +                                   FileObserverService.CMD_DEL_OBSERVED_FILE));
 +                intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);
 +                intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
-                 Log_OC.e(TAG, "starting observer service");
 +                getActivity().startService(intent);
 +                
 +                if (mFile.keepInSync()) {
 +                    onClick(getView().findViewById(R.id.fdDownloadBtn));    // force an immediate synchronization
 +                }
 +                break;
 +            }
 +            case R.id.fdRenameBtn: {
 +                EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mFile.getFileName(), this);
 +                dialog.show(getFragmentManager(), "nameeditdialog");
 +                break;
 +            }   
 +            case R.id.fdRemoveBtn: {
 +                ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
 +                        R.string.confirmation_remove_alert,
 +                        new String[]{mFile.getFileName()},
 +                        mFile.isDown() ? R.string.confirmation_remove_remote_and_local : R.string.confirmation_remove_remote,
 +                        mFile.isDown() ? R.string.confirmation_remove_local : -1,
 +                        R.string.common_cancel);
 +                confDialog.setOnConfirmationListener(this);
-                 mCurrentDialog = confDialog;
-                 mCurrentDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
++                confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
 +                break;
 +            }
 +            case R.id.fdOpenBtn: {
-                 String storagePath = mFile.getStoragePath();
-                 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
-                 try {
-                     Intent i = new Intent(Intent.ACTION_VIEW);
-                     i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
-                     i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                     startActivity(i);
-                     
-                 } catch (Throwable t) {
-                     Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
-                     boolean toastIt = true; 
-                     String mimeType = "";
-                     try {
-                         Intent i = new Intent(Intent.ACTION_VIEW);
-                         mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
-                         if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
-                             if (mimeType != null) {
-                                 i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
-                             } else {
-                                 // desperate try
-                                 i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
-                             }
-                             i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                             startActivity(i);
-                             toastIt = false;
-                         }
-                         
-                     } catch (IndexOutOfBoundsException e) {
-                         Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
-                         
-                     } catch (ActivityNotFoundException e) {
-                         Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
-                         
-                     } catch (Throwable th) {
-                         Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
-                         
-                     } finally {
-                         if (toastIt) {
-                             Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
-                         }
-                     }
-                     
-                 }
++                openFile();
 +                break;
 +            }
 +            default:
 +                Log_OC.e(TAG, "Incorrect view clicked!");
 +        }
 +        
 +        /* else if (v.getId() == R.id.fdShareBtn) {
 +            Thread t = new Thread(new ShareRunnable(mFile.getRemotePath()));
 +            t.start();
 +        }*/
 +    }
 +    
 +    
++    /**
++     * Opens mFile.
++     */
++    private void openFile() {
++        
++        String storagePath = mFile.getStoragePath();
++        String encodedStoragePath = WebdavUtils.encodePath(storagePath);
++        try {
++            Intent i = new Intent(Intent.ACTION_VIEW);
++            i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
++            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
++            startActivity(i);
++            
++        } catch (Throwable t) {
++            Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
++            boolean toastIt = true; 
++            String mimeType = "";
++            try {
++                Intent i = new Intent(Intent.ACTION_VIEW);
++                mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
++                if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
++                    if (mimeType != null) {
++                        i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
++                    } else {
++                        // desperate try
++                        i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
++                    }
++                    i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
++                    startActivity(i);
++                    toastIt = false;
++                }
++                
++            } catch (IndexOutOfBoundsException e) {
++                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
++                
++            } catch (ActivityNotFoundException e) {
++                Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
++                
++            } catch (Throwable th) {
++                Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
++                
++            } finally {
++                if (toastIt) {
++                    Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
++                }
++            }
++            
++        }
++    }
++
++
 +    @Override
 +    public void onConfirmation(String callerTag) {
 +        if (callerTag.equals(FTAG_CONFIRMATION)) {
 +            if (mStorageManager.getFileById(mFile.getFileId()) != null) {
 +                mLastRemoteOperation = new RemoveFileOperation( mFile, 
 +                                                                true, 
 +                                                                mStorageManager);
 +                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
 +                mLastRemoteOperation.execute(wc, this, mHandler);
 +                
 +                boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +                getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
 +            }
 +        }
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
 +    }
 +    
 +    @Override
 +    public void onNeutral(String callerTag) {
 +        File f = null;
 +        if (mFile.isDown() && (f = new File(mFile.getStoragePath())).exists()) {
 +            f.delete();
 +            mFile.setStoragePath(null);
 +            mStorageManager.saveFile(mFile);
 +            updateFileDetails(mFile, mAccount);
 +        }
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
 +    }
 +    
 +    @Override
 +    public void onCancel(String callerTag) {
-         Log_OC.d(TAG, "REMOVAL CANCELED");
-         mCurrentDialog.dismiss();
-         mCurrentDialog = null;
++        Log.d(TAG, "REMOVAL CANCELED");
 +    }
 +    
 +    
 +    /**
 +     * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
 +     * 
 +     * @return  True when the fragment was created with the empty layout.
 +     */
 +    public boolean isEmpty() {
 +        return (mLayout == R.layout.file_details_empty || mFile == null || mAccount == null);
 +    }
 +
 +    
 +    /**
-      * Can be used to get the file that is currently being displayed.
-      * @return The file on the screen.
++     * {@inheritDoc}
 +     */
-     public OCFile getDisplayedFile(){
++    public OCFile getFile(){
 +        return mFile;
 +    }
 +    
 +    /**
 +     * Use this method to signal this Activity that it shall update its view.
 +     * 
 +     * @param file : An {@link OCFile}
 +     */
 +    public void updateFileDetails(OCFile file, Account ocAccount) {
 +        mFile = file;
 +        if (ocAccount != null && ( 
 +                mStorageManager == null || 
 +                (mAccount != null && !mAccount.equals(ocAccount))
 +           )) {
 +            mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
 +        }
 +        mAccount = ocAccount;
-         updateFileDetails(false);
++        updateFileDetails(false, false);
 +    }
-     
 +
 +    /**
 +     * Updates the view with all relevant details about that file.
 +     *
 +     * TODO Remove parameter when the transferring state of files is kept in database. 
 +     * 
++     * TODO REFACTORING! this method called 5 times before every time the fragment is shown! 
++     * 
 +     * @param transferring      Flag signaling if the file should be considered as downloading or uploading, 
 +     *                          although {@link FileDownloaderBinder#isDownloading(Account, OCFile)}  and 
 +     *                          {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
-      * 
++     *                          
++     * @param refresh           If 'true', try to refresh the hold file from the database
 +     */
-     public void updateFileDetails(boolean transferring) {
++    public void updateFileDetails(boolean transferring, boolean refresh) {
 +
-         if (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment) {
++        if (readyToShow()) {
++            
++            if (refresh && mStorageManager != null) {
++                mFile = mStorageManager.getFileByPath(mFile.getRemotePath());
++            }
 +            
 +            // set file details
 +            setFilename(mFile.getFileName());
 +            setFiletype(mFile.getMimetype());
 +            setFilesize(mFile.getFileLength());
 +            if(ocVersionSupportsTimeCreated()){
 +                setTimeCreated(mFile.getCreationTimestamp());
 +            }
 +           
 +            setTimeModified(mFile.getModificationTimestamp());
 +            
 +            CheckBox cb = (CheckBox)getView().findViewById(R.id.fdKeepInSync);
 +            cb.setChecked(mFile.keepInSync());
 +
 +            // configure UI for depending upon local state of the file
 +            //if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {
 +            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
 +            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
 +            if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))) {
 +                setButtonsForTransferring();
 +                
 +            } else if (mFile.isDown()) {
-                 // Update preview
-                 if (mFile.getMimetype().startsWith("image/")) {
-                     BitmapLoader bl = new BitmapLoader();
-                     bl.execute(new String[]{mFile.getStoragePath()});
-                 }
 +                
 +                setButtonsForDown();
 +                
 +            } else {
 +                // TODO load default preview image; when the local file is removed, the preview remains there
 +                setButtonsForRemote();
 +            }
 +        }
 +        getView().invalidate();
 +    }
 +    
 +    
 +    /**
++     * Checks if the fragment is ready to show details of a OCFile
++     *  
++     * @return  'True' when the fragment is ready to show details of a file
++     */
++    private boolean readyToShow() {
++        return (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment);        
++    }
++
++
++    /**
 +     * Updates the filename in view
 +     * @param filename to set
 +     */
 +    private void setFilename(String filename) {
 +        TextView tv = (TextView) getView().findViewById(R.id.fdFilename);
 +        if (tv != null)
 +            tv.setText(filename);
 +    }
 +
 +    /**
 +     * Updates the MIME type in view
 +     * @param mimetype to set
 +     */
 +    private void setFiletype(String mimetype) {
 +        TextView tv = (TextView) getView().findViewById(R.id.fdType);
 +        if (tv != null) {
 +            String printableMimetype = DisplayUtils.convertMIMEtoPrettyPrint(mimetype);;        
 +            tv.setText(printableMimetype);
 +        }
 +        ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);
 +        if (iv != null) {
 +            iv.setImageResource(DisplayUtils.getResourceId(mimetype));
 +        }
 +    }
 +
 +    /**
 +     * Updates the file size in view
 +     * @param filesize in bytes to set
 +     */
 +    private void setFilesize(long filesize) {
 +        TextView tv = (TextView) getView().findViewById(R.id.fdSize);
 +        if (tv != null)
 +            tv.setText(DisplayUtils.bytesToHumanReadable(filesize));
 +    }
 +    
 +    /**
 +     * Updates the time that the file was created in view
 +     * @param milliseconds Unix time to set
 +     */
 +    private void setTimeCreated(long milliseconds){
 +        TextView tv = (TextView) getView().findViewById(R.id.fdCreated);
 +        TextView tvLabel = (TextView) getView().findViewById(R.id.fdCreatedLabel);
 +        if(tv != null){
 +            tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
 +            tv.setVisibility(View.VISIBLE);
 +            tvLabel.setVisibility(View.VISIBLE);
 +        }
 +    }
 +    
 +    /**
 +     * Updates the time that the file was last modified
 +     * @param milliseconds Unix time to set
 +     */
 +    private void setTimeModified(long milliseconds){
 +        TextView tv = (TextView) getView().findViewById(R.id.fdModified);
 +        if(tv != null){
 +            tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
 +        }
 +    }
 +    
 +    /**
 +     * Enables or disables buttons for a file being downloaded
 +     */
 +    private void setButtonsForTransferring() {
 +        if (!isEmpty()) {
 +            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
 +            downloadButton.setText(R.string.common_cancel);
 +            //downloadButton.setEnabled(false);
 +        
 +            // let's protect the user from himself ;)
 +            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);
 +            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);
 +            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);
 +            getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
++            
++            // show the progress bar for the transfer
++            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
++            progressBar.setVisibility(View.VISIBLE);
++            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
++            progressText.setVisibility(View.VISIBLE);
++            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
++            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
++            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
++                progressText.setText(R.string.downloader_download_in_progress_ticker);
++            } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
++                progressText.setText(R.string.uploader_upload_in_progress_ticker);
++            }
 +        }
 +    }
-     
++
 +    /**
 +     * Enables or disables buttons for a file locally available 
 +     */
 +    private void setButtonsForDown() {
 +        if (!isEmpty()) {
 +            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
 +            downloadButton.setText(R.string.filedetails_sync_file);
 +        
 +            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);
 +            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
 +            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
 +            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
++            
++            // hides the progress bar
++            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
++            progressBar.setVisibility(View.GONE);
++            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
++            progressText.setVisibility(View.GONE);
 +        }
 +    }
 +
 +    /**
 +     * Enables or disables buttons for a file not locally available 
 +     */
 +    private void setButtonsForRemote() {
 +        if (!isEmpty()) {
 +            Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
 +            downloadButton.setText(R.string.filedetails_download);
 +            
 +            ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);
 +            ((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
 +            ((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
 +            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
++            
++            // hides the progress bar
++            ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
++            progressBar.setVisibility(View.GONE);
++            TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
++            progressText.setVisibility(View.GONE);
 +        }
 +    }
 +    
 +
 +    /**
 +     * In ownCloud 3.X.X and 4.X.X there is a bug that SabreDAV does not return
 +     * the time that the file was created. There is a chance that this will
 +     * be fixed in future versions. Use this method to check if this version of
 +     * ownCloud has this fix.
 +     * @return True, if ownCloud the ownCloud version is supporting creation time
 +     */
 +    private boolean ocVersionSupportsTimeCreated(){
 +        /*if(mAccount != null){
 +            AccountManager accManager = (AccountManager) getActivity().getSystemService(Context.ACCOUNT_SERVICE);
 +            OwnCloudVersion ocVersion = new OwnCloudVersion(accManager
 +                    .getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION));
 +            if(ocVersion.compareTo(new OwnCloudVersion(0x030000)) < 0) {
 +                return true;
 +            }
 +        }*/
 +        return false;
 +    }
 +    
-     
-     /**
-      * Interface to implement by any Activity that includes some instance of FileDetailFragment
-      * 
-      * @author David A. Velasco
-      */
-     public interface ContainerActivity extends TransferServiceGetter {
-         /**
-          * Callback method invoked when the detail fragment wants to notice its container 
-          * activity about a relevant state the file shown by the fragment.
-          * 
-          * Added to notify to FileDisplayActivity about the need of refresh the files list. 
-          * 
-          * Currently called when:
-          *  - a download is started;
-          *  - a rename is completed;
-          *  - a deletion is completed;
-          *  - the 'inSync' flag is changed;
-          */
-         public void onFileStateChanged();
-         
-     }
-     
-     /**
-      * Once the file download has finished -> update view
-      * @author Bartek Przybylski
-      */
-     private class DownloadFinishReceiver extends BroadcastReceiver {
-         @Override
-         public void onReceive(Context context, Intent intent) {
-             String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
 +
-             if (!isEmpty() && accountName.equals(mAccount.name)) {
-                 boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
-                 String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
-                 if (mFile.getRemotePath().equals(downloadedRemotePath)) {
-                     if (downloadWasFine) {
-                         mFile = mStorageManager.getFileByPath(downloadedRemotePath);
-                     }
-                     updateFileDetails(false);    // it updates the buttons; must be called although !downloadWasFine
-                 }
-             }
-         }
-     }
-     
-     
 +    /**
 +     * Once the file upload has finished -> update view
 +     * 
 +     * Being notified about the finish of an upload is necessary for the next sequence:
 +     *   1. Upload a big file.
 +     *   2. Force a synchronization; if it finished before the upload, the file in transfer will be included in the local database and in the file list
 +     *      of its containing folder; the the server includes it in the PROPFIND requests although it's not fully upload. 
 +     *   3. Click the file in the list to see its details.
 +     *   4. Wait for the upload finishes; at this moment, the details view must be refreshed to enable the action buttons.
 +     */
 +    private class UploadFinishReceiver extends BroadcastReceiver {
 +        @Override
 +        public void onReceive(Context context, Intent intent) {
 +            String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
 +
 +            if (!isEmpty() && accountName.equals(mAccount.name)) {
 +                boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);
 +                String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);
 +                boolean renamedInUpload = mFile.getRemotePath().equals(intent.getStringExtra(FileUploader.EXTRA_OLD_REMOTE_PATH));
 +                if (mFile.getRemotePath().equals(uploadRemotePath) ||
 +                    renamedInUpload) {
 +                    if (uploadWasFine) {
 +                        mFile = mStorageManager.getFileByPath(uploadRemotePath);
 +                    }
 +                    if (renamedInUpload) {
 +                        String newName = (new File(uploadRemotePath)).getName();
 +                        Toast msg = Toast.makeText(getActivity().getApplicationContext(), String.format(getString(R.string.filedetails_renamed_in_upload_msg), newName), Toast.LENGTH_LONG);
 +                        msg.show();
 +                    }
 +                    getSherlockActivity().removeStickyBroadcast(intent);    // not the best place to do this; a small refactorization of BroadcastReceivers should be done
-                     updateFileDetails(false);    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
++                    updateFileDetails(false, false);    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
 +                }
 +            }
 +        }
 +    }
 +    
 +
 +    // this is a temporary class for sharing purposes, it need to be replaced in transfer service
 +    @SuppressWarnings("unused")
 +    private class ShareRunnable implements Runnable {
 +        private String mPath;
 +
 +        public ShareRunnable(String path) {
 +            mPath = path;
 +        }
 +        
 +        public void run() {
 +            AccountManager am = AccountManager.get(getActivity());
 +            Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
 +            OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
 +            String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
 +
-             Log_OC.d("share", "sharing for version " + ocv.toString());
++            Log.d("share", "sharing for version " + ocv.toString());
 +
 +            if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
 +                String APPS_PATH = "/apps/files_sharing/";
 +                String SHARE_PATH = "ajax/share.php";
 +
 +                String SHARED_PATH = "/apps/files_sharing/get.php?token=";
 +                
 +                final String WEBDAV_SCRIPT = "webdav.php";
 +                final String WEBDAV_FILES_LOCATION = "/files/";
 +                
 +                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());
 +                HttpConnectionManagerParams params = new HttpConnectionManagerParams();
 +                params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);
 +
 +                //wc.getParams().setParameter("http.protocol.single-cookie-header", true);
 +                //wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
 +
 +                PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);
 +
 +                post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
 +                post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
 +                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
-                 Log_OC.d("share", mPath+"");
++                Log.d("share", mPath+"");
 +                formparams.add(new BasicNameValuePair("sources",mPath));
 +                formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
 +                formparams.add(new BasicNameValuePair("permissions", "0"));
 +                post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));
 +
 +                int status;
 +                try {
 +                    PropFindMethod find = new PropFindMethod(url+"/");
 +                    find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
-                     Log_OC.d("sharer", ""+ url+"/");
++                    Log.d("sharer", ""+ url+"/");
 +                    
 +                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
-                         Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
++                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
 +                    }
 +                    
 +                    int status2 = wc.executeMethod(find);
 +
-                     Log_OC.d("sharer", "propstatus "+status2);
++                    Log.d("sharer", "propstatus "+status2);
 +                    
 +                    GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
 +                    get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
 +                    
 +                    status2 = wc.executeMethod(get);
 +
-                     Log_OC.d("sharer", "getstatus "+status2);
-                     Log_OC.d("sharer", "" + get.getResponseBodyAsString());
++                    Log.d("sharer", "getstatus "+status2);
++                    Log.d("sharer", "" + get.getResponseBodyAsString());
 +                    
 +                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
-                         Log_OC.d("sharer", a.getName() + ":"+a.getValue());
++                        Log.d("sharer", a.getName() + ":"+a.getValue());
 +                    }
 +
 +                    status = wc.executeMethod(post);
 +                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
-                         Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
++                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
 +                    }
 +                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
-                         Log_OC.d("sharer", a.getName() + ":"+a.getValue());
++                        Log.d("sharer", a.getName() + ":"+a.getValue());
 +                    }
 +                    String resp = post.getResponseBodyAsString();
-                     Log_OC.d("share", ""+post.getURI().toString());
-                     Log_OC.d("share", "returned status " + status);
-                     Log_OC.d("share", " " +resp);
++                    Log.d("share", ""+post.getURI().toString());
++                    Log.d("share", "returned status " + status);
++                    Log.d("share", " " +resp);
 +                    
 +                    if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
 +                        return;
 +                     }
 +
 +                    JSONObject jsonObject = new JSONObject (resp);
 +                    String jsonStatus = jsonObject.getString("status");
 +                    if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");
 +                    
 +                    String token = jsonObject.getString("data");
 +                    String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token; 
-                     Log_OC.d("Actions:shareFile ok", "url: " + uri);   
++                    Log.d("Actions:shareFile ok", "url: " + uri);   
 +                    
 +                } catch (Exception e) {
 +                    e.printStackTrace();
 +                }
 +                
 +            } else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {
 +                
 +            }
 +        }
 +    }
 +    
 +    public void onDismiss(EditNameDialog dialog) {
 +        if (dialog.getResult()) {
 +            String newFilename = dialog.getNewFilename();
-             Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
++            Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
 +            mLastRemoteOperation = new RenameFileOperation( mFile, 
 +                                                            mAccount, 
 +                                                            newFilename, 
 +                                                            new FileDataStorageManager(mAccount, getActivity().getContentResolver()));
 +            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
 +            mLastRemoteOperation.execute(wc, this, mHandler);
 +            boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +            getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
 +        }
 +    }
 +    
 +    
-     class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
-         @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20
-               @Override
-         protected Bitmap doInBackground(String... params) {
-             Bitmap result = null;
-             if (params.length != 1) return result;
-             String storagePath = params[0];
-             try {
-                 BitmapFactory.Options options = new Options();
-                 options.inScaled = true;
-                 options.inPurgeable = true;
-                 options.inJustDecodeBounds = true;
-                 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
-                     options.inPreferQualityOverSpeed = false;
-                 }
-                 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
-                     options.inMutable = false;
-                 }
-                 result = BitmapFactory.decodeFile(storagePath, options);
-                 options.inJustDecodeBounds = false;
-                 int width = options.outWidth;
-                 int height = options.outHeight;
-                 int scale = 1;
-                 if (width >= 2048 || height >= 2048) {
-                     scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));
-                     options.inSampleSize = scale;
-                 }
-                 Display display = getActivity().getWindowManager().getDefaultDisplay();
-                 Point size = new Point();
-                 int screenwidth;
-                 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
-                     display.getSize(size);
-                     screenwidth = size.x;
-                 } else {
-                     screenwidth = display.getWidth();
-                 }
-                 Log_OC.e("ASD", "W " + width + " SW " + screenwidth);
-                 if (width > screenwidth) {
-                     scale = (int) Math.ceil((float)width / screenwidth);
-                     options.inSampleSize = scale;
-                 }
-                 result = BitmapFactory.decodeFile(storagePath, options);
-                 Log_OC.e("ASD", "W " + options.outWidth + " SW " + options.outHeight);
-             } catch (OutOfMemoryError e) {
-                 result = null;
-                 Log_OC.e(TAG, "Out of memory occured for file with size " + storagePath);
-                 
-             } catch (NoSuchFieldError e) {
-                 result = null;
-                 Log_OC.e(TAG, "Error from access to unexisting field despite protection " + storagePath);
-                 
-             } catch (Throwable t) {
-                 result = null;
-                 Log_OC.e(TAG, "Unexpected error while creating image preview " + storagePath, t);
-             }
-             return result;
-         }
-         @Override
-         protected void onPostExecute(Bitmap result) {
-             if (result != null && mPreview != null) {
-                 mPreview.setImageBitmap(result);
-             }
-         }
-         
-     }
 +    /**
 +     * {@inheritDoc}
 +     */
 +    @Override
 +    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
 +        if (operation.equals(mLastRemoteOperation)) {
 +            if (operation instanceof RemoveFileOperation) {
 +                onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
 +                
 +            } else if (operation instanceof RenameFileOperation) {
 +                onRenameFileOperationFinish((RenameFileOperation)operation, result);
 +                
 +            } else if (operation instanceof SynchronizeFileOperation) {
 +                onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
 +            }
 +        }
 +    }
 +    
 +    
 +    private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
 +        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
 +        
 +        if (result.isSuccess()) {
 +            Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);
 +            msg.show();
 +            if (inDisplayActivity) {
 +                // double pane
 +                FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
 +                transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment
 +                transaction.commit();
 +                mContainerActivity.onFileStateChanged();
 +            } else {
 +                getActivity().finish();
 +            }
 +                
 +        } else {
 +            Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG); 
 +            msg.show();
 +            if (result.isSslRecoverableException()) {
 +                // TODO show the SSL warning dialog
 +            }
 +        }
 +    }
 +    
 +    private void onRenameFileOperationFinish(RenameFileOperation operation, RemoteOperationResult result) {
 +        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
 +        
 +        if (result.isSuccess()) {
 +            updateFileDetails(((RenameFileOperation)operation).getFile(), mAccount);
 +            mContainerActivity.onFileStateChanged();
 +            
 +        } else {
 +            if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) {
 +                Toast msg = Toast.makeText(getActivity(), R.string.rename_local_fail_msg, Toast.LENGTH_LONG); 
 +                msg.show();
 +                // TODO throw again the new rename dialog
 +            } else {
 +                Toast msg = Toast.makeText(getActivity(), R.string.rename_server_fail_msg, Toast.LENGTH_LONG); 
 +                msg.show();
 +                if (result.isSslRecoverableException()) {
 +                    // TODO show the SSL warning dialog
 +                }
 +            }
 +        }
 +    }
 +    
 +    private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {
 +        boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
 +        getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
 +
 +        if (!result.isSuccess()) {
 +            if (result.getCode() == ResultCode.SYNC_CONFLICT) {
 +                Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);
 +                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, mFile);
 +                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 (mFile.isDown()) {
 +                setButtonsForDown();
 +                
 +            } else {
 +                setButtonsForRemote();
 +            }
 +            
 +        } else {
 +            if (operation.transferWasRequested()) {
++                setButtonsForTransferring();
 +                mContainerActivity.onFileStateChanged();    // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so 
 +                                                            // checking the service to see if the file is downloading results in FALSE
 +            } else {
 +                Toast msg = Toast.makeText(getActivity(), R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); 
 +                msg.show();
 +                if (mFile.isDown()) {
 +                    setButtonsForDown();
 +                    
 +                } else {
 +                    setButtonsForRemote();
 +                }
 +            }
 +        }
 +    }
++    
++    
++    public void listenForTransferProgress() {
++        if (mProgressListener != null) {
++            if (mContainerActivity.getFileDownloaderBinder() != null) {
++                mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
++            }
++            if (mContainerActivity.getFileUploaderBinder() != null) {
++                mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
++            }
++        }
++    }
++    
++    
++    public void leaveTransferProgress() {
++        if (mProgressListener != null) {
++            if (mContainerActivity.getFileDownloaderBinder() != null) {
++                mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
++            }
++            if (mContainerActivity.getFileUploaderBinder() != null) {
++                mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
++            }
++        }
++    }
++
++
++    
++    /**
++     * Helper class responsible for updating the progress bar shown for file uploading or downloading  
++     * 
++     * @author David A. Velasco
++     */
++    private class ProgressListener implements OnDatatransferProgressListener {
++        int mLastPercent = 0;
++        WeakReference<ProgressBar> mProgressBar = null;
++        
++        ProgressListener(ProgressBar progressBar) {
++            mProgressBar = new WeakReference<ProgressBar>(progressBar);
++        }
++        
++        @Override
++        public void onTransferProgress(long progressRate) {
++            // old method, nothing here
++        };
++
++        @Override
++        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
++            int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
++            if (percent != mLastPercent) {
++                ProgressBar pb = mProgressBar.get();
++                if (pb != null) {
++                    pb.setProgress(percent);
++                    pb.postInvalidate();
++                }
++            }
++            mLastPercent = percent;
++        }
++
++    };
 +
- }
++}
@@@ -23,7 -23,6 +23,7 @@@ import java.util.ArrayList
  import java.util.List;
  
  import com.owncloud.android.AccountUtils;
 +import com.owncloud.android.Log_OC;
  import com.owncloud.android.R;
  import com.owncloud.android.datamodel.DataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
@@@ -82,8 -81,6 +82,6 @@@ public class OCFileListFragment extend
      private Handler mHandler;
      private OCFile mTargetFile;
      
-     private DialogFragment mCurrentDialog;
-     
      /**
       * {@inheritDoc}
       */
       */
      @Override
      public void onActivityCreated(Bundle savedInstanceState) {
 -        Log.i(TAG, "onActivityCreated() start");
 +        Log_OC.i(TAG, "onActivityCreated() start");
          
          super.onActivityCreated(savedInstanceState);
          mAdapter = new FileListListAdapter(mContainerActivity.getInitialDirectory(), mContainerActivity.getStorageManager(), getActivity(), mContainerActivity);
          setListAdapter(mAdapter);
          
          if (savedInstanceState != null) {
 -            Log.i(TAG, "savedInstanceState is not null");
 +            Log_OC.i(TAG, "savedInstanceState is not null");
              int position = savedInstanceState.getInt(SAVED_LIST_POSITION);
              setReferencePosition(position);
          }
          
          mHandler = new Handler();
          
 -        Log.i(TAG, "onActivityCreated() stop");
 +        Log_OC.i(TAG, "onActivityCreated() stop");
      }
      
      
  
      @Override
      public void onSaveInstanceState(Bundle savedInstanceState) {
 -        Log.i(TAG, "onSaveInstanceState() start");
 +        Log_OC.i(TAG, "onSaveInstanceState() start");
          
          savedInstanceState.putInt(SAVED_LIST_POSITION, getReferencePosition());
          
 -        Log.i(TAG, "onSaveInstanceState() stop");
 +        Log_OC.i(TAG, "onSaveInstanceState() stop");
      }
      
      
              }
              
          } else {
 -            Log.d(TAG, "Null object in ListAdapter!!");
 +            Log_OC.d(TAG, "Null object in ListAdapter!!");
          }
          
      }
      public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
          super.onCreateContextMenu(menu, v, menuInfo);
          MenuInflater inflater = getActivity().getMenuInflater();
-         inflater.inflate(R.menu.file_context_menu, menu);
+         inflater.inflate(R.menu.file_actions_menu, menu);
          AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
          OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
          List<Integer> toHide = new ArrayList<Integer>();    
          MenuItem item = null;
          if (targetFile.isDirectory()) {
              // contextual menu for folders
-             toHide.add(R.id.open_file_item);
-             toHide.add(R.id.download_file_item);
-             toHide.add(R.id.cancel_download_item);
-             toHide.add(R.id.cancel_upload_item);
+             toHide.add(R.id.action_open_file_with);
+             toHide.add(R.id.action_download_file);
+             toHide.add(R.id.action_cancel_download);
+             toHide.add(R.id.action_cancel_upload);
+             toHide.add(R.id.action_see_details);
              if (    mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ||
                      mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)           ) {
-                 toDisable.add(R.id.rename_file_item);
-                 toDisable.add(R.id.remove_file_item);
+                 toDisable.add(R.id.action_rename_file);
+                 toDisable.add(R.id.action_remove_file);
                  
              }
              
          } else {
              // contextual menu for regular files
              if (targetFile.isDown()) {
-                 toHide.add(R.id.cancel_download_item);
-                 toHide.add(R.id.cancel_upload_item);
-                 item = menu.findItem(R.id.download_file_item);
+                 toHide.add(R.id.action_cancel_download);
+                 toHide.add(R.id.action_cancel_upload);
+                 item = menu.findItem(R.id.action_download_file);
                  if (item != null) {
                      item.setTitle(R.string.filedetails_sync_file);
                  }
              } else {
-                 toHide.add(R.id.open_file_item);
+                 toHide.add(R.id.action_open_file_with);
              }
              if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
-                 toHide.add(R.id.download_file_item);
-                 toHide.add(R.id.cancel_upload_item);
-                 toDisable.add(R.id.open_file_item);
-                 toDisable.add(R.id.rename_file_item);
-                 toDisable.add(R.id.remove_file_item);
+                 toHide.add(R.id.action_download_file);
+                 toHide.add(R.id.action_cancel_upload);
+                 toDisable.add(R.id.action_open_file_with);
+                 toDisable.add(R.id.action_rename_file);
+                 toDisable.add(R.id.action_remove_file);
                      
              } else if ( mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
-                 toHide.add(R.id.download_file_item);
-                 toHide.add(R.id.cancel_download_item);
-                 toDisable.add(R.id.open_file_item);
-                 toDisable.add(R.id.rename_file_item);
-                 toDisable.add(R.id.remove_file_item);
+                 toHide.add(R.id.action_download_file);
+                 toHide.add(R.id.action_cancel_download);
+                 toDisable.add(R.id.action_open_file_with);
+                 toDisable.add(R.id.action_rename_file);
+                 toDisable.add(R.id.action_remove_file);
                      
              } else {
-                 toHide.add(R.id.cancel_download_item);
-                 toHide.add(R.id.cancel_upload_item);
+                 toHide.add(R.id.action_cancel_download);
+                 toHide.add(R.id.action_cancel_upload);
              }
          }
  
          AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();        
          mTargetFile = (OCFile) mAdapter.getItem(info.position);
          switch (item.getItemId()) {
-             case R.id.rename_file_item: {
+             case R.id.action_rename_file: {
                  EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mTargetFile.getFileName(), this);
                  dialog.show(getFragmentManager(), EditNameDialog.TAG);
                  return true;
              }
-             case R.id.remove_file_item: {
+             case R.id.action_remove_file: {
                  int messageStringId = R.string.confirmation_remove_alert;
                  int posBtnStringId = R.string.confirmation_remove_remote;
                  int neuBtnStringId = -1;
                          neuBtnStringId,
                          R.string.common_cancel);
                  confDialog.setOnConfirmationListener(this);
-                 mCurrentDialog = confDialog;
-                 mCurrentDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION);
+                 confDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION);
                  return true;
              }
-             case R.id.open_file_item: {
+             case R.id.action_open_file_with: {
                  String storagePath = mTargetFile.getStoragePath();
                  String encodedStoragePath = WebdavUtils.encodePath(storagePath);
                  try {
                      startActivity(i);
                      
                  } catch (Throwable t) {
 -                    Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mTargetFile.getMimetype());
 +                    Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mTargetFile.getMimetype());
                      boolean toastIt = true; 
                      String mimeType = "";
                      try {
                          }
                          
                      } catch (IndexOutOfBoundsException e) {
 -                        Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
 +                        Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
                          
                      } catch (ActivityNotFoundException e) {
 -                        Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
 +                        Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
                          
                      } catch (Throwable th) {
 -                        Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
 +                        Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
                          
                      } finally {
                          if (toastIt) {
                  }
                  return true;
              }
-             case R.id.download_file_item: {
+             case R.id.action_download_file: {
                  Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
                  RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
                  WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getSherlockActivity().getApplicationContext());
                  getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
                  return true;
              }
-             case R.id.cancel_download_item: {
+             case R.id.action_cancel_download: {
                  FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
                  Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
                  if (downloaderBinder != null && downloaderBinder.isDownloading(account, mTargetFile)) {
                  }
                  return true;
              }
-             case R.id.cancel_upload_item: {
+             case R.id.action_cancel_upload: {
                  FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
                  Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
                  if (uploaderBinder != null && uploaderBinder.isUploading(account, mTargetFile)) {
                  }
                  return true;
              }
+             case R.id.action_see_details: {
+                 ((FileFragment.ContainerActivity)getActivity()).showFragmentWithDetails(mTargetFile);
+                 return true;
+             }
              default:
                  return super.onContextItemSelected(item); 
          }
          
              // If that's not a directory -> List its parent
              if(!directory.isDirectory()){
 -                Log.w(TAG, "You see, that is not a directory -> " + directory.toString());
 +                Log_OC.w(TAG, "You see, that is not a directory -> " + directory.toString());
                  directory = storageManager.getFileById(directory.getParentId());
              }
  
      public void onDismiss(EditNameDialog dialog) {
          if (dialog.getResult()) {
              String newFilename = dialog.getNewFilename();
 -            Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
 +            Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
              RemoteOperation operation = new RenameFileOperation(mTargetFile, 
                                                                  AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
                                                                  newFilename, 
                  
                  getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
              }
-             if (mCurrentDialog != null) {
-                 mCurrentDialog.dismiss();
-                 mCurrentDialog = null;
-             }
          }
      }
      
              mTargetFile.setStoragePath(null);
              mContainerActivity.getStorageManager().saveFile(mTargetFile);
          }
-         if (mCurrentDialog != null) {
-             mCurrentDialog.dismiss();
-             mCurrentDialog = null;
-         }
          listDirectory();
          mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
      }
      
      @Override
      public void onCancel(String callerTag) {
 -        Log.d(TAG, "REMOVAL CANCELED");
 +        Log_OC.d(TAG, "REMOVAL CANCELED");
-         if (mCurrentDialog != null) {
-             mCurrentDialog.dismiss();
-             mCurrentDialog = null;
-         }
      }
  
  
@@@ -30,19 -30,19 +30,18 @@@ import java.util.Set
  
  import org.apache.commons.httpclient.methods.RequestEntity;
  
 +import com.owncloud.android.Log_OC;
+ import com.owncloud.android.network.ProgressiveDataTransferer;
  
  import eu.alefzero.webdav.OnDatatransferProgressListener;
  
--import android.util.Log;
--
  
  /**
   * A RequestEntity that represents a PIECE of a file.
   * 
   * @author David A. Velasco
   */
- public class ChunkFromFileChannelRequestEntity implements RequestEntity {
+ public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
  
      private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
      
          return true;
      }
      
-     public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
-         mDataTransferListeners.add(listener);
+     @Override
+     public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.add(listener);
+         }
      }
      
-     public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-         mDataTransferListeners.addAll(listeners);
+     @Override
+     public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.addAll(listeners);
+         }
      }
      
-     public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
-         mDataTransferListeners.remove(listener);
+     @Override
+     public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.remove(listener);
+         }
      }
      
      
                  out.write(mBuffer.array(), 0, readCount);
                  mBuffer.clear();
                  mTransferred += readCount;
-                 it = mDataTransferListeners.iterator();
-                 while (it.hasNext()) {
-                     it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+                 synchronized (mDataTransferListeners) {
+                     it = mDataTransferListeners.iterator();
+                     while (it.hasNext()) {
+                         it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+                     }
                  }
              }
              
          } catch (IOException io) {
 -            Log.e(TAG, io.getMessage());
 +            Log_OC.e(TAG, io.getMessage());
              throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
              
          }
@@@ -32,18 -32,18 +32,17 @@@ import java.util.Set
  
  import org.apache.commons.httpclient.methods.RequestEntity;
  
 +import com.owncloud.android.Log_OC;
+ import com.owncloud.android.network.ProgressiveDataTransferer;
  
  import eu.alefzero.webdav.OnDatatransferProgressListener;
  
--import android.util.Log;
--
  
  /**
   * A RequestEntity that represents a File.
   * 
   */
- public class FileRequestEntity implements RequestEntity {
+ public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
  
      final File mFile;
      final String mContentType;
      public boolean isRepeatable() {
          return true;
      }
-     
-     public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
-         mDataTransferListeners.add(listener);
+     @Override
+     public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.add(listener);
+         }
      }
      
-     public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-         mDataTransferListeners.addAll(listeners);
+     @Override
+     public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.addAll(listeners);
+         }
      }
      
-     public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
-         mDataTransferListeners.remove(listener);
+     @Override
+     public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+         synchronized (mDataTransferListeners) {
+             mDataTransferListeners.remove(listener);
+         }
      }
      
      
                  out.write(tmp.array(), 0, readResult);
                  tmp.clear();
                  transferred += readResult;
-                 it = mDataTransferListeners.iterator();
-                 while (it.hasNext()) {
-                     it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+                 synchronized (mDataTransferListeners) {
+                     it = mDataTransferListeners.iterator();
+                     while (it.hasNext()) {
+                         it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+                     }
                  }
              }
              
          } catch (IOException io) {
 -            Log.e("FileRequestException", io.getMessage());
 +            Log_OC.e("FileRequestException", io.getMessage());
              throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
              
          } finally {
 -/* ownCloud Android client application\r
 - *   Copyright (C) 2011  Bartek Przybylski\r
 - *   Copyright (C) 2012-2013 ownCloud Inc.\r
 - *\r
 - *   This program is free software: you can redistribute it and/or modify\r
 - *   it under the terms of the GNU General Public License as published by\r
 - *   the Free Software Foundation, either version 2 of the License, or\r
 - *   (at your option) any later version.\r
 - *\r
 - *   This program is distributed in the hope that it will be useful,\r
 - *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 - *   GNU General Public License for more details.\r
 - *\r
 - *   You should have received a copy of the GNU General Public License\r
 - *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - *\r
 - */\r
 -package eu.alefzero.webdav;\r
 -\r
 -import java.io.BufferedInputStream;\r
 -import java.io.File;\r
 -import java.io.FileOutputStream;\r
 -import java.io.IOException;\r
 -import java.io.InputStream;\r
 -\r
 -import org.apache.commons.httpclient.Credentials;\r
 -import org.apache.commons.httpclient.HttpClient;\r
 -import org.apache.commons.httpclient.HttpConnectionManager;\r
 -import org.apache.commons.httpclient.HttpException;\r
 -import org.apache.commons.httpclient.HttpMethodBase;\r
 -import org.apache.commons.httpclient.HttpVersion;\r
 -import org.apache.commons.httpclient.UsernamePasswordCredentials;\r
 -import org.apache.commons.httpclient.auth.AuthScope;\r
 -import org.apache.commons.httpclient.methods.GetMethod;\r
 -import org.apache.commons.httpclient.methods.HeadMethod;\r
 -import org.apache.commons.httpclient.methods.PutMethod;\r
 -import org.apache.commons.httpclient.params.HttpMethodParams;\r
 -import org.apache.http.HttpStatus;\r
 -import org.apache.http.params.CoreProtocolPNames;\r
 -import org.apache.jackrabbit.webdav.client.methods.DavMethod;\r
 -import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;\r
 -import org.apache.jackrabbit.webdav.client.methods.MkColMethod;\r
 -\r
 -import android.net.Uri;\r
 -import android.util.Log;\r
 -\r
 -public class WebdavClient extends HttpClient {\r
 -    private Uri mUri;\r
 -    private Credentials mCredentials;\r
 -    final private static String TAG = "WebdavClient";\r
 -    private static final String USER_AGENT = "Android-ownCloud";\r
 -    \r
 -    private OnDatatransferProgressListener mDataTransferListener;\r
 -    static private byte[] sExhaustBuffer = new byte[1024];\r
 -    \r
 -    /**\r
 -     * Constructor\r
 -     */\r
 -    public WebdavClient(HttpConnectionManager connectionMgr) {\r
 -        super(connectionMgr);\r
 -        Log.d(TAG, "Creating WebdavClient");\r
 -        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);\r
 -        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);\r
 -    }\r
 -\r
 -    public void setCredentials(String username, String password) {\r
 -        getParams().setAuthenticationPreemptive(true);\r
 -        getState().setCredentials(AuthScope.ANY,\r
 -                getCredentials(username, password));\r
 -    }\r
 -\r
 -    private Credentials getCredentials(String username, String password) {\r
 -        if (mCredentials == null)\r
 -            mCredentials = new UsernamePasswordCredentials(username, password);\r
 -        return mCredentials;\r
 -    }\r
 -    \r
 -    /**\r
 -     * Downloads a file in remoteFilepath to the local targetPath.\r
 -     * \r
 -     * @param remoteFilepath    Path to the file in the remote server, URL DECODED. \r
 -     * @param targetFile        Local path to save the downloaded file.\r
 -     * @return                  'True' when the file is successfully downloaded.\r
 -     */\r
 -    public boolean downloadFile(String remoteFilePath, File targetFile) {\r
 -        boolean ret = false;\r
 -        GetMethod get = new GetMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));\r
 -\r
 -        try {\r
 -            int status = executeMethod(get);\r
 -            if (status == HttpStatus.SC_OK) {\r
 -                targetFile.createNewFile();\r
 -                BufferedInputStream bis = new BufferedInputStream(\r
 -                        get.getResponseBodyAsStream());\r
 -                FileOutputStream fos = new FileOutputStream(targetFile);\r
 -\r
 -                byte[] bytes = new byte[4096];\r
 -                int readResult;\r
 -                while ((readResult = bis.read(bytes)) != -1) {\r
 -                    if (mDataTransferListener != null)\r
 -                        mDataTransferListener.onTransferProgress(readResult);\r
 -                    fos.write(bytes, 0, readResult);\r
 -                }\r
 -                fos.close();\r
 -                ret = true;\r
 -            } else {\r
 -                exhaustResponse(get.getResponseBodyAsStream());\r
 -            }\r
 -            Log.e(TAG, "Download of " + remoteFilePath + " to " + targetFile + " finished with HTTP status " + status + (!ret?"(FAIL)":""));\r
 -        } catch (Exception e) {\r
 -            logException(e, "dowloading " + remoteFilePath);\r
 -            \r
 -        } finally {\r
 -            if (!ret && targetFile.exists()) {\r
 -                targetFile.delete();\r
 -            }\r
 -            get.releaseConnection();    // let the connection available for other methods\r
 -        }\r
 -        return ret;\r
 -    }\r
 -    \r
 -    /**\r
 -     * Deletes a remote file via webdav\r
 -     * @param remoteFilePath       Remote file path of the file to delete, in URL DECODED format.\r
 -     * @return\r
 -     */\r
 -    public boolean deleteFile(String remoteFilePath) {\r
 -        boolean ret = false;\r
 -        DavMethod delete = new DeleteMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));\r
 -        try {\r
 -            int status = executeMethod(delete);\r
 -            ret = (status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED || status == HttpStatus.SC_NO_CONTENT);\r
 -            exhaustResponse(delete.getResponseBodyAsStream());\r
 -            \r
 -            Log.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status +  (!ret?"(FAIL)":""));\r
 -            \r
 -        } catch (Exception e) {\r
 -            logException(e, "deleting " + remoteFilePath);\r
 -            \r
 -        } finally {\r
 -            delete.releaseConnection();    // let the connection available for other methods\r
 -        }\r
 -        return ret;\r
 -    }\r
 -\r
 -    \r
 -    public void setDataTransferProgressListener(OnDatatransferProgressListener listener) {\r
 -        mDataTransferListener = listener;\r
 -    }\r
 -    \r
 -    /**\r
 -     * Creates or update a file in the remote server with the contents of a local file.\r
 -     * \r
 -     * @param localFile         Path to the local file to upload.\r
 -     * @param remoteTarget      Remote path to the file to create or update, URL DECODED\r
 -     * @param contentType       MIME type of the file.\r
 -     * @return                  Status HTTP code returned by the server.\r
 -     * @throws IOException      When a transport error that could not be recovered occurred while uploading the file to the server.\r
 -     * @throws HttpException    When a violation of the HTTP protocol occurred. \r
 -     */\r
 -    public int putFile(String localFile, String remoteTarget, String contentType) throws HttpException, IOException {\r
 -        int status = -1;\r
 -        PutMethod put = new PutMethod(mUri.toString() + WebdavUtils.encodePath(remoteTarget));\r
 -        \r
 -        try {\r
 -            File f = new File(localFile);\r
 -            FileRequestEntity entity = new FileRequestEntity(f, contentType);\r
 -            entity.addDatatransferProgressListener(mDataTransferListener);\r
 -            put.setRequestEntity(entity);\r
 -            status = executeMethod(put);\r
 -            \r
 -            exhaustResponse(put.getResponseBodyAsStream());\r
 -            \r
 -        } finally {\r
 -            put.releaseConnection();    // let the connection available for other methods\r
 -        }\r
 -        return status;\r
 -    }\r
 -    \r
 -    /**\r
 -     * Tries to log in to the current URI, with the current credentials\r
 -     * \r
 -     * @return A {@link HttpStatus}-Code of the result. SC_OK is good.\r
 -     */\r
 -    public int tryToLogin() {\r
 -        int status = 0;\r
 -        HeadMethod head = new HeadMethod(mUri.toString());\r
 -        try {\r
 -            status = executeMethod(head);\r
 -            boolean result = status == HttpStatus.SC_OK;\r
 -            Log.d(TAG, "HEAD for " + mUri + " finished with HTTP status " + status + (!result?"(FAIL)":""));\r
 -            exhaustResponse(head.getResponseBodyAsStream());\r
 -            \r
 -        } catch (Exception e) {\r
 -            logException(e, "trying to login at " + mUri.toString());\r
 -            \r
 -        } finally {\r
 -            head.releaseConnection();\r
 -        }\r
 -        return status;\r
 -    }\r
 -\r
 -    /**\r
 -     * Creates a remote directory with the received path.\r
 -     * \r
 -     * @param path      Path of the directory to create, URL DECODED\r
 -     * @return          'True' when the directory is successfully created\r
 -     */\r
 -    public boolean createDirectory(String path) {\r
 -        boolean result = false;\r
 -        int status = -1;\r
 -        MkColMethod mkcol = new MkColMethod(mUri.toString() + WebdavUtils.encodePath(path));\r
 -        try {\r
 -            Log.d(TAG, "Creating directory " + path);\r
 -            status = executeMethod(mkcol);\r
 -            Log.d(TAG, "Status returned: " + status);\r
 -            result = mkcol.succeeded();\r
 -            \r
 -            Log.d(TAG, "MKCOL to " + path + " finished with HTTP status " + status + (!result?"(FAIL)":""));\r
 -            exhaustResponse(mkcol.getResponseBodyAsStream());\r
 -            \r
 -        } catch (Exception e) {\r
 -            logException(e, "creating directory " + path);\r
 -            \r
 -        } finally {\r
 -            mkcol.releaseConnection();    // let the connection available for other methods\r
 -        }\r
 -        return result;\r
 -    }\r
 -    \r
 -    \r
 -    /**\r
 -     * Check if a file exists in the OC server\r
 -     * \r
 -     * @return              'true' if the file exists; 'false' it doesn't exist\r
 -     * @throws  Exception   When the existence could not be determined\r
 -     */\r
 -    public boolean existsFile(String path) throws IOException, HttpException {\r
 -        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));\r
 -        try {\r
 -            int status = executeMethod(head);\r
 -            Log.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));\r
 -            exhaustResponse(head.getResponseBodyAsStream());\r
 -            return (status == HttpStatus.SC_OK);\r
 -            \r
 -        } finally {\r
 -            head.releaseConnection();    // let the connection available for other methods\r
 -        }\r
 -    }\r
 -\r
 -\r
 -    /**\r
 -     * Requests the received method with the received timeout (milliseconds).\r
 -     * \r
 -     * Executes the method through the inherited HttpClient.executedMethod(method).\r
 -     * \r
 -     * Sets the socket and connection timeouts only for the method received.\r
 -     * \r
 -     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'\r
 -     * \r
 -     * @param method            HTTP method request.\r
 -     * @param readTimeout       Timeout to set for data reception\r
 -     * @param conntionTimout    Timeout to set for connection establishment\r
 -     */\r
 -    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {\r
 -        int oldSoTimeout = getParams().getSoTimeout();\r
 -        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();\r
 -        try {\r
 -            if (readTimeout >= 0) { \r
 -                method.getParams().setSoTimeout(readTimeout);   // this should be enough...\r
 -                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS\r
 -            }\r
 -            if (connectionTimeout >= 0) {\r
 -                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);\r
 -            }\r
 -            return executeMethod(method);\r
 -        } finally {\r
 -            getParams().setSoTimeout(oldSoTimeout);\r
 -            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);\r
 -        }\r
 -    }\r
 -\r
 -    /**\r
 -     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.\r
 -     * \r
 -     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.\r
 -     */\r
 -    public void exhaustResponse(InputStream responseBodyAsStream) {\r
 -        if (responseBodyAsStream != null) {\r
 -            try {\r
 -                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);\r
 -                responseBodyAsStream.close();\r
 -            \r
 -            } catch (IOException io) {\r
 -                Log.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);\r
 -            }\r
 -        }\r
 -    }\r
 -\r
 -\r
 -    /**\r
 -     * Logs an exception triggered in a HTTP request. \r
 -     * \r
 -     * @param e         Caught exception.\r
 -     * @param doing     Suffix to add at the end of the logged message.\r
 -     */\r
 -    private void logException(Exception e, String doing) {\r
 -        if (e instanceof HttpException) {\r
 -            Log.e(TAG, "HTTP violation while " + doing, e);\r
 -\r
 -        } else if (e instanceof IOException) {\r
 -            Log.e(TAG, "Unrecovered transport exception while " + doing, e);\r
 -\r
 -        } else {\r
 -            Log.e(TAG, "Unexpected exception while " + doing, e);\r
 -        }\r
 -    }\r
 -\r
 -    \r
 -    /**\r
 -     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.\r
 -     */\r
 -    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {\r
 -            getParams().setSoTimeout(defaultDataTimeout);\r
 -            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);\r
 -    }\r
 -\r
 -    /**\r
 -     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs\r
 -     * @param uri\r
 -     */\r
 -    public void setBaseUri(Uri uri) {\r
 -        mUri = uri;\r
 -    }\r
 -\r
 -    public Uri getBaseUri() {\r
 -        return mUri;\r
 -    }\r
 -\r
 -}\r
 +/* ownCloud Android client application
 + *   Copyright (C) 2011  Bartek Przybylski
 + *   Copyright (C) 2012-2013 ownCloud Inc.
 + *
 + *   This program is free software: you can redistribute it and/or modify
 + *   it under the terms of the GNU General Public License as published by
 + *   the Free Software Foundation, either version 2 of the License, or
 + *   (at your option) any later version.
 + *
 + *   This program is distributed in the hope that it will be useful,
 + *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *   GNU General Public License for more details.
 + *
 + *   You should have received a copy of the GNU General Public License
 + *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +package eu.alefzero.webdav;
 +
 +import java.io.BufferedInputStream;
 +import java.io.File;
 +import java.io.FileOutputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +
 +import org.apache.commons.httpclient.Credentials;
 +import org.apache.commons.httpclient.HttpClient;
 +import org.apache.commons.httpclient.HttpConnectionManager;
 +import org.apache.commons.httpclient.HttpException;
 +import org.apache.commons.httpclient.HttpMethodBase;
 +import org.apache.commons.httpclient.HttpVersion;
 +import org.apache.commons.httpclient.UsernamePasswordCredentials;
 +import org.apache.commons.httpclient.auth.AuthScope;
 +import org.apache.commons.httpclient.methods.GetMethod;
 +import org.apache.commons.httpclient.methods.HeadMethod;
 +import org.apache.commons.httpclient.methods.PutMethod;
 +import org.apache.commons.httpclient.params.HttpMethodParams;
 +import org.apache.http.HttpStatus;
 +import org.apache.http.params.CoreProtocolPNames;
 +import org.apache.jackrabbit.webdav.client.methods.DavMethod;
 +import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
 +import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
 +
 +import com.owncloud.android.Log_OC;
 +
 +import android.net.Uri;
 +import android.util.Log;
 +
 +public class WebdavClient extends HttpClient {
 +    private Uri mUri;
 +    private Credentials mCredentials;
 +    final private static String TAG = "WebdavClient";
 +    private static final String USER_AGENT = "Android-ownCloud";
 +    
 +    private OnDatatransferProgressListener mDataTransferListener;
 +    static private byte[] sExhaustBuffer = new byte[1024];
 +    
 +    /**
 +     * Constructor
 +     */
 +    public WebdavClient(HttpConnectionManager connectionMgr) {
 +        super(connectionMgr);
 +        Log_OC.d(TAG, "Creating WebdavClient");
 +        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
 +        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
 +    }
 +
 +    public void setCredentials(String username, String password) {
 +        getParams().setAuthenticationPreemptive(true);
 +        getState().setCredentials(AuthScope.ANY,
 +                getCredentials(username, password));
 +    }
 +
 +    private Credentials getCredentials(String username, String password) {
 +        if (mCredentials == null)
 +            mCredentials = new UsernamePasswordCredentials(username, password);
 +        return mCredentials;
 +    }
 +    
 +    /**
 +     * Downloads a file in remoteFilepath to the local targetPath.
 +     * 
 +     * @param remoteFilepath    Path to the file in the remote server, URL DECODED. 
 +     * @param targetFile        Local path to save the downloaded file.
 +     * @return                  'True' when the file is successfully downloaded.
 +     */
 +    public boolean downloadFile(String remoteFilePath, File targetFile) {
 +        boolean ret = false;
 +        GetMethod get = new GetMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));
 +
 +        try {
 +            int status = executeMethod(get);
 +            if (status == HttpStatus.SC_OK) {
 +                targetFile.createNewFile();
 +                BufferedInputStream bis = new BufferedInputStream(
 +                        get.getResponseBodyAsStream());
 +                FileOutputStream fos = new FileOutputStream(targetFile);
 +
 +                byte[] bytes = new byte[4096];
 +                int readResult;
 +                while ((readResult = bis.read(bytes)) != -1) {
 +                    if (mDataTransferListener != null)
 +                        mDataTransferListener.onTransferProgress(readResult);
 +                    fos.write(bytes, 0, readResult);
 +                }
 +                fos.close();
 +                ret = true;
 +            } else {
 +                exhaustResponse(get.getResponseBodyAsStream());
 +            }
 +            Log_OC.e(TAG, "Download of " + remoteFilePath + " to " + targetFile + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
++            
 +        } catch (Exception e) {
 +            logException(e, "dowloading " + remoteFilePath);
 +            
 +        } finally {
 +            if (!ret && targetFile.exists()) {
 +                targetFile.delete();
 +            }
 +            get.releaseConnection();    // let the connection available for other methods
 +        }
 +        return ret;
 +    }
 +    
 +    /**
 +     * Deletes a remote file via webdav
 +     * @param remoteFilePath       Remote file path of the file to delete, in URL DECODED format.
 +     * @return
 +     */
 +    public boolean deleteFile(String remoteFilePath) {
 +        boolean ret = false;
 +        DavMethod delete = new DeleteMethod(mUri.toString() + WebdavUtils.encodePath(remoteFilePath));
 +        try {
 +            int status = executeMethod(delete);
 +            ret = (status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED || status == HttpStatus.SC_NO_CONTENT);
 +            exhaustResponse(delete.getResponseBodyAsStream());
 +            
-             Log.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status +  (!ret?"(FAIL)":""));
++            Log_OC.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status +  (!ret?"(FAIL)":""));
 +            
 +        } catch (Exception e) {
 +            logException(e, "deleting " + remoteFilePath);
 +            
 +        } finally {
 +            delete.releaseConnection();    // let the connection available for other methods
 +        }
 +        return ret;
 +    }
 +
 +    
 +    public void setDataTransferProgressListener(OnDatatransferProgressListener listener) {
 +        mDataTransferListener = listener;
 +    }
 +    
 +    /**
 +     * Creates or update a file in the remote server with the contents of a local file.
 +     * 
 +     * @param localFile         Path to the local file to upload.
 +     * @param remoteTarget      Remote path to the file to create or update, URL DECODED
 +     * @param contentType       MIME type of the file.
 +     * @return                  Status HTTP code returned by the server.
 +     * @throws IOException      When a transport error that could not be recovered occurred while uploading the file to the server.
 +     * @throws HttpException    When a violation of the HTTP protocol occurred. 
 +     */
 +    public int putFile(String localFile, String remoteTarget, String contentType) throws HttpException, IOException {
 +        int status = -1;
 +        PutMethod put = new PutMethod(mUri.toString() + WebdavUtils.encodePath(remoteTarget));
 +        
 +        try {
 +            File f = new File(localFile);
 +            FileRequestEntity entity = new FileRequestEntity(f, contentType);
-             entity.addOnDatatransferProgressListener(mDataTransferListener);
++            entity.addDatatransferProgressListener(mDataTransferListener);
 +            put.setRequestEntity(entity);
 +            status = executeMethod(put);
 +            
 +            exhaustResponse(put.getResponseBodyAsStream());
 +            
 +        } finally {
 +            put.releaseConnection();    // let the connection available for other methods
 +        }
 +        return status;
 +    }
 +    
 +    /**
 +     * Tries to log in to the current URI, with the current credentials
 +     * 
 +     * @return A {@link HttpStatus}-Code of the result. SC_OK is good.
 +     */
 +    public int tryToLogin() {
 +        int status = 0;
 +        HeadMethod head = new HeadMethod(mUri.toString());
 +        try {
 +            status = executeMethod(head);
 +            boolean result = status == HttpStatus.SC_OK;
 +            Log_OC.d(TAG, "HEAD for " + mUri + " finished with HTTP status " + status + (!result?"(FAIL)":""));
 +            exhaustResponse(head.getResponseBodyAsStream());
 +            
 +        } catch (Exception e) {
 +            logException(e, "trying to login at " + mUri.toString());
 +            
 +        } finally {
 +            head.releaseConnection();
 +        }
 +        return status;
 +    }
 +
 +    /**
 +     * Creates a remote directory with the received path.
 +     * 
 +     * @param path      Path of the directory to create, URL DECODED
 +     * @return          'True' when the directory is successfully created
 +     */
 +    public boolean createDirectory(String path) {
 +        boolean result = false;
 +        int status = -1;
 +        MkColMethod mkcol = new MkColMethod(mUri.toString() + WebdavUtils.encodePath(path));
 +        try {
 +            Log_OC.d(TAG, "Creating directory " + path);
 +            status = executeMethod(mkcol);
 +            Log_OC.d(TAG, "Status returned: " + status);
 +            result = mkcol.succeeded();
 +            
 +            Log_OC.d(TAG, "MKCOL to " + path + " finished with HTTP status " + status + (!result?"(FAIL)":""));
 +            exhaustResponse(mkcol.getResponseBodyAsStream());
 +            
 +        } catch (Exception e) {
 +            logException(e, "creating directory " + path);
 +            
 +        } finally {
 +            mkcol.releaseConnection();    // let the connection available for other methods
 +        }
 +        return result;
 +    }
 +    
 +    
 +    /**
 +     * Check if a file exists in the OC server
 +     * 
 +     * @return              'true' if the file exists; 'false' it doesn't exist
 +     * @throws  Exception   When the existence could not be determined
 +     */
 +    public boolean existsFile(String path) throws IOException, HttpException {
 +        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
 +        try {
 +            int status = executeMethod(head);
 +            Log_OC.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
 +            exhaustResponse(head.getResponseBodyAsStream());
 +            return (status == HttpStatus.SC_OK);
 +            
 +        } finally {
 +            head.releaseConnection();    // let the connection available for other methods
 +        }
 +    }
 +
 +    /**
 +     * Requests the received method with the received timeout (milliseconds).
 +     * 
 +     * Executes the method through the inherited HttpClient.executedMethod(method).
 +     * 
 +     * Sets the socket and connection timeouts only for the method received.
 +     * 
 +     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
 +     * 
 +     * @param method            HTTP method request.
 +     * @param readTimeout       Timeout to set for data reception
 +     * @param conntionTimout    Timeout to set for connection establishment
 +     */
 +    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
 +        int oldSoTimeout = getParams().getSoTimeout();
 +        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
 +        try {
 +            if (readTimeout >= 0) { 
 +                method.getParams().setSoTimeout(readTimeout);   // this should be enough...
 +                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS
 +            }
 +            if (connectionTimeout >= 0) {
 +                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
 +            }
 +            return executeMethod(method);
 +        } finally {
 +            getParams().setSoTimeout(oldSoTimeout);
 +            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
 +        }
 +    }
 +
 +    /**
 +     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
 +     * 
 +     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.
 +     */
 +    public void exhaustResponse(InputStream responseBodyAsStream) {
 +        if (responseBodyAsStream != null) {
 +            try {
 +                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
 +                responseBodyAsStream.close();
 +            
 +            } catch (IOException io) {
 +                Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
 +            }
 +        }
 +    }
 +
 +    /**
 +     * Logs an exception triggered in a HTTP request. 
 +     * 
 +     * @param e         Caught exception.
 +     * @param doing     Suffix to add at the end of the logged message.
 +     */
 +    private void logException(Exception e, String doing) {
 +        if (e instanceof HttpException) {
 +            Log_OC.e(TAG, "HTTP violation while " + doing, e);
 +
 +        } else if (e instanceof IOException) {
 +            Log_OC.e(TAG, "Unrecovered transport exception while " + doing, e);
 +
 +        } else {
 +            Log_OC.e(TAG, "Unexpected exception while " + doing, e);
 +        }
 +    }
 +
 +    
 +    /**
 +     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
 +     */
 +    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
 +            getParams().setSoTimeout(defaultDataTimeout);
 +            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
 +    }
 +
 +    /**
 +     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
 +     * @param uri
 +     */
 +    public void setBaseUri(Uri uri) {
 +        mUri = uri;
 +    }
 +
 +    public Uri getBaseUri() {
 +        return mUri;
 +    }
 +
 +}