Browse Source

Merge pull request #118 from owncloud/loggingtool

This can go in by now.
David A. Velasco 12 years ago
parent
commit
5a25a6a698
61 changed files with 5308 additions and 4929 deletions
  1. 174 172
      AndroidManifest.xml
  2. 19 0
      res/layout/log_item.xml
  3. 34 0
      res/layout/log_send_file.xml
  4. 0 1
      res/menu/main_menu.xml
  5. 10 3
      res/values/strings.xml
  6. 13 2
      res/xml/preferences.xml
  7. 127 0
      src/com/owncloud/android/Log_OC.java
  8. 407 407
      src/com/owncloud/android/Uploader.java
  9. 283 282
      src/com/owncloud/android/authenticator/AccountAuthenticator.java
  10. 12 11
      src/com/owncloud/android/datamodel/FileDataStorageManager.java
  11. 4 5
      src/com/owncloud/android/datamodel/OCFile.java
  12. 5 3
      src/com/owncloud/android/db/DbHandler.java
  13. 2 1
      src/com/owncloud/android/extensions/ExtensionsAvailableDialog.java
  14. 2 1
      src/com/owncloud/android/extensions/ExtensionsListActivity.java
  15. 4 3
      src/com/owncloud/android/files/BootupBroadcastReceiver.java
  16. 11 10
      src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
  17. 3 2
      src/com/owncloud/android/files/OwnCloudFileObserver.java
  18. 510 511
      src/com/owncloud/android/files/services/FileDownloader.java
  19. 12 11
      src/com/owncloud/android/files/services/FileObserverService.java
  20. 18 17
      src/com/owncloud/android/files/services/FileUploader.java
  21. 8 8
      src/com/owncloud/android/files/services/InstantUploadService.java
  22. 4 2
      src/com/owncloud/android/location/LocationServiceLauncherReciever.java
  23. 3 2
      src/com/owncloud/android/location/LocationUpdateService.java
  24. 7 7
      src/com/owncloud/android/media/MediaService.java
  25. 5 5
      src/com/owncloud/android/media/MediaServiceBinder.java
  26. 5 3
      src/com/owncloud/android/network/AdvancedSslSocketFactory.java
  27. 3 1
      src/com/owncloud/android/network/AdvancedX509TrustManager.java
  28. 7 6
      src/com/owncloud/android/network/OwnCloudClientUtils.java
  29. 2 1
      src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
  30. 5 4
      src/com/owncloud/android/operations/ConnectionCheckOperation.java
  31. 4 3
      src/com/owncloud/android/operations/DownloadFileOperation.java
  32. 2 1
      src/com/owncloud/android/operations/RemoteOperationResult.java
  33. 3 2
      src/com/owncloud/android/operations/RemoveFileOperation.java
  34. 4 3
      src/com/owncloud/android/operations/RenameFileOperation.java
  35. 3 2
      src/com/owncloud/android/operations/SynchronizeFileOperation.java
  36. 10 9
      src/com/owncloud/android/operations/SynchronizeFolderOperation.java
  37. 6 5
      src/com/owncloud/android/operations/UpdateOCVersionOperation.java
  38. 6 12
      src/com/owncloud/android/operations/UploadFileOperation.java
  39. 290 289
      src/com/owncloud/android/providers/FileContentProvider.java
  40. 371 370
      src/com/owncloud/android/syncadapter/FileSyncAdapter.java
  41. 2 1
      src/com/owncloud/android/ui/activity/AccountSelectActivity.java
  42. 610 609
      src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
  43. 2 2
      src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java
  44. 4 3
      src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java
  45. 392 395
      src/com/owncloud/android/ui/activity/FileDetailActivity.java
  46. 23 74
      src/com/owncloud/android/ui/activity/FileDisplayActivity.java
  47. 14 13
      src/com/owncloud/android/ui/activity/InstantUploadActivity.java
  48. 119 0
      src/com/owncloud/android/ui/activity/LogHistoryActivity.java
  49. 241 237
      src/com/owncloud/android/ui/activity/Preferences.java
  50. 8 7
      src/com/owncloud/android/ui/activity/UploadFilesActivity.java
  51. 54 0
      src/com/owncloud/android/ui/adapter/LogListAdapter.java
  52. 3 2
      src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
  53. 2 1
      src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java
  54. 1058 1037
      src/com/owncloud/android/ui/fragment/FileDetailFragment.java
  55. 11 10
      src/com/owncloud/android/ui/fragment/LocalFileListFragment.java
  56. 14 13
      src/com/owncloud/android/ui/fragment/OCFileListFragment.java
  57. 4 0
      src/com/owncloud/android/utils/FileStorageUtils.java
  58. 2 3
      src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java
  59. 2 3
      src/eu/alefzero/webdav/FileRequestEntity.java
  60. 342 341
      src/eu/alefzero/webdav/WebdavClient.java
  61. 3 1
      src/eu/alefzero/webdav/WebdavEntry.java

+ 174 - 172
AndroidManifest.xml

@@ -1,174 +1,176 @@
-<?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="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 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"/>
+<?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="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 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.InstantUploadService" />
         <service android:name=".files.services.InstantUploadService" />
-        <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>
+        <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>

+ 19 - 0
res/layout/log_item.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal" >
+    
+     <TextView android:id="@+id/log_item_single"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:gravity="center_vertical"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentBottom="true"
+        android:textStyle="bold"
+        android:textSize="22dp"
+        android:textColor="#000000"
+        android:layout_marginTop="5dp"
+        android:layout_marginBottom="5dp" />
+
+</LinearLayout>

+ 34 - 0
res/layout/log_send_file.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <LinearLayout 
+      	 xmlns:android="http://schemas.android.com/apk/res/android"
+         android:orientation="vertical"
+         android:layout_width="match_parent"
+         android:layout_height="match_parent"
+         android:paddingLeft="8dp"
+         android:paddingRight="8dp">
+      
+
+     <ListView 	android:id="@android:id/list"
+               	android:layout_width="match_parent"
+               	android:layout_height="wrap_content"
+               />
+
+     <TextView 	android:id="@android:id/empty"
+               	android:layout_width="match_parent"
+               	android:layout_height="wrap_content"
+               	android:background="#FF0000"
+               	android:text="No data"/>
+     <LinearLayout 
+         android:orientation="vertical"
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+         android:gravity="bottom">
+        
+     <Button   	android:id="@+id/deleteLogHistoryButton"
+         		android:layout_width="match_parent"
+     		   	android:layout_height="wrap_content"
+     		   	android:text="@string/prefs_log_delete_history_button"/>
+     
+     </LinearLayout>
+     
+ </LinearLayout>

+ 0 - 1
res/menu/main_menu.xml

@@ -24,7 +24,6 @@
     <item android:id="@+id/action_create_dir" 		android:title="@string/actionbar_mkdir" 	android:icon="@drawable/ic_action_create_dir"			android:orderInCategory="2" />
     <item android:id="@+id/action_create_dir" 		android:title="@string/actionbar_mkdir" 	android:icon="@drawable/ic_action_create_dir"			android:orderInCategory="2" />
     <item android:id="@+id/action_upload" 			android:title="@string/actionbar_upload" 	android:icon="@drawable/ic_action_upload" 				android:orderInCategory="2" />
     <item android:id="@+id/action_upload" 			android:title="@string/actionbar_upload" 	android:icon="@drawable/ic_action_upload" 				android:orderInCategory="2" />
     <item android:id="@+id/action_settings" 		android:title="@string/actionbar_settings" 	android:icon="@android:drawable/ic_menu_preferences" 	android:orderInCategory="2" />
     <item android:id="@+id/action_settings" 		android:title="@string/actionbar_settings" 	android:icon="@android:drawable/ic_menu_preferences" 	android:orderInCategory="2" />
-    <item android:id="@+id/action_about_app" 		android:title="@string/about_title" 		android:icon="@android:drawable/ic_menu_info_details" 	android:orderInCategory="2" />
     
     
     <!--  <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item>-->
     <!--  <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item>-->
 </menu>
 </menu>

+ 10 - 3
res/values/strings.xml

@@ -14,7 +14,8 @@
     <string name="main_settings">Settings</string>
     <string name="main_settings">Settings</string>
     <string name="main_tit_accsetup">Setup Account</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="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">%1$s Android App</string>
+    <string name="about_version">version %1$s</string>
     <string name="actionbar_sync">Refresh</string>
     <string name="actionbar_sync">Refresh</string>
     <string name="actionbar_upload">Upload</string>
     <string name="actionbar_upload">Upload</string>
     <string name="actionbar_upload_from_apps">Content from other apps</string>
     <string name="actionbar_upload_from_apps">Content from other apps</string>
@@ -40,6 +41,12 @@
     <string name="prefs_pincode_summary">Protect your client</string>
     <string name="prefs_pincode_summary">Protect your client</string>
     <string name="prefs_instant_upload">Enable instant uploads</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_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_host_url">URL</string>
     <string name="auth_username">Username</string>
     <string name="auth_username">Username</string>
     <string name="auth_password">Password</string>
     <string name="auth_password">Password</string>
@@ -169,14 +176,14 @@
         <item>60</item>
         <item>60</item>
     </string-array>
     </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_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_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_connect_anyway">Connect anyway</string>
     <string name="auth_nossl_plain_ok_title">Secure connection unavailable.</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_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_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_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_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="auth_unknown_error_title">Unknown error occurred!</string>

+ 13 - 2
res/xml/preferences.xml

@@ -32,8 +32,19 @@
     <CheckBoxPreference android:key="instant_uploading" 
     <CheckBoxPreference android:key="instant_uploading" 
                         android:title="@string/prefs_instant_upload"  
                         android:title="@string/prefs_instant_upload"  
                         android:summary="@string/prefs_instant_upload_summary"/>
                         android:summary="@string/prefs_instant_upload_summary"/>
-    <CheckBoxPreference android:dependency="instant_uploading" android:disableDependentsState="true" android:title="@string/instant_upload_on_wifi" android:key="instant_upload_on_wifi"/>
-    
+    <CheckBoxPreference android:dependency="instant_uploading" 
+        				android:disableDependentsState="true" 
+        				android:title="@string/instant_upload_on_wifi" 
+        				android:key="instant_upload_on_wifi"/>
+    <CheckBoxPreference android:key="log_to_file" 
+                        android:title="@string/prefs_log_title"  
+                        android:summary="@string/prefs_log_summary"/>
+	<Preference 		android:key="log_history" 
+                        android:title="@string/prefs_log_title_history"  
+                        android:summary="@string/prefs_log_summary_history"/>
+	<Preference 		android:id="@+id/about_app" 
+        				android:title="@string/about_title" 
+        				android:key="about_app" />
 	</PreferenceCategory>
 	</PreferenceCategory>
     
     
 
 

+ 127 - 0
src/com/owncloud/android/Log_OC.java

@@ -0,0 +1,127 @@
+package com.owncloud.android;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import android.util.Log;
+
+
+
+public class Log_OC {
+    
+
+    private static boolean isEnabled = false;
+    private static File logFile;
+    private static File folder;
+    private static BufferedWriter buf;  
+    
+    public static void i(String TAG, String message){
+        // Printing the message to LogCat console
+        Log.i(TAG, message);
+        // Write the log message to the file
+        appendLog(TAG+" : "+message);
+    }
+
+    public static void d(String TAG, String message){
+        Log.d(TAG, message);
+        appendLog(TAG+" : "+message);
+    }
+    public static void d(String TAG, String message, Exception e) {
+        Log.d(TAG, message, e);
+        appendLog(TAG+" : "+ message+" Exception : "+e.getStackTrace());
+    }
+    public static void e(String TAG, String message){
+        Log.e(TAG, message);
+        appendLog(TAG+" : "+message);
+    }
+    
+    public static void e(String TAG, String message, Throwable e) {
+        Log.e(TAG, message, e);
+        appendLog(TAG+" : "+ message+" Exception : "+e.getStackTrace());
+    }
+    
+    public static void v(String TAG, String message){
+        Log.v(TAG, message);
+        appendLog(TAG+" : "+message);
+    }
+    
+    public static void w(String TAG, String message) {
+        Log.w(TAG,message); 
+        appendLog(TAG+" : "+message);
+    }
+    
+    public static void wtf(String TAG, String message) {
+        Log.wtf(TAG,message); 
+        appendLog(TAG+" : "+message);
+    }
+    
+    public static void startLogging(String logPath) {
+        folder = new File(logPath);
+        logFile = new File(folder+File.separator+"log.txt");
+        
+        if (!folder.exists()) {
+            folder.mkdirs();
+        }
+        if (logFile.exists()) {
+            logFile.delete();
+        }
+        try { 
+            logFile.createNewFile();
+            buf = new BufferedWriter(new FileWriter(logFile, true));
+            isEnabled = true;
+            appendPhoneInfo();
+        }catch (IOException e){ 
+            e.printStackTrace(); 
+        } 
+    }
+    
+    public static void stopLogging() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.getDefault());
+        String currentDateandTime = sdf.format(new Date());
+        if (logFile != null) {
+            logFile.renameTo(new File(folder+File.separator+"Owncloud_"+currentDateandTime+".log"));
+          
+            isEnabled = false;
+            try {
+                buf.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            } 
+        
+        }
+        
+    }
+    
+    private static void appendPhoneInfo() {
+        appendLog("Model : " + android.os.Build.MODEL);
+        appendLog("Brand : " + android.os.Build.BRAND);
+        appendLog("Product : " + android.os.Build.PRODUCT);
+        appendLog("Device : " + android.os.Build.DEVICE);
+        appendLog("Version-Codename : " + android.os.Build.VERSION.CODENAME);
+        appendLog("Version-Release : " + android.os.Build.VERSION.RELEASE);
+    }
+    
+    private static void appendLog(String text) { 
+        if (isEnabled) {
+           try { 
+               buf.append(text); 
+               buf.newLine(); 
+           } catch (IOException e) { 
+               e.printStackTrace(); 
+        } 
+    }
+}
+
+    
+   
+
+  
+
+   
+   
+}

+ 407 - 407
src/com/owncloud/android/Uploader.java

@@ -1,407 +1,407 @@
-/* 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;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Stack;
-import java.util.Vector;
-
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.datamodel.DataStorageManager;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.network.OwnCloudClientUtils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
-import android.app.Dialog;
-import android.app.ListActivity;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.provider.MediaStore.Images.Media;
-import android.util.Log;
-import android.view.View;
-import android.view.Window;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.SimpleAdapter;
-import android.widget.Toast;
-
-import com.owncloud.android.R;
-import eu.alefzero.webdav.WebdavClient;
-
-/**
- * This can be used to upload things to an ownCloud instance.
- * 
- * @author Bartek Przybylski
- * 
- */
-public class Uploader extends ListActivity implements OnItemClickListener, android.view.View.OnClickListener {
-    private static final String TAG = "ownCloudUploader";
-
-    private Account mAccount;
-    private AccountManager mAccountManager;
-    private Stack<String> mParents;
-    private ArrayList<Parcelable> mStreamsToUpload;
-    private boolean mCreateDir;
-    private String mUploadPath;
-    private static final String[] CONTENT_PROJECTION = { Media.DATA, Media.DISPLAY_NAME, Media.MIME_TYPE, Media.SIZE };
-    private DataStorageManager mStorageManager;
-    private OCFile mFile;
-
-    private final static int DIALOG_NO_ACCOUNT = 0;
-    private final static int DIALOG_WAITING = 1;
-    private final static int DIALOG_NO_STREAM = 2;
-    private final static int DIALOG_MULTIPLE_ACCOUNT = 3;
-    //private final static int DIALOG_GET_DIRNAME = 4;
-
-    private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
-        mParents = new Stack<String>();
-        mParents.add("");
-        /*if (getIntent().hasExtra(Intent.EXTRA_STREAM)) {
-            prepareStreamsToUpload();*/
-        if (prepareStreamsToUpload()) {
-            mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
-            Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE);
-            if (accounts.length == 0) {
-                Log.i(TAG, "No ownCloud account is available");
-                showDialog(DIALOG_NO_ACCOUNT);
-            } else if (accounts.length > 1) {
-                Log.i(TAG, "More then one ownCloud is available");
-                showDialog(DIALOG_MULTIPLE_ACCOUNT);
-            } else {
-                mAccount = accounts[0];
-                mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                populateDirectoryList();
-            }
-        } else {
-            showDialog(DIALOG_NO_STREAM);
-        }
-    }
-    
-    @Override
-    protected Dialog onCreateDialog(final int id) {
-        final AlertDialog.Builder builder = new Builder(this);
-        switch (id) {
-        case DIALOG_WAITING:
-            ProgressDialog pDialog = new ProgressDialog(this);
-            pDialog.setIndeterminate(false);
-            pDialog.setCancelable(false);
-            pDialog.setMessage(getResources().getString(R.string.uploader_info_uploading));
-            return pDialog;
-        case DIALOG_NO_ACCOUNT:
-            builder.setIcon(android.R.drawable.ic_dialog_alert);
-            builder.setTitle(R.string.uploader_wrn_no_account_title);
-            builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
-            builder.setCancelable(false);
-            builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) {
-                        // using string value since in API7 this
-                        // constatn is not defined
-                        // in API7 < this constatant is defined in
-                        // Settings.ADD_ACCOUNT_SETTINGS
-                        // and Settings.EXTRA_AUTHORITIES
-                        Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
-                        intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
-                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
-                    } else {
-                        // since in API7 there is no direct call for
-                        // account setup, so we need to
-                        // show our own AccountSetupAcricity, get
-                        // desired results and setup
-                        // everything for ourself
-                        Intent intent = new Intent(getBaseContext(), AccountAuthenticator.class);
-                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
-                    }
-                }
-            });
-            builder.setNegativeButton(R.string.uploader_wrn_no_account_quit_btn_text, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            return builder.create();
-        /*case DIALOG_GET_DIRNAME:
-            final EditText dirName = new EditText(getBaseContext());
-            builder.setView(dirName);
-            builder.setTitle(R.string.uploader_info_dirname);
-            String pathToUpload;
-            if (mParents.empty()) {
-                pathToUpload = "/";
-            } else {
-                mCursor = managedQuery(Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, mParents.peek()), null,
-                        null, null, null);
-                mCursor.moveToFirst();
-                pathToUpload = mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_PATH))
-                        + mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_NAME)).replace(" ", "%20");   // TODO don't make this ; use WebdavUtils.encode in the right moment
-            }
-            a a = new a(pathToUpload, dirName);
-            builder.setPositiveButton(R.string.common_ok, a);
-            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
-                public void onClick(DialogInterface dialog, int which) {
-                    dialog.cancel();
-                }
-            });
-            return builder.create();*/
-        case DIALOG_MULTIPLE_ACCOUNT:
-            CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE).length];
-            for (int i = 0; i < ac.length; ++i) {
-                ac[i] = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[i].name;
-            }
-            builder.setTitle(R.string.common_choose_account);
-            builder.setItems(ac, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    mAccount = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[which];
-                    mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                    populateDirectoryList();
-                }
-            });
-            builder.setCancelable(true);
-            builder.setOnCancelListener(new OnCancelListener() {
-                @Override
-                public void onCancel(DialogInterface dialog) {
-                    dialog.cancel();
-                    finish();
-                }
-            });
-            return builder.create();
-        case DIALOG_NO_STREAM:
-            builder.setIcon(android.R.drawable.ic_dialog_alert);
-            builder.setTitle(R.string.uploader_wrn_no_content_title);
-            builder.setMessage(R.string.uploader_wrn_no_content_text);
-            builder.setCancelable(false);
-            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            return builder.create();
-        default:
-            throw new IllegalArgumentException("Unknown dialog id: " + id);
-        }
-    }
-
-    class a implements OnClickListener {
-        String mPath;
-        EditText mDirname;
-
-        public a(String path, EditText dirname) {
-            mPath = path; 
-            mDirname = dirname;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            Uploader.this.mUploadPath = mPath + mDirname.getText().toString();
-            Uploader.this.mCreateDir = true;
-            uploadFiles();
-        }
-    }
-
-    @Override
-    public void onBackPressed() {
-
-        if (mParents.size() <= 1) {
-            super.onBackPressed();
-            return;
-        } else {
-            mParents.pop();
-            populateDirectoryList();
-        }
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        // click on folder in the list
-        Log.d(TAG, "on item click");
-        Vector<OCFile> tmpfiles = mStorageManager.getDirectoryContent(mFile);
-        if (tmpfiles.size() <= 0) return;
-        // filter on dirtype
-        Vector<OCFile> files = new Vector<OCFile>();
-        for (OCFile f : tmpfiles)
-            if (f.isDirectory())
-                files.add(f);
-        if (files.size() < position) {
-            throw new IndexOutOfBoundsException("Incorrect item selected");
-        }
-        mParents.push(files.get(position).getFileName());
-        populateDirectoryList();
-    }
-
-    @Override
-    public void onClick(View v) {
-        // click on button
-        switch (v.getId()) {
-        case R.id.uploader_choose_folder:
-            mUploadPath = "";   // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
-            for (String p : mParents)
-                mUploadPath += p + OCFile.PATH_SEPARATOR;
-            Log.d(TAG, "Uploading file to dir " + mUploadPath);
-
-            uploadFiles();
-
-            break;
-        /*case android.R.id.button1: // dynamic action for create aditional dir
-            showDialog(DIALOG_GET_DIRNAME);
-            break;*/
-        default:
-            throw new IllegalArgumentException("Wrong element clicked");
-        }
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        Log.i(TAG, "result received. req: " + requestCode + " res: " + resultCode);
-        if (requestCode == REQUEST_CODE_SETUP_ACCOUNT) {
-            dismissDialog(DIALOG_NO_ACCOUNT);
-            if (resultCode == RESULT_CANCELED) {
-                finish();
-            }
-            Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.AUTH_TOKEN_TYPE);
-            if (accounts.length == 0) {
-                showDialog(DIALOG_NO_ACCOUNT);
-            } else {
-                // there is no need for checking for is there more then one
-                // account at this point
-                // since account setup can set only one account at time
-                mAccount = accounts[0];
-                populateDirectoryList();
-            }
-        }
-    }
-
-    private void populateDirectoryList() {
-        setContentView(R.layout.uploader_layout);
-
-        String full_path = "";
-        for (String a : mParents)
-            full_path += a + "/";
-        
-        Log.d(TAG, "Populating view with content of : " + full_path);
-        
-        mFile = mStorageManager.getFileByPath(full_path);
-        if (mFile != null) {
-            Vector<OCFile> files = mStorageManager.getDirectoryContent(mFile);
-            List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
-            for (OCFile f : files) {
-                HashMap<String, Object> h = new HashMap<String, Object>();
-                if (f.isDirectory()) {
-                    h.put("dirname", f.getFileName());
-                    data.add(h);
-                }
-            }
-            SimpleAdapter sa = new SimpleAdapter(this,
-                                                data,
-                                                R.layout.uploader_list_item_layout,
-                                                new String[] {"dirname"},
-                                                new int[] {R.id.textView1});
-            setListAdapter(sa);
-            Button btn = (Button) findViewById(R.id.uploader_choose_folder);
-            btn.setOnClickListener(this);
-            getListView().setOnItemClickListener(this);
-        }
-    }
-
-    private boolean prepareStreamsToUpload() {
-        if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
-            mStreamsToUpload = new ArrayList<Parcelable>();
-            mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
-        } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
-            mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
-        }
-        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
-    }
-
-    public void uploadFiles() {
-        try {
-            WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
-
-            // create last directory in path if necessary
-            if (mCreateDir) {
-                wdc.createDirectory(mUploadPath);
-            }
-
-            String[] local = new String[mStreamsToUpload.size()], remote = new String[mStreamsToUpload.size()];
-
-            for (int i = 0; i < mStreamsToUpload.size(); ++i) {
-                Uri uri = (Uri) mStreamsToUpload.get(i);
-                if (uri.getScheme().equals("content")) {
-                    Cursor c = getContentResolver().query((Uri) mStreamsToUpload.get(i),
-                                                      CONTENT_PROJECTION,
-                                                      null,
-                                                      null,
-                                                      null);
-
-                    if (!c.moveToFirst())
-                        continue;
-
-                    final String display_name = c.getString(c.getColumnIndex(Media.DISPLAY_NAME)),
-                                data = c.getString(c.getColumnIndex(Media.DATA));
-                    local[i] = data;
-                    remote[i] = mUploadPath + display_name;
-                } else if (uri.getScheme().equals("file")) {
-                    final File file = new File(Uri.decode(uri.toString()).replace(uri.getScheme() + "://", ""));
-                    local[i] = file.getAbsolutePath();
-                    remote[i] = mUploadPath + file.getName();
-                }
-
-            }
-            Intent intent = new Intent(getApplicationContext(), FileUploader.class);
-            intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
-            intent.putExtra(FileUploader.KEY_LOCAL_FILE, local);
-            intent.putExtra(FileUploader.KEY_REMOTE_FILE, remote);
-            intent.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
-            startService(intent);
-            finish();
-            
-        } catch (SecurityException e) {
-            String message = String.format(getString(R.string.uploader_error_forbidden_content), getString(R.string.app_name));
-            Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
-        }
-    }
-
-}
+/* 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;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.network.OwnCloudClientUtils;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.ListActivity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.MediaStore.Images.Media;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.SimpleAdapter;
+import android.widget.Toast;
+
+import com.owncloud.android.R;
+import eu.alefzero.webdav.WebdavClient;
+
+/**
+ * This can be used to upload things to an ownCloud instance.
+ * 
+ * @author Bartek Przybylski
+ * 
+ */
+public class Uploader extends ListActivity implements OnItemClickListener, android.view.View.OnClickListener {
+    private static final String TAG = "ownCloudUploader";
+
+    private Account mAccount;
+    private AccountManager mAccountManager;
+    private Stack<String> mParents;
+    private ArrayList<Parcelable> mStreamsToUpload;
+    private boolean mCreateDir;
+    private String mUploadPath;
+    private static final String[] CONTENT_PROJECTION = { Media.DATA, Media.DISPLAY_NAME, Media.MIME_TYPE, Media.SIZE };
+    private DataStorageManager mStorageManager;
+    private OCFile mFile;
+
+    private final static int DIALOG_NO_ACCOUNT = 0;
+    private final static int DIALOG_WAITING = 1;
+    private final static int DIALOG_NO_STREAM = 2;
+    private final static int DIALOG_MULTIPLE_ACCOUNT = 3;
+    //private final static int DIALOG_GET_DIRNAME = 4;
+
+    private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+        mParents = new Stack<String>();
+        mParents.add("");
+        /*if (getIntent().hasExtra(Intent.EXTRA_STREAM)) {
+            prepareStreamsToUpload();*/
+        if (prepareStreamsToUpload()) {
+            mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
+            Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE);
+            if (accounts.length == 0) {
+                Log_OC.i(TAG, "No ownCloud account is available");
+                showDialog(DIALOG_NO_ACCOUNT);
+            } else if (accounts.length > 1) {
+                Log_OC.i(TAG, "More then one ownCloud is available");
+                showDialog(DIALOG_MULTIPLE_ACCOUNT);
+            } else {
+                mAccount = accounts[0];
+                mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                populateDirectoryList();
+            }
+        } else {
+            showDialog(DIALOG_NO_STREAM);
+        }
+    }
+    
+    @Override
+    protected Dialog onCreateDialog(final int id) {
+        final AlertDialog.Builder builder = new Builder(this);
+        switch (id) {
+        case DIALOG_WAITING:
+            ProgressDialog pDialog = new ProgressDialog(this);
+            pDialog.setIndeterminate(false);
+            pDialog.setCancelable(false);
+            pDialog.setMessage(getResources().getString(R.string.uploader_info_uploading));
+            return pDialog;
+        case DIALOG_NO_ACCOUNT:
+            builder.setIcon(android.R.drawable.ic_dialog_alert);
+            builder.setTitle(R.string.uploader_wrn_no_account_title);
+            builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
+            builder.setCancelable(false);
+            builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) {
+                        // using string value since in API7 this
+                        // constatn is not defined
+                        // in API7 < this constatant is defined in
+                        // Settings.ADD_ACCOUNT_SETTINGS
+                        // and Settings.EXTRA_AUTHORITIES
+                        Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
+                        intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
+                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
+                    } else {
+                        // since in API7 there is no direct call for
+                        // account setup, so we need to
+                        // show our own AccountSetupAcricity, get
+                        // desired results and setup
+                        // everything for ourself
+                        Intent intent = new Intent(getBaseContext(), AccountAuthenticator.class);
+                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
+                    }
+                }
+            });
+            builder.setNegativeButton(R.string.uploader_wrn_no_account_quit_btn_text, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    finish();
+                }
+            });
+            return builder.create();
+        /*case DIALOG_GET_DIRNAME:
+            final EditText dirName = new EditText(getBaseContext());
+            builder.setView(dirName);
+            builder.setTitle(R.string.uploader_info_dirname);
+            String pathToUpload;
+            if (mParents.empty()) {
+                pathToUpload = "/";
+            } else {
+                mCursor = managedQuery(Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, mParents.peek()), null,
+                        null, null, null);
+                mCursor.moveToFirst();
+                pathToUpload = mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_PATH))
+                        + mCursor.getString(mCursor.getColumnIndex(ProviderTableMeta.FILE_NAME)).replace(" ", "%20");   // TODO don't make this ; use WebdavUtils.encode in the right moment
+            }
+            a a = new a(pathToUpload, dirName);
+            builder.setPositiveButton(R.string.common_ok, a);
+            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    dialog.cancel();
+                }
+            });
+            return builder.create();*/
+        case DIALOG_MULTIPLE_ACCOUNT:
+            CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE).length];
+            for (int i = 0; i < ac.length; ++i) {
+                ac[i] = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[i].name;
+            }
+            builder.setTitle(R.string.common_choose_account);
+            builder.setItems(ac, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    mAccount = mAccountManager.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE)[which];
+                    mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                    populateDirectoryList();
+                }
+            });
+            builder.setCancelable(true);
+            builder.setOnCancelListener(new OnCancelListener() {
+                @Override
+                public void onCancel(DialogInterface dialog) {
+                    dialog.cancel();
+                    finish();
+                }
+            });
+            return builder.create();
+        case DIALOG_NO_STREAM:
+            builder.setIcon(android.R.drawable.ic_dialog_alert);
+            builder.setTitle(R.string.uploader_wrn_no_content_title);
+            builder.setMessage(R.string.uploader_wrn_no_content_text);
+            builder.setCancelable(false);
+            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    finish();
+                }
+            });
+            return builder.create();
+        default:
+            throw new IllegalArgumentException("Unknown dialog id: " + id);
+        }
+    }
+
+    class a implements OnClickListener {
+        String mPath;
+        EditText mDirname;
+
+        public a(String path, EditText dirname) {
+            mPath = path; 
+            mDirname = dirname;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            Uploader.this.mUploadPath = mPath + mDirname.getText().toString();
+            Uploader.this.mCreateDir = true;
+            uploadFiles();
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+
+        if (mParents.size() <= 1) {
+            super.onBackPressed();
+            return;
+        } else {
+            mParents.pop();
+            populateDirectoryList();
+        }
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        // click on folder in the list
+        Log_OC.d(TAG, "on item click");
+        Vector<OCFile> tmpfiles = mStorageManager.getDirectoryContent(mFile);
+        if (tmpfiles.size() <= 0) return;
+        // filter on dirtype
+        Vector<OCFile> files = new Vector<OCFile>();
+        for (OCFile f : tmpfiles)
+            if (f.isDirectory())
+                files.add(f);
+        if (files.size() < position) {
+            throw new IndexOutOfBoundsException("Incorrect item selected");
+        }
+        mParents.push(files.get(position).getFileName());
+        populateDirectoryList();
+    }
+
+    @Override
+    public void onClick(View v) {
+        // click on button
+        switch (v.getId()) {
+        case R.id.uploader_choose_folder:
+            mUploadPath = "";   // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
+            for (String p : mParents)
+                mUploadPath += p + OCFile.PATH_SEPARATOR;
+            Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
+
+            uploadFiles();
+
+            break;
+        /*case android.R.id.button1: // dynamic action for create aditional dir
+            showDialog(DIALOG_GET_DIRNAME);
+            break;*/
+        default:
+            throw new IllegalArgumentException("Wrong element clicked");
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        Log_OC.i(TAG, "result received. req: " + requestCode + " res: " + resultCode);
+        if (requestCode == REQUEST_CODE_SETUP_ACCOUNT) {
+            dismissDialog(DIALOG_NO_ACCOUNT);
+            if (resultCode == RESULT_CANCELED) {
+                finish();
+            }
+            Account[] accounts = mAccountManager.getAccountsByType(AccountAuthenticator.AUTH_TOKEN_TYPE);
+            if (accounts.length == 0) {
+                showDialog(DIALOG_NO_ACCOUNT);
+            } else {
+                // there is no need for checking for is there more then one
+                // account at this point
+                // since account setup can set only one account at time
+                mAccount = accounts[0];
+                populateDirectoryList();
+            }
+        }
+    }
+
+    private void populateDirectoryList() {
+        setContentView(R.layout.uploader_layout);
+
+        String full_path = "";
+        for (String a : mParents)
+            full_path += a + "/";
+        
+        Log_OC.d(TAG, "Populating view with content of : " + full_path);
+        
+        mFile = mStorageManager.getFileByPath(full_path);
+        if (mFile != null) {
+            Vector<OCFile> files = mStorageManager.getDirectoryContent(mFile);
+            List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
+            for (OCFile f : files) {
+                HashMap<String, Object> h = new HashMap<String, Object>();
+                if (f.isDirectory()) {
+                    h.put("dirname", f.getFileName());
+                    data.add(h);
+                }
+            }
+            SimpleAdapter sa = new SimpleAdapter(this,
+                                                data,
+                                                R.layout.uploader_list_item_layout,
+                                                new String[] {"dirname"},
+                                                new int[] {R.id.textView1});
+            setListAdapter(sa);
+            Button btn = (Button) findViewById(R.id.uploader_choose_folder);
+            btn.setOnClickListener(this);
+            getListView().setOnItemClickListener(this);
+        }
+    }
+
+    private boolean prepareStreamsToUpload() {
+        if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
+            mStreamsToUpload = new ArrayList<Parcelable>();
+            mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
+        } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
+            mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+        }
+        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
+    }
+
+    public void uploadFiles() {
+        try {
+            WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
+
+            // create last directory in path if necessary
+            if (mCreateDir) {
+                wdc.createDirectory(mUploadPath);
+            }
+
+            String[] local = new String[mStreamsToUpload.size()], remote = new String[mStreamsToUpload.size()];
+
+            for (int i = 0; i < mStreamsToUpload.size(); ++i) {
+                Uri uri = (Uri) mStreamsToUpload.get(i);
+                if (uri.getScheme().equals("content")) {
+                    Cursor c = getContentResolver().query((Uri) mStreamsToUpload.get(i),
+                                                      CONTENT_PROJECTION,
+                                                      null,
+                                                      null,
+                                                      null);
+
+                    if (!c.moveToFirst())
+                        continue;
+
+                    final String display_name = c.getString(c.getColumnIndex(Media.DISPLAY_NAME)),
+                                data = c.getString(c.getColumnIndex(Media.DATA));
+                    local[i] = data;
+                    remote[i] = mUploadPath + display_name;
+                } else if (uri.getScheme().equals("file")) {
+                    final File file = new File(Uri.decode(uri.toString()).replace(uri.getScheme() + "://", ""));
+                    local[i] = file.getAbsolutePath();
+                    remote[i] = mUploadPath + file.getName();
+                }
+
+            }
+            Intent intent = new Intent(getApplicationContext(), FileUploader.class);
+            intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
+            intent.putExtra(FileUploader.KEY_LOCAL_FILE, local);
+            intent.putExtra(FileUploader.KEY_REMOTE_FILE, remote);
+            intent.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
+            startService(intent);
+            finish();
+            
+        } catch (SecurityException e) {
+            String message = String.format(getString(R.string.uploader_error_forbidden_content), getString(R.string.app_name));
+            Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
+        }
+    }
+
+}

+ 283 - 282
src/com/owncloud/android/authenticator/AccountAuthenticator.java

@@ -1,282 +1,283 @@
-/* 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.authenticator;
-
-import com.owncloud.android.ui.activity.AuthenticatorActivity;
-
-import android.accounts.*;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-public class AccountAuthenticator extends AbstractAccountAuthenticator {
-    /**
-     * Is used by android system to assign accounts to authenticators. Should be
-     * used by application and all extensions.
-     */
-    public static final String ACCOUNT_TYPE = "owncloud";
-    public static final String AUTH_TOKEN_TYPE = "org.owncloud";
-
-    public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType";
-    public static final String KEY_REQUIRED_FEATURES = "requiredFeatures";
-    public static final String KEY_LOGIN_OPTIONS = "loginOptions";
-    public static final String KEY_ACCOUNT = "account";
-    /**
-     * Value under this key should handle path to webdav php script. Will be
-     * removed and usage should be replaced by combining
-     * {@link com.owncloud.android.authenticator.AuthenticatorActivity.KEY_OC_BASE_URL} and
-     * {@link com.owncloud.android.utils.OwnCloudVersion}
-     * 
-     * @deprecated
-     */
-    public static final String KEY_OC_URL = "oc_url";
-    /**
-     * Version should be 3 numbers separated by dot so it can be parsed by
-     * {@link com.owncloud.android.utils.OwnCloudVersion}
-     */
-    public static final String KEY_OC_VERSION = "oc_version";
-    /**
-     * Base url should point to owncloud installation without trailing / ie:
-     * http://server/path or https://owncloud.server
-     */
-    public static final String KEY_OC_BASE_URL = "oc_base_url";
-
-    private static final String TAG = "AccountAuthenticator";
-    private Context mContext;
-
-    public AccountAuthenticator(Context context) {
-        super(context);
-        mContext = context;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Bundle addAccount(AccountAuthenticatorResponse response,
-            String accountType, String authTokenType,
-            String[] requiredFeatures, Bundle options)
-            throws NetworkErrorException {
-        Log.i(TAG, "Adding account with type " + accountType
-                + " and auth token " + authTokenType);
-        try {
-            validateAccountType(accountType);
-        } catch (AuthenticatorException e) {
-            Log.e(TAG, "Failed to validate account type " + accountType + ": "
-                    + e.getMessage());
-            e.printStackTrace();
-            return e.getFailureBundle();
-        }
-        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
-        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
-        intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
-        intent.putExtra(KEY_LOGIN_OPTIONS, options);
-
-        setIntentFlags(intent);
-        final Bundle bundle = new Bundle();
-        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
-        return bundle;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Bundle confirmCredentials(AccountAuthenticatorResponse response,
-            Account account, Bundle options) throws NetworkErrorException {
-        try {
-            validateAccountType(account.type);
-        } catch (AuthenticatorException e) {
-            Log.e(TAG, "Failed to validate account type " + account.type + ": "
-                    + e.getMessage());
-            e.printStackTrace();
-            return e.getFailureBundle();
-        }
-        Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
-        intent.putExtra(KEY_ACCOUNT, account);
-        intent.putExtra(KEY_LOGIN_OPTIONS, options);
-
-        setIntentFlags(intent);
-
-        Bundle resultBundle = new Bundle();
-        resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
-        return resultBundle;
-    }
-
-    @Override
-    public Bundle editProperties(AccountAuthenticatorResponse response,
-            String accountType) {
-        return null;
-    }
-
-    @Override
-    public Bundle getAuthToken(AccountAuthenticatorResponse response,
-            Account account, String authTokenType, Bundle options)
-            throws NetworkErrorException {
-        try {
-            validateAccountType(account.type);
-            validateAuthTokenType(authTokenType);
-        } catch (AuthenticatorException e) {
-            Log.e(TAG, "Failed to validate account type " + account.type + ": "
-                    + e.getMessage());
-            e.printStackTrace();
-            return e.getFailureBundle();
-        }
-        final AccountManager am = AccountManager.get(mContext);
-        final String password = am.getPassword(account);
-        if (password != null) {
-            final Bundle result = new Bundle();
-            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
-            result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
-            result.putString(AccountManager.KEY_AUTHTOKEN, password);
-            return result;
-        }
-
-        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
-        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
-        intent.putExtra(KEY_LOGIN_OPTIONS, options);
-        intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
-
-        final Bundle bundle = new Bundle();
-        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
-        return bundle;
-    }
-
-    @Override
-    public String getAuthTokenLabel(String authTokenType) {
-        return null;
-    }
-
-    @Override
-    public Bundle hasFeatures(AccountAuthenticatorResponse response,
-            Account account, String[] features) throws NetworkErrorException {
-        final Bundle result = new Bundle();
-        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
-        return result;
-    }
-
-    @Override
-    public Bundle updateCredentials(AccountAuthenticatorResponse response,
-            Account account, String authTokenType, Bundle options)
-            throws NetworkErrorException {
-        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
-        intent.putExtra(KEY_ACCOUNT, account);
-        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
-        intent.putExtra(KEY_LOGIN_OPTIONS, options);
-        setIntentFlags(intent);
-
-        final Bundle bundle = new Bundle();
-        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
-        return bundle;
-    }
-
-    @Override
-    public Bundle getAccountRemovalAllowed(
-            AccountAuthenticatorResponse response, Account account)
-            throws NetworkErrorException {
-        return super.getAccountRemovalAllowed(response, account);
-    }
-
-    private void setIntentFlags(Intent intent) {
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
-        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
-    }
-
-    private void validateAccountType(String type)
-            throws UnsupportedAccountTypeException {
-        if (!type.equals(ACCOUNT_TYPE)) {
-            throw new UnsupportedAccountTypeException();
-        }
-    }
-
-    private void validateAuthTokenType(String authTokenType)
-            throws UnsupportedAuthTokenTypeException {
-        if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
-            throw new UnsupportedAuthTokenTypeException();
-        }
-    }
-
-    public static class AuthenticatorException extends Exception {
-        private static final long serialVersionUID = 1L;
-        private Bundle mFailureBundle;
-
-        public AuthenticatorException(int code, String errorMsg) {
-            mFailureBundle = new Bundle();
-            mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
-            mFailureBundle
-                    .putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
-        }
-
-        public Bundle getFailureBundle() {
-            return mFailureBundle;
-        }
-    }
-
-    public static class UnsupportedAccountTypeException extends
-            AuthenticatorException {
-        private static final long serialVersionUID = 1L;
-
-        public UnsupportedAccountTypeException() {
-            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                    "Unsupported account type");
-        }
-    }
-
-    public static class UnsupportedAuthTokenTypeException extends
-            AuthenticatorException {
-        private static final long serialVersionUID = 1L;
-
-        public UnsupportedAuthTokenTypeException() {
-            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                    "Unsupported auth token type");
-        }
-    }
-
-    public static class UnsupportedFeaturesException extends
-            AuthenticatorException {
-        public static final long serialVersionUID = 1L;
-
-        public UnsupportedFeaturesException() {
-            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
-                    "Unsupported features");
-        }
-    }
-
-    public static class AccessDeniedException extends AuthenticatorException {
-        public AccessDeniedException(int code, String errorMsg) {
-            super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
-        }
-
-        private static final long serialVersionUID = 1L;
-
-    }
-}
+/* 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.authenticator;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.ui.activity.AuthenticatorActivity;
+
+import android.accounts.*;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class AccountAuthenticator extends AbstractAccountAuthenticator {
+    /**
+     * Is used by android system to assign accounts to authenticators. Should be
+     * used by application and all extensions.
+     */
+    public static final String ACCOUNT_TYPE = "owncloud";
+    public static final String AUTH_TOKEN_TYPE = "org.owncloud";
+
+    public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType";
+    public static final String KEY_REQUIRED_FEATURES = "requiredFeatures";
+    public static final String KEY_LOGIN_OPTIONS = "loginOptions";
+    public static final String KEY_ACCOUNT = "account";
+    /**
+     * Value under this key should handle path to webdav php script. Will be
+     * removed and usage should be replaced by combining
+     * {@link com.owncloud.android.authenticator.AuthenticatorActivity.KEY_OC_BASE_URL} and
+     * {@link com.owncloud.android.utils.OwnCloudVersion}
+     * 
+     * @deprecated
+     */
+    public static final String KEY_OC_URL = "oc_url";
+    /**
+     * Version should be 3 numbers separated by dot so it can be parsed by
+     * {@link com.owncloud.android.utils.OwnCloudVersion}
+     */
+    public static final String KEY_OC_VERSION = "oc_version";
+    /**
+     * Base url should point to owncloud installation without trailing / ie:
+     * http://server/path or https://owncloud.server
+     */
+    public static final String KEY_OC_BASE_URL = "oc_base_url";
+
+    private static final String TAG = "AccountAuthenticator";
+    private Context mContext;
+
+    public AccountAuthenticator(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Bundle addAccount(AccountAuthenticatorResponse response,
+            String accountType, String authTokenType,
+            String[] requiredFeatures, Bundle options)
+            throws NetworkErrorException {
+        Log_OC.i(TAG, "Adding account with type " + accountType
+                + " and auth token " + authTokenType);
+        try {
+            validateAccountType(accountType);
+        } catch (AuthenticatorException e) {
+            Log_OC.e(TAG, "Failed to validate account type " + accountType + ": "
+                    + e.getMessage());
+            e.printStackTrace();
+            return e.getFailureBundle();
+        }
+        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
+                response);
+        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
+        intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
+        intent.putExtra(KEY_LOGIN_OPTIONS, options);
+
+        setIntentFlags(intent);
+        final Bundle bundle = new Bundle();
+        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
+        return bundle;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Bundle confirmCredentials(AccountAuthenticatorResponse response,
+            Account account, Bundle options) throws NetworkErrorException {
+        try {
+            validateAccountType(account.type);
+        } catch (AuthenticatorException e) {
+            Log_OC.e(TAG, "Failed to validate account type " + account.type + ": "
+                    + e.getMessage());
+            e.printStackTrace();
+            return e.getFailureBundle();
+        }
+        Intent intent = new Intent(mContext, AuthenticatorActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
+                response);
+        intent.putExtra(KEY_ACCOUNT, account);
+        intent.putExtra(KEY_LOGIN_OPTIONS, options);
+
+        setIntentFlags(intent);
+
+        Bundle resultBundle = new Bundle();
+        resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
+        return resultBundle;
+    }
+
+    @Override
+    public Bundle editProperties(AccountAuthenticatorResponse response,
+            String accountType) {
+        return null;
+    }
+
+    @Override
+    public Bundle getAuthToken(AccountAuthenticatorResponse response,
+            Account account, String authTokenType, Bundle options)
+            throws NetworkErrorException {
+        try {
+            validateAccountType(account.type);
+            validateAuthTokenType(authTokenType);
+        } catch (AuthenticatorException e) {
+            Log_OC.e(TAG, "Failed to validate account type " + account.type + ": "
+                    + e.getMessage());
+            e.printStackTrace();
+            return e.getFailureBundle();
+        }
+        final AccountManager am = AccountManager.get(mContext);
+        final String password = am.getPassword(account);
+        if (password != null) {
+            final Bundle result = new Bundle();
+            result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
+            result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
+            result.putString(AccountManager.KEY_AUTHTOKEN, password);
+            return result;
+        }
+
+        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
+                response);
+        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
+        intent.putExtra(KEY_LOGIN_OPTIONS, options);
+        intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
+
+        final Bundle bundle = new Bundle();
+        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
+        return bundle;
+    }
+
+    @Override
+    public String getAuthTokenLabel(String authTokenType) {
+        return null;
+    }
+
+    @Override
+    public Bundle hasFeatures(AccountAuthenticatorResponse response,
+            Account account, String[] features) throws NetworkErrorException {
+        final Bundle result = new Bundle();
+        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+        return result;
+    }
+
+    @Override
+    public Bundle updateCredentials(AccountAuthenticatorResponse response,
+            Account account, String authTokenType, Bundle options)
+            throws NetworkErrorException {
+        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
+                response);
+        intent.putExtra(KEY_ACCOUNT, account);
+        intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
+        intent.putExtra(KEY_LOGIN_OPTIONS, options);
+        setIntentFlags(intent);
+
+        final Bundle bundle = new Bundle();
+        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
+        return bundle;
+    }
+
+    @Override
+    public Bundle getAccountRemovalAllowed(
+            AccountAuthenticatorResponse response, Account account)
+            throws NetworkErrorException {
+        return super.getAccountRemovalAllowed(response, account);
+    }
+
+    private void setIntentFlags(Intent intent) {
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
+    }
+
+    private void validateAccountType(String type)
+            throws UnsupportedAccountTypeException {
+        if (!type.equals(ACCOUNT_TYPE)) {
+            throw new UnsupportedAccountTypeException();
+        }
+    }
+
+    private void validateAuthTokenType(String authTokenType)
+            throws UnsupportedAuthTokenTypeException {
+        if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
+            throw new UnsupportedAuthTokenTypeException();
+        }
+    }
+
+    public static class AuthenticatorException extends Exception {
+        private static final long serialVersionUID = 1L;
+        private Bundle mFailureBundle;
+
+        public AuthenticatorException(int code, String errorMsg) {
+            mFailureBundle = new Bundle();
+            mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
+            mFailureBundle
+                    .putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
+        }
+
+        public Bundle getFailureBundle() {
+            return mFailureBundle;
+        }
+    }
+
+    public static class UnsupportedAccountTypeException extends
+            AuthenticatorException {
+        private static final long serialVersionUID = 1L;
+
+        public UnsupportedAccountTypeException() {
+            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
+                    "Unsupported account type");
+        }
+    }
+
+    public static class UnsupportedAuthTokenTypeException extends
+            AuthenticatorException {
+        private static final long serialVersionUID = 1L;
+
+        public UnsupportedAuthTokenTypeException() {
+            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
+                    "Unsupported auth token type");
+        }
+    }
+
+    public static class UnsupportedFeaturesException extends
+            AuthenticatorException {
+        public static final long serialVersionUID = 1L;
+
+        public UnsupportedFeaturesException() {
+            super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
+                    "Unsupported features");
+        }
+    }
+
+    public static class AccessDeniedException extends AuthenticatorException {
+        public AccessDeniedException(int code, String errorMsg) {
+            super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
+        }
+
+        private static final long serialVersionUID = 1L;
+
+    }
+}

+ 12 - 11
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.List;
 import java.util.Vector;
 import java.util.Vector;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.FileStorageUtils;
@@ -156,7 +157,7 @@ public class FileDataStorageManager implements DataStorageManager {
                             cv, ProviderTableMeta._ID + "=?",
                             cv, ProviderTableMeta._ID + "=?",
                             new String[] { String.valueOf(file.getFileId()) });
                             new String[] { String.valueOf(file.getFileId()) });
                 } catch (RemoteException e) {
                 } catch (RemoteException e) {
-                    Log.e(TAG,
+                    Log_OC.e(TAG,
                             "Fail to insert insert file to database "
                             "Fail to insert insert file to database "
                                     + e.getMessage());
                                     + e.getMessage());
                 }
                 }
@@ -171,7 +172,7 @@ public class FileDataStorageManager implements DataStorageManager {
                     result_uri = getContentProvider().insert(
                     result_uri = getContentProvider().insert(
                             ProviderTableMeta.CONTENT_URI_FILE, cv);
                             ProviderTableMeta.CONTENT_URI_FILE, cv);
                 } catch (RemoteException e) {
                 } catch (RemoteException e) {
-                    Log.e(TAG,
+                    Log_OC.e(TAG,
                             "Fail to insert insert file to database "
                             "Fail to insert insert file to database "
                                     + e.getMessage());
                                     + e.getMessage());
                 }
                 }
@@ -256,10 +257,10 @@ public class FileDataStorageManager implements DataStorageManager {
             }
             }
             
             
         } catch (OperationApplicationException e) {
         } 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) {
         } 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
         // update new id in file objects for insertions
@@ -269,7 +270,7 @@ public class FileDataStorageManager implements DataStorageManager {
                 if (results[i].uri != null) {
                 if (results[i].uri != null) {
                     newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
                     newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
                     files.get(i).setFileId(newId);
                     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());
                 }
                 }
             }
             }
         }
         }
@@ -321,7 +322,7 @@ public class FileDataStorageManager implements DataStorageManager {
                             ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                             ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                             new String[] { mAccount.name }, null);
                             new String[] { mAccount.name }, null);
                 } catch (RemoteException e) {
                 } catch (RemoteException e) {
-                    Log.e(TAG, e.getMessage());
+                    Log_OC.e(TAG, e.getMessage());
                     return ret;
                     return ret;
                 }
                 }
             } else {
             } else {
@@ -364,7 +365,7 @@ public class FileDataStorageManager implements DataStorageManager {
                                 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                                 + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
                         new String[] { value, mAccount.name }, null);
                         new String[] { value, mAccount.name }, null);
             } catch (RemoteException e) {
             } catch (RemoteException e) {
-                Log.e(TAG,
+                Log_OC.e(TAG,
                         "Couldn't determine file existance, assuming non existance: "
                         "Couldn't determine file existance, assuming non existance: "
                                 + e.getMessage());
                                 + e.getMessage());
                 return false;
                 return false;
@@ -394,7 +395,7 @@ public class FileDataStorageManager implements DataStorageManager {
                                 + "=?", new String[] { value, mAccount.name },
                                 + "=?", new String[] { value, mAccount.name },
                         null);
                         null);
             } catch (RemoteException e) {
             } 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;
                 c = null;
             }
             }
         }
         }
@@ -517,7 +518,7 @@ public class FileDataStorageManager implements DataStorageManager {
                                                     ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
                                                     ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
                                                     new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
                                                     new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
                 } catch (RemoteException e) {
                 } catch (RemoteException e) {
-                    Log.e(TAG, e.getMessage());
+                    Log_OC.e(TAG, e.getMessage());
                 }
                 }
             } else {
             } else {
                 c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
                 c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
@@ -558,10 +559,10 @@ public class FileDataStorageManager implements DataStorageManager {
                 }
                 }
                 
                 
             } catch (OperationApplicationException e) {
             } 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) {
             } 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);
             }
             }
             
             
         }
         }

+ 4 - 5
src/com/owncloud/android/datamodel/OCFile.java

@@ -21,11 +21,10 @@ package com.owncloud.android.datamodel;
 
 
 import java.io.File;
 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.Parcel;
 import android.os.Parcelable;
 import android.os.Parcelable;
-import android.util.Log;
 import android.webkit.MimeTypeMap;
 import android.webkit.MimeTypeMap;
 
 
 public class OCFile implements Parcelable, Comparable<OCFile> {
 public class OCFile implements Parcelable, Comparable<OCFile> {
@@ -265,7 +264,7 @@ 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 
      * Does nothing if the new name is null, empty or includes "/" ; or if the file is the root directory 
      */
      */
     public void setFileName(String name) {
     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)) {
         if (name != null && name.length() > 0 && !name.contains(PATH_SEPARATOR) && !mRemotePath.equals(PATH_SEPARATOR)) {
             String parent = (new File(getRemotePath())).getParent();
             String parent = (new File(getRemotePath())).getParent();
             parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
             parent = (parent.endsWith(PATH_SEPARATOR)) ? parent : parent + PATH_SEPARATOR;
@@ -273,7 +272,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
             if (isDirectory()) {
             if (isDirectory()) {
                 mRemotePath += PATH_SEPARATOR;
                 mRemotePath += PATH_SEPARATOR;
             }
             }
-            Log.d(TAG, "OCFile name changed to " + mRemotePath);
+            Log_OC.d(TAG, "OCFile name changed to " + mRemotePath);
         }
         }
     }
     }
 
 

+ 5 - 3
src/com/owncloud/android/db/DbHandler.java

@@ -17,6 +17,8 @@
  */
  */
 package com.owncloud.android.db;
 package com.owncloud.android.db;
 
 
+import com.owncloud.android.Log_OC;
+
 import android.content.ContentValues;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.Cursor;
@@ -57,7 +59,7 @@ public class DbHandler {
         cv.put("attempt", UPLOAD_STATUS_UPLOAD_LATER);
         cv.put("attempt", UPLOAD_STATUS_UPLOAD_LATER);
         cv.put("message", message);
         cv.put("message", message);
         long result = mDB.insert(TABLE_INSTANT_UPLOAD, null, cv);
         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;
         return result != -1;
     }
     }
 
 
@@ -66,7 +68,7 @@ public class DbHandler {
         cv.put("attempt", status);
         cv.put("attempt", status);
         cv.put("message", message);
         cv.put("message", message);
         int result = mDB.update(TABLE_INSTANT_UPLOAD, cv, "path=?", new String[] { filepath });
         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;
         return result;
     }
     }
 
 
@@ -89,7 +91,7 @@ public class DbHandler {
      */
      */
     public boolean removeIUPendingFile(String localPath) {
     public boolean removeIUPendingFile(String localPath) {
         long result = mDB.delete(TABLE_INSTANT_UPLOAD, "path = ?", new 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;
         return result != 0;
 
 
     }
     }

+ 2 - 1
src/com/owncloud/android/extensions/ExtensionsAvailableDialog.java

@@ -19,6 +19,7 @@
 
 
 package com.owncloud.android.extensions;
 package com.owncloud.android.extensions;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import android.content.Intent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Bundle;
@@ -62,7 +63,7 @@ public class ExtensionsAvailableDialog extends DialogFragment implements
             getActivity().finish();
             getActivity().finish();
             break;
             break;
         default:
         default:
-            Log.e("EAD", "Button with unknown id clicked " + v.getId());
+            Log_OC.e("EAD", "Button with unknown id clicked " + v.getId());
         }
         }
     }
     }
 
 

+ 2 - 1
src/com/owncloud/android/extensions/ExtensionsListActivity.java

@@ -28,6 +28,7 @@ import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONObject;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.utils.OwnCloudVersion;
 import com.owncloud.android.utils.OwnCloudVersion;
 
 
 
 
@@ -81,7 +82,7 @@ public class ExtensionsListActivity extends ListActivity {
             final JSONArray ar;
             final JSONArray ar;
             try {
             try {
                 hc.executeMethod(gm);
                 hc.executeMethod(gm);
-                Log.e("ASD", gm.getResponseBodyAsString() + "");
+                Log_OC.e("ASD", gm.getResponseBodyAsString() + "");
                 ar = new JSONObject(gm.getResponseBodyAsString())
                 ar = new JSONObject(gm.getResponseBodyAsString())
                         .getJSONArray("apps");
                         .getJSONArray("apps");
             } catch (Exception e) {
             } catch (Exception e) {

+ 4 - 3
src/com/owncloud/android/files/BootupBroadcastReceiver.java

@@ -19,6 +19,7 @@
 
 
 package com.owncloud.android.files;
 package com.owncloud.android.files;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileObserverService;
 
 
 import android.content.BroadcastReceiver;
 import android.content.BroadcastReceiver;
@@ -33,15 +34,15 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
     @Override
     @Override
     public void onReceive(Context context, Intent intent) {
     public void onReceive(Context context, Intent intent) {
         if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
         if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
-            Log.wtf(TAG, "Incorrect action sent " + intent.getAction());
+            Log_OC.wtf(TAG, "Incorrect action sent " + intent.getAction());
             return;
             return;
         }
         }
-        Log.d(TAG, "Starting file observer service...");
+        Log_OC.d(TAG, "Starting file observer service...");
         Intent i = new Intent(context, FileObserverService.class);
         Intent i = new Intent(context, FileObserverService.class);
         i.putExtra(FileObserverService.KEY_FILE_CMD,
         i.putExtra(FileObserverService.KEY_FILE_CMD,
                    FileObserverService.CMD_INIT_OBSERVED_LIST);
                    FileObserverService.CMD_INIT_OBSERVED_LIST);
         context.startService(i);
         context.startService(i);
-        Log.d(TAG, "DONE");
+        Log_OC.d(TAG, "DONE");
     }
     }
 
 
 }
 }

+ 11 - 10
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java

@@ -35,6 +35,7 @@ import android.util.Log;
 import android.webkit.MimeTypeMap;
 import android.webkit.MimeTypeMap;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader;
@@ -48,7 +49,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
 
 
     @Override
     @Override
     public void onReceive(Context context, Intent intent) {
     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)) {
         if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION)) {
             handleConnectivityAction(context, intent);
             handleConnectivityAction(context, intent);
         } else if (intent.getAction().equals(NEW_PHOTO_ACTION)) {
         } else if (intent.getAction().equals(NEW_PHOTO_ACTION)) {
@@ -56,7 +57,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
         } else if (intent.getAction().equals(FileUploader.UPLOAD_FINISH_MESSAGE)) {
         } else if (intent.getAction().equals(FileUploader.UPLOAD_FINISH_MESSAGE)) {
             handleUploadFinished(context, intent);
             handleUploadFinished(context, intent);
         } else {
         } else {
-            Log.e(TAG, "Incorrect intent sent: " + intent.getAction());
+            Log_OC.e(TAG, "Incorrect intent sent: " + intent.getAction());
         }
         }
     }
     }
 
 
@@ -66,7 +67,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
             DbHandler db = new DbHandler(context);
             DbHandler db = new DbHandler(context);
             String localPath = intent.getStringExtra(FileUploader.EXTRA_OLD_FILE_PATH);
             String localPath = intent.getStringExtra(FileUploader.EXTRA_OLD_FILE_PATH);
             if (!db.removeIUPendingFile(localPath)) {
             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();
             db.close();
         }
         }
@@ -74,20 +75,20 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
 
 
     private void handleNewPhotoAction(Context context, Intent intent) {
     private void handleNewPhotoAction(Context context, Intent intent) {
         if (!instantUploadEnabled(context)) {
         if (!instantUploadEnabled(context)) {
-            Log.d(TAG, "Instant upload disabled, abording uploading");
+            Log_OC.d(TAG, "Instant upload disabled, abording uploading");
             return;
             return;
         }
         }
 
 
         Account account = AccountUtils.getCurrentOwnCloudAccount(context);
         Account account = AccountUtils.getCurrentOwnCloudAccount(context);
         if (account == null) {
         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;
             return;
         }
         }
 
 
         Cursor c = context.getContentResolver().query(intent.getData(), CONTENT_PROJECTION, null, null, null);
         Cursor c = context.getContentResolver().query(intent.getData(), CONTENT_PROJECTION, null, null, null);
 
 
         if (!c.moveToFirst()) {
         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;
             return;
         }
         }
 
 
@@ -96,7 +97,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
         String mime_type = c.getString(c.getColumnIndex(Media.MIME_TYPE));
         String mime_type = c.getString(c.getColumnIndex(Media.MIME_TYPE));
 
 
         c.close();
         c.close();
-        Log.e(TAG, file_path + "");
+        Log_OC.e(TAG, file_path + "");
 
 
         // same always temporally the picture to upload
         // same always temporally the picture to upload
         DbHandler db = new DbHandler(context);
         DbHandler db = new DbHandler(context);
@@ -131,7 +132,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
 
 
     private void handleConnectivityAction(Context context, Intent intent) {
     private void handleConnectivityAction(Context context, Intent intent) {
         if (!instantUploadEnabled(context)) {
         if (!instantUploadEnabled(context)) {
-            Log.d(TAG, "Instant upload disabled, abording uploading");
+            Log_OC.d(TAG, "Instant upload disabled, abording uploading");
             return;
             return;
         }
         }
 
 
@@ -156,7 +157,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
                                     f.getName().substring(f.getName().lastIndexOf('.') + 1));
                                     f.getName().substring(f.getName().lastIndexOf('.') + 1));
 
 
                         } catch (Throwable e) {
                         } 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)
                         if (mimeType == null)
                             mimeType = "application/octet-stream";
                             mimeType = "application/octet-stream";
@@ -170,7 +171,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
                         context.startService(i);
                         context.startService(i);
 
 
                     } else {
                     } 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());
                 } while (c.moveToNext());
             }
             }

+ 3 - 2
src/com/owncloud/android/files/OwnCloudFileObserver.java

@@ -21,6 +21,7 @@ package com.owncloud.android.files;
 
 
 import java.io.File;
 import java.io.File;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.network.OwnCloudClientUtils;
 import com.owncloud.android.network.OwnCloudClientUtils;
@@ -71,9 +72,9 @@ public class OwnCloudFileObserver extends FileObserver {
     
     
     @Override
     @Override
     public void onEvent(int event, String path) {
     public void onEvent(int event, String path) {
-        Log.d(TAG, "Got file modified with event " + event + " and path " + mPath + ((path != null) ? File.separator + path : ""));
+        Log_OC.d(TAG, "Got file modified with event " + event + " and path " + mPath + ((path != null) ? File.separator + path : ""));
         if ((event & mMask) == 0) {
         if ((event & mMask) == 0) {
-            Log.wtf(TAG, "Incorrect event " + event + " sent for file " + mPath + ((path != null) ? File.separator + path : "") +
+            Log_OC.wtf(TAG, "Incorrect event " + event + " sent for file " + mPath + ((path != null) ? File.separator + path : "") +
                          " with registered for " + mMask + " and original path " +
                          " with registered for " + mMask + " and original path " +
                          mPath);
                          mPath);
             return;
             return;

+ 510 - 511
src/com/owncloud/android/files/services/FileDownloader.java

@@ -1,511 +1,510 @@
-/* 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.AccountUtils;
-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.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.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 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 = 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;
-            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(EXTRA_FILE_PATH, download.getSavePath());
-        sendStickyBroadcast(added);
-    }
-
-}
+/* 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.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 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 = 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;
+            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(EXTRA_FILE_PATH, download.getSavePath());
+        sendStickyBroadcast(added);
+    }
+
+}

+ 12 - 11
src/com/owncloud/android/files/services/FileObserverService.java

@@ -23,6 +23,7 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
@@ -83,7 +84,7 @@ public class FileObserverService extends Service {
         super.onDestroy();
         super.onDestroy();
         unregisterReceiver(mDownloadReceiver);
         unregisterReceiver(mDownloadReceiver);
         mObserversMap = null;   // TODO study carefully the life cycle of Services to grant the best possible observance
         mObserversMap = null;   // TODO study carefully the life cycle of Services to grant the best possible observance
-        Log.d(TAG, "Bye, bye");
+        Log_OC.d(TAG, "Bye, bye");
     }
     }
     
     
     
     
@@ -102,7 +103,7 @@ public class FileObserverService extends Service {
         }
         }
             
             
         if (!intent.hasExtra(KEY_FILE_CMD)) {
         if (!intent.hasExtra(KEY_FILE_CMD)) {
-            Log.e(TAG, "No KEY_FILE_CMD argument given");
+            Log_OC.e(TAG, "No KEY_FILE_CMD argument given");
             return Service.START_STICKY;
             return Service.START_STICKY;
         }
         }
 
 
@@ -119,7 +120,7 @@ public class FileObserverService extends Service {
                                     (Account)intent.getParcelableExtra(KEY_CMD_ARG_ACCOUNT));
                                     (Account)intent.getParcelableExtra(KEY_CMD_ARG_ACCOUNT));
                 break;
                 break;
             default:
             default:
-                Log.wtf(TAG, "Incorrect key given");
+                Log_OC.wtf(TAG, "Incorrect key given");
         }
         }
 
 
         return Service.START_STICKY;
         return Service.START_STICKY;
@@ -166,7 +167,7 @@ public class FileObserverService extends Service {
             mObserversMap.put(path, observer);
             mObserversMap.put(path, observer);
             if (new File(path).exists()) {
             if (new File(path).exists()) {
                 observer.startWatching();
                 observer.startWatching();
-                Log.d(TAG, "Started watching file " + path);
+                Log_OC.d(TAG, "Started watching file " + path);
             }
             }
             
             
         } while (c.moveToNext());
         } while (c.moveToNext());
@@ -189,7 +190,7 @@ public class FileObserverService extends Service {
      */
      */
     private void addObservedFile(OCFile file, Account account) {
     private void addObservedFile(OCFile file, Account account) {
         if (file == null) {
         if (file == null) {
-            Log.e(TAG, "Trying to add a NULL file to observer");
+            Log_OC.e(TAG, "Trying to add a NULL file to observer");
             return;
             return;
         }
         }
         String localPath = file.getStoragePath();
         String localPath = file.getStoragePath();
@@ -204,11 +205,11 @@ public class FileObserverService extends Service {
                                                     getApplicationContext(), 
                                                     getApplicationContext(), 
                                                     OwnCloudFileObserver.CHANGES_ONLY);
                                                     OwnCloudFileObserver.CHANGES_ONLY);
             mObserversMap.put(localPath, observer);
             mObserversMap.put(localPath, observer);
-            Log.d(TAG, "Observer added for path " + localPath);
+            Log_OC.d(TAG, "Observer added for path " + localPath);
         
         
             if (file.isDown()) {
             if (file.isDown()) {
                 observer.startWatching();
                 observer.startWatching();
-                Log.d(TAG, "Started watching " + localPath);
+                Log_OC.d(TAG, "Started watching " + localPath);
             }   // else - the observance can't be started on a file not already down; mDownloadReceiver will get noticed when the download of the file finishes
             }   // else - the observance can't be started on a file not already down; mDownloadReceiver will get noticed when the download of the file finishes
         }
         }
         
         
@@ -229,7 +230,7 @@ public class FileObserverService extends Service {
      */
      */
     private void removeObservedFile(OCFile file, Account account) {
     private void removeObservedFile(OCFile file, Account account) {
         if (file == null) {
         if (file == null) {
-            Log.e(TAG, "Trying to remove a NULL file");
+            Log_OC.e(TAG, "Trying to remove a NULL file");
             return;
             return;
         }
         }
         String localPath = file.getStoragePath();
         String localPath = file.getStoragePath();
@@ -241,7 +242,7 @@ public class FileObserverService extends Service {
         if (observer != null) {
         if (observer != null) {
             observer.stopWatching();
             observer.stopWatching();
             mObserversMap.remove(observer);
             mObserversMap.remove(observer);
-            Log.d(TAG, "Stopped watching " + localPath);
+            Log_OC.d(TAG, "Stopped watching " + localPath);
         }
         }
         
         
     }
     }
@@ -263,11 +264,11 @@ public class FileObserverService extends Service {
                 if (intent.getAction().equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE) &&
                 if (intent.getAction().equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE) &&
                         new File(downloadPath).exists()) {  // the download could be successful, or not; in both cases, the file could be down, due to a former download or upload   
                         new File(downloadPath).exists()) {  // the download could be successful, or not; in both cases, the file could be down, due to a former download or upload   
                     observer.startWatching();
                     observer.startWatching();
-                    Log.d(TAG, "Watching again " + downloadPath);
+                    Log_OC.d(TAG, "Watching again " + downloadPath);
                 
                 
                 } else if (intent.getAction().equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
                 } else if (intent.getAction().equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
                     observer.stopWatching();
                     observer.stopWatching();
-                    Log.d(TAG, "Disabling observance of " + downloadPath);
+                    Log_OC.d(TAG, "Disabling observance of " + downloadPath);
                 } 
                 } 
             }
             }
         }
         }

+ 18 - 17
src/com/owncloud/android/files/services/FileUploader.java

@@ -51,6 +51,7 @@ import android.webkit.MimeTypeMap;
 import android.widget.RemoteViews;
 import android.widget.RemoteViews;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -151,7 +152,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     @Override
     @Override
     public void onCreate() {
     public void onCreate() {
         super.onCreate();
         super.onCreate();
-        Log.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
+        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
         HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND);
         HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND);
         thread.start();
         thread.start();
@@ -171,12 +172,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
     public int onStartCommand(Intent intent, int flags, int startId) {
     public int onStartCommand(Intent intent, int flags, int startId) {
         if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE)
         if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE)
                 || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
                 || !(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;
             return Service.START_NOT_STICKY;
         }
         }
         int uploadType = intent.getIntExtra(KEY_UPLOAD_TYPE, -1);
         int uploadType = intent.getIntExtra(KEY_UPLOAD_TYPE, -1);
         if (uploadType == -1) {
         if (uploadType == -1) {
-            Log.e(TAG, "Incorrect upload type provided");
+            Log_OC.e(TAG, "Incorrect upload type provided");
             return Service.START_NOT_STICKY;
             return Service.START_NOT_STICKY;
         }
         }
         Account account = intent.getParcelableExtra(KEY_ACCOUNT);
         Account account = intent.getParcelableExtra(KEY_ACCOUNT);
@@ -227,20 +228,20 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         }
         }
 
 
         if (intent.hasExtra(KEY_FILE) && files == null) {
         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;
             return Service.START_NOT_STICKY;
 
 
         } else if (!intent.hasExtra(KEY_FILE)) {
         } else if (!intent.hasExtra(KEY_FILE)) {
             if (localPaths == null) {
             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;
                 return Service.START_NOT_STICKY;
             }
             }
             if (remotePaths == null) {
             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;
                 return Service.START_NOT_STICKY;
             }
             }
             if (localPaths.length != remotePaths.length) {
             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;
                 return Service.START_NOT_STICKY;
             }
             }
 
 
@@ -280,15 +281,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             }
             }
 
 
         } catch (IllegalArgumentException e) {
         } 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;
             return START_NOT_STICKY;
 
 
         } catch (IllegalStateException e) {
         } 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;
             return START_NOT_STICKY;
 
 
         } catch (Exception e) {
         } 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;
             return START_NOT_STICKY;
 
 
         }
         }
@@ -299,7 +300,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             msg.obj = requestedUploads;
             msg.obj = requestedUploads;
             mServiceHandler.sendMessage(msg);
             mServiceHandler.sendMessage(msg);
         }
         }
-        Log.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
+        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
         return Service.START_NOT_STICKY;
         return Service.START_NOT_STICKY;
     }
     }
 
 
@@ -516,7 +517,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             } finally {
             } finally {
                 synchronized (mPendingUploads) {
                 synchronized (mPendingUploads) {
                     mPendingUploads.remove(uploadKey);
                     mPendingUploads.remove(uploadKey);
-                    Log.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
+                    Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
                 }
                 }
             }
             }
 
 
@@ -562,12 +563,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             }
             }
 
 
             result = new RemoteOperationResult(isMultiStatus, status);
             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());
                     + result.getLogMessage());
 
 
         } catch (Exception e) {
         } catch (Exception e) {
             result = new RemoteOperationResult(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);
                     + result.getLogMessage(), e);
 
 
         } finally {
         } finally {
@@ -642,7 +643,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                 mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                         remotePath.substring(remotePath.lastIndexOf('.') + 1));
                         remotePath.substring(remotePath.lastIndexOf('.') + 1));
             } catch (IndexOutOfBoundsException e) {
             } 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) {
         if (mimeType == null) {
@@ -736,7 +737,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      * @param upload Finished upload operation
      * @param upload Finished upload operation
      */
      */
     private void notifyUploadResult(RemoteOperationResult uploadResult, UploadFileOperation upload) {
     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()) {
         if (uploadResult.isCancelled()) {
             // / cancelled operation -> silent removal of progress notification
             // / cancelled operation -> silent removal of progress notification
             mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
             mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
@@ -817,7 +818,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 try {
                 try {
                     db = new DbHandler(this.getBaseContext());
                     db = new DbHandler(this.getBaseContext());
                     String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
                     String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
-                    Log.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
+                    Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
                     if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
                     if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
                         message = getString(R.string.failed_upload_quota_exceeded_text);
                         message = getString(R.string.failed_upload_quota_exceeded_text);
                     }
                     }

+ 8 - 8
src/com/owncloud/android/files/services/InstantUploadService.java

@@ -23,16 +23,16 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.LinkedList;
 import java.util.List;
 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.accounts.Account;
 import android.app.Service;
 import android.app.Service;
 import android.content.Intent;
 import android.content.Intent;
 import android.os.IBinder;
 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 {
 public class InstantUploadService extends Service {
 
 
@@ -57,7 +57,7 @@ public class InstantUploadService extends Service {
         if (intent == null || !intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_DISPLAY_NAME)
         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_FILE_PATH) || !intent.hasExtra(KEY_FILE_SIZE)
                 || !intent.hasExtra(KEY_MIME_TYPE)) {
                 || !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;
             return Service.START_NOT_STICKY;
         }
         }
 
 
@@ -75,7 +75,7 @@ public class InstantUploadService extends Service {
 
 
         // starting new thread for new download doesnt seems like a good idea
         // starting new thread for new download doesnt seems like a good idea
         // maybe some thread pool or single background thread would be better
         // 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();
         new Thread(mUploaderRunnable).start();
 
 
         return Service.START_STICKY;
         return Service.START_STICKY;

+ 4 - 2
src/com/owncloud/android/location/LocationServiceLauncherReciever.java

@@ -18,6 +18,8 @@
  */
  */
 package com.owncloud.android.location;
 package com.owncloud.android.location;
 
 
+import com.owncloud.android.Log_OC;
+
 import android.app.ActivityManager;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningServiceInfo;
 import android.app.ActivityManager.RunningServiceInfo;
 import android.content.BroadcastReceiver;
 import android.content.BroadcastReceiver;
@@ -60,10 +62,10 @@ public class LocationServiceLauncherReciever extends BroadcastReceiver {
         deviceTrackingIntent
         deviceTrackingIntent
                 .setAction("com.owncloud.android.location.LocationUpdateService");
                 .setAction("com.owncloud.android.location.LocationUpdateService");
         if (!isDeviceTrackingServiceRunning(context) && trackDevice) {
         if (!isDeviceTrackingServiceRunning(context) && trackDevice) {
-            Log.d(TAG, "Starting device tracker service");
+            Log_OC.d(TAG, "Starting device tracker service");
             context.startService(deviceTrackingIntent);
             context.startService(deviceTrackingIntent);
         } else if (isDeviceTrackingServiceRunning(context) && !trackDevice) {
         } else if (isDeviceTrackingServiceRunning(context) && !trackDevice) {
-            Log.d(TAG, "Stopping device tracker service");
+            Log_OC.d(TAG, "Stopping device tracker service");
             context.stopService(deviceTrackingIntent);
             context.stopService(deviceTrackingIntent);
         }
         }
     }
     }

+ 3 - 2
src/com/owncloud/android/location/LocationUpdateService.java

@@ -31,6 +31,7 @@ import android.preference.PreferenceManager;
 import android.util.Log;
 import android.util.Log;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 
 
 public class LocationUpdateService extends IntentService implements
 public class LocationUpdateService extends IntentService implements
@@ -76,7 +77,7 @@ public class LocationUpdateService extends IntentService implements
 
 
         // If we do shall track the device -> Stop
         // If we do shall track the device -> Stop
         if (!trackDevice) {
         if (!trackDevice) {
-            Log.d(TAG, "Devicetracking is disabled");
+            Log_OC.d(TAG, "Devicetracking is disabled");
             stopSelf();
             stopSelf();
             return;
             return;
         }
         }
@@ -87,7 +88,7 @@ public class LocationUpdateService extends IntentService implements
 
 
     @Override
     @Override
     public void onLocationChanged(Location location) {
     public void onLocationChanged(Location location) {
-        Log.d(TAG, "Location changed: " + location);
+        Log_OC.d(TAG, "Location changed: " + location);
 
 
     }
     }
 
 

+ 7 - 7
src/com/owncloud/android/media/MediaService.java

@@ -34,11 +34,11 @@ import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.WifiLock;
 import android.net.wifi.WifiManager.WifiLock;
 import android.os.IBinder;
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.PowerManager;
-import android.util.Log;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
 import java.io.IOException;
 import java.io.IOException;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.ui.activity.FileDetailActivity;
 import com.owncloud.android.ui.activity.FileDetailActivity;
@@ -218,7 +218,7 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
      */
      */
     @Override
     @Override
     public void onCreate() {
     public void onCreate() {
-        Log.d(TAG, "Creating ownCloud media service");
+        Log_OC.d(TAG, "Creating ownCloud media service");
 
 
         mWifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)).
         mWifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)).
                 createWifiLock(WifiManager.WIFI_MODE_FULL, MEDIA_WIFI_LOCK_TAG);
                 createWifiLock(WifiManager.WIFI_MODE_FULL, MEDIA_WIFI_LOCK_TAG);
@@ -466,22 +466,22 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
             }
             }
             
             
         } catch (SecurityException e) {
         } catch (SecurityException e) {
-            Log.e(TAG, "SecurityException playing " + mAccount.name + mFile.getRemotePath(), e);
+            Log_OC.e(TAG, "SecurityException playing " + mAccount.name + mFile.getRemotePath(), e);
             Toast.makeText(this, String.format(getString(R.string.media_err_security_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
             Toast.makeText(this, String.format(getString(R.string.media_err_security_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
             processStopRequest(true);
             processStopRequest(true);
             
             
         } catch (IOException e) {
         } catch (IOException e) {
-            Log.e(TAG, "IOException playing " + mAccount.name + mFile.getRemotePath(), e);
+            Log_OC.e(TAG, "IOException playing " + mAccount.name + mFile.getRemotePath(), e);
             Toast.makeText(this, String.format(getString(R.string.media_err_io_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
             Toast.makeText(this, String.format(getString(R.string.media_err_io_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
             processStopRequest(true);
             processStopRequest(true);
             
             
         } catch (IllegalStateException e) {
         } catch (IllegalStateException e) {
-            Log.e(TAG, "IllegalStateException " + mAccount.name + mFile.getRemotePath(), e);
+            Log_OC.e(TAG, "IllegalStateException " + mAccount.name + mFile.getRemotePath(), e);
             Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
             Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
             processStopRequest(true);
             processStopRequest(true);
             
             
         } catch (IllegalArgumentException e) {
         } catch (IllegalArgumentException e) {
-            Log.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e);
+            Log_OC.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e);
             Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
             Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
             processStopRequest(true);
             processStopRequest(true);
         }
         }
@@ -593,7 +593,7 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
      * Warns the user about the error and resets the media player.
      * Warns the user about the error and resets the media player.
      */
      */
     public boolean onError(MediaPlayer mp, int what, int extra) {
     public boolean onError(MediaPlayer mp, int what, int extra) {
-        Log.e(TAG, "Error in audio playback, what = " + what + ", extra = " + extra);
+        Log_OC.e(TAG, "Error in audio playback, what = " + what + ", extra = " + extra);
         
         
         String message = getMessageForMediaError(this, what, extra);
         String message = getMessageForMediaError(this, what, extra);
         Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
         Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();

+ 5 - 5
src/com/owncloud/android/media/MediaServiceBinder.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.media;
 package com.owncloud.android.media;
 
 
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaService.State;
 import com.owncloud.android.media.MediaService.State;
 
 
@@ -26,7 +27,6 @@ import android.accounts.Account;
 import android.content.Intent;
 import android.content.Intent;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer;
 import android.os.Binder;
 import android.os.Binder;
-import android.util.Log;
 import android.widget.MediaController;
 import android.widget.MediaController;
 
 
 
 
@@ -129,13 +129,13 @@ public class MediaServiceBinder extends Binder implements MediaController.MediaP
     
     
     @Override
     @Override
     public void pause() {
     public void pause() {
-        Log.d(TAG, "Pausing through binder...");
+        Log_OC.d(TAG, "Pausing through binder...");
         mService.processPauseRequest();
         mService.processPauseRequest();
     }
     }
 
 
     @Override
     @Override
     public void seekTo(int pos) {
     public void seekTo(int pos) {
-        Log.d(TAG, "Seeking " + pos + " through binder...");
+        Log_OC.d(TAG, "Seeking " + pos + " through binder...");
         MediaPlayer currentPlayer = mService.getPlayer();
         MediaPlayer currentPlayer = mService.getPlayer();
         MediaService.State currentState = mService.getState();
         MediaService.State currentState = mService.getState();
         if (currentPlayer != null && currentState != State.PREPARING && currentState != State.STOPPED) {
         if (currentPlayer != null && currentState != State.PREPARING && currentState != State.STOPPED) {
@@ -145,12 +145,12 @@ public class MediaServiceBinder extends Binder implements MediaController.MediaP
 
 
     @Override
     @Override
     public void start() {
     public void start() {
-        Log.d(TAG, "Starting through binder...");
+        Log_OC.d(TAG, "Starting through binder...");
         mService.processPlayRequest();  // this will finish the service if there is no file preloaded to play
         mService.processPlayRequest();  // this will finish the service if there is no file preloaded to play
     }
     }
     
     
     public void start(Account account, OCFile file, boolean playImmediately, int position) {
     public void start(Account account, OCFile file, boolean playImmediately, int position) {
-        Log.d(TAG, "Loading and starting through binder...");
+        Log_OC.d(TAG, "Loading and starting through binder...");
         Intent i = new Intent(mService, MediaService.class);
         Intent i = new Intent(mService, MediaService.class);
         i.putExtra(MediaService.EXTRA_ACCOUNT, account);
         i.putExtra(MediaService.EXTRA_ACCOUNT, account);
         i.putExtra(MediaService.EXTRA_FILE, file);
         i.putExtra(MediaService.EXTRA_FILE, file);

+ 5 - 3
src/com/owncloud/android/network/AdvancedSslSocketFactory.java

@@ -40,6 +40,8 @@ import org.apache.commons.httpclient.params.HttpConnectionParams;
 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 
 
+import com.owncloud.android.Log_OC;
+
 import android.util.Log;
 import android.util.Log;
 
 
 /**
 /**
@@ -104,13 +106,13 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
             final InetAddress localAddress, final int localPort,
             final InetAddress localAddress, final int localPort,
             final HttpConnectionParams params) throws IOException,
             final HttpConnectionParams params) throws IOException,
             UnknownHostException, ConnectTimeoutException {
             UnknownHostException, ConnectTimeoutException {
-        Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
+        Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
         if (params == null) {
         if (params == null) {
             throw new IllegalArgumentException("Parameters may not be null");
             throw new IllegalArgumentException("Parameters may not be null");
         } 
         } 
         int timeout = params.getConnectionTimeout();
         int timeout = params.getConnectionTimeout();
         SocketFactory socketfactory = mSslContext.getSocketFactory();
         SocketFactory socketfactory = mSslContext.getSocketFactory();
-        Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
+        Log_OC.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
         Socket socket = socketfactory.createSocket();
         Socket socket = socketfactory.createSocket();
         SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
         SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
         SocketAddress remoteaddr = new InetSocketAddress(host, port);
         SocketAddress remoteaddr = new InetSocketAddress(host, port);
@@ -126,7 +128,7 @@ public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
      */
      */
     public Socket createSocket(String host, int port) throws IOException,
     public Socket createSocket(String host, int port) throws IOException,
             UnknownHostException {
             UnknownHostException {
-        Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
+        Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
         Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
         Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
         verifyPeerIdentity(host, port, socket);
         verifyPeerIdentity(host, port, socket);
         return socket; 
         return socket; 

+ 3 - 1
src/com/owncloud/android/network/AdvancedX509TrustManager.java

@@ -32,6 +32,8 @@ import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 import javax.net.ssl.X509TrustManager;
 
 
+import com.owncloud.android.Log_OC;
+
 import android.util.Log;
 import android.util.Log;
 
 
 /**
 /**
@@ -139,7 +141,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
         try {
         try {
             return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
             return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
         } catch (KeyStoreException e) {
         } catch (KeyStoreException e) {
-            Log.d(TAG, "Fail while checking certificate in the known-servers store");
+            Log_OC.d(TAG, "Fail while checking certificate in the known-servers store");
             return false;
             return false;
         }
         }
     }
     }

+ 7 - 6
src/com/owncloud/android/network/OwnCloudClientUtils.java

@@ -38,6 +38,7 @@ import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 
 
 import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavClient;
 
 
@@ -75,7 +76,7 @@ public class OwnCloudClientUtils {
      * @return          A WebdavClient object ready to be used
      * @return          A WebdavClient object ready to be used
      */
      */
     public static WebdavClient createOwnCloudClient (Account account, Context context) {
     public static WebdavClient createOwnCloudClient (Account account, Context context) {
-        Log.d(TAG, "Creating WebdavClient associated to " + account.name);
+        Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
        
        
         Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(context, account));
         Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(context, account));
         WebdavClient client = createOwnCloudClient(uri, context);
         WebdavClient client = createOwnCloudClient(uri, context);
@@ -100,7 +101,7 @@ public class OwnCloudClientUtils {
      * @return          A WebdavClient object ready to be used
      * @return          A WebdavClient object ready to be used
      */
      */
     public static WebdavClient createOwnCloudClient(Uri uri, String username, String password, Context context) {
     public static WebdavClient createOwnCloudClient(Uri uri, String username, String password, Context context) {
-        Log.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
+        Log_OC.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
         
         
         WebdavClient client = createOwnCloudClient(uri, context);
         WebdavClient client = createOwnCloudClient(uri, context);
         
         
@@ -118,16 +119,16 @@ public class OwnCloudClientUtils {
      * @return          A WebdavClient object ready to be used
      * @return          A WebdavClient object ready to be used
      */
      */
     public static WebdavClient createOwnCloudClient(Uri uri, Context context) {
     public static WebdavClient createOwnCloudClient(Uri uri, Context context) {
-        Log.d(TAG, "Creating WebdavClient for " + uri);
+        Log_OC.d(TAG, "Creating WebdavClient for " + uri);
         
         
         //allowSelfsignedCertificates(true);
         //allowSelfsignedCertificates(true);
         try {
         try {
             registerAdvancedSslContext(true, context);
             registerAdvancedSslContext(true, context);
         }  catch (GeneralSecurityException e) {
         }  catch (GeneralSecurityException e) {
-            Log.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
+            Log_OC.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
             
             
         } catch (IOException e) {
         } catch (IOException e) {
-            Log.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
+            Log_OC.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
         }
         }
         
         
         WebdavClient client = new WebdavClient(getMultiThreadedConnManager());
         WebdavClient client = new WebdavClient(getMultiThreadedConnManager());
@@ -205,7 +206,7 @@ public class OwnCloudClientUtils {
             //mKnownServersStore = KeyStore.getInstance("BKS");
             //mKnownServersStore = KeyStore.getInstance("BKS");
             mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
             mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
             File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
             File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
-            Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
+            Log_OC.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
             if (localTrustStoreFile.exists()) {
             if (localTrustStoreFile.exists()) {
                 InputStream in = new FileInputStream(localTrustStoreFile);
                 InputStream in = new FileInputStream(localTrustStoreFile);
                 try {
                 try {

+ 2 - 1
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java

@@ -28,6 +28,7 @@ import java.util.Random;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.commons.httpclient.methods.PutMethod;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 
 
@@ -75,7 +76,7 @@ public class ChunkedUploadFileOperation extends UploadFileOperation {
                 mPutMethod.setRequestEntity(mEntity);
                 mPutMethod.setRequestEntity(mEntity);
                 status = client.executeMethod(mPutMethod);
                 status = client.executeMethod(mPutMethod);
                 client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
                 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))
                 if (!isSuccess(status))
                     break;
                     break;
             }
             }

+ 5 - 4
src/com/owncloud/android/operations/ConnectionCheckOperation.java

@@ -24,6 +24,7 @@ import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONObject;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.utils.OwnCloudVersion;
 import com.owncloud.android.utils.OwnCloudVersion;
 
 
 import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavClient;
@@ -96,13 +97,13 @@ public class ConnectionCheckOperation extends RemoteOperation {
         }
         }
         
         
         if (mLatestResult.isSuccess()) {
         if (mLatestResult.isSuccess()) {
-            Log.i(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
+            Log_OC.i(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
             
             
         } else if (mLatestResult.getException() != null) {
         } else if (mLatestResult.getException() != null) {
-            Log.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage(), mLatestResult.getException());
+            Log_OC.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage(), mLatestResult.getException());
             
             
         } else {
         } else {
-            Log.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
+            Log_OC.e(TAG, "Connection check at " + urlSt + ": " + mLatestResult.getLogMessage());
         }
         }
 
 
         return retval;
         return retval;
@@ -127,7 +128,7 @@ public class ConnectionCheckOperation extends RemoteOperation {
             client.setBaseUri(Uri.parse("https://" + mUrl + AccountUtils.STATUS_PATH));
             client.setBaseUri(Uri.parse("https://" + mUrl + AccountUtils.STATUS_PATH));
             boolean httpsSuccess = tryConnection(client, "https://" + mUrl + AccountUtils.STATUS_PATH); 
             boolean httpsSuccess = tryConnection(client, "https://" + mUrl + AccountUtils.STATUS_PATH); 
             if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) {
             if (!httpsSuccess && !mLatestResult.isSslRecoverableException()) {
-                Log.d(TAG, "establishing secure connection failed, trying non secure connection");
+                Log_OC.d(TAG, "establishing secure connection failed, trying non secure connection");
                 client.setBaseUri(Uri.parse("http://" + mUrl + AccountUtils.STATUS_PATH));
                 client.setBaseUri(Uri.parse("http://" + mUrl + AccountUtils.STATUS_PATH));
                 tryConnection(client, "http://" + mUrl + AccountUtils.STATUS_PATH);
                 tryConnection(client, "http://" + mUrl + AccountUtils.STATUS_PATH);
             }
             }

+ 4 - 3
src/com/owncloud/android/operations/DownloadFileOperation.java

@@ -33,6 +33,7 @@ import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.http.HttpStatus;
 import org.apache.http.HttpStatus;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoteOperationResult;
 import com.owncloud.android.operations.RemoteOperationResult;
@@ -104,7 +105,7 @@ public class DownloadFileOperation extends RemoteOperation {
                     .getMimeTypeFromExtension(
                     .getMimeTypeFromExtension(
                             mFile.getRemotePath().substring(mFile.getRemotePath().lastIndexOf('.') + 1));
                             mFile.getRemotePath().substring(mFile.getRemotePath().lastIndexOf('.') + 1));
             } catch (IndexOutOfBoundsException e) {
             } 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) {
         if (mimeType == null) {
@@ -156,11 +157,11 @@ public class DownloadFileOperation extends RemoteOperation {
                 result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
                 result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
             else
             else
                 result = new RemoteOperationResult(isSuccess(status), status);
                 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) {
         } catch (Exception e) {
             result = new RemoteOperationResult(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;
         return result;

+ 2 - 1
src/com/owncloud/android/operations/RemoteOperationResult.java

@@ -35,6 +35,7 @@ import org.apache.jackrabbit.webdav.DavException;
 
 
 import android.util.Log;
 import android.util.Log;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.network.CertificateCombinedException;
 import com.owncloud.android.network.CertificateCombinedException;
 
 
 /**
 /**
@@ -91,7 +92,7 @@ public class RemoteOperationResult implements Serializable {
                 break;
                 break;
             default:
             default:
                 mCode = ResultCode.UNHANDLED_HTTP_CODE;
                 mCode = ResultCode.UNHANDLED_HTTP_CODE;
-                Log.d(TAG, "RemoteOperationResult has prcessed UNHANDLED_HTTP_CODE: " + httpCode);
+                Log_OC.d(TAG, "RemoteOperationResult has prcessed UNHANDLED_HTTP_CODE: " + httpCode);
             }
             }
         }
         }
     }
     }

+ 3 - 2
src/com/owncloud/android/operations/RemoveFileOperation.java

@@ -23,6 +23,7 @@ import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
 
 
 import android.util.Log;
 import android.util.Log;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 
 
@@ -91,11 +92,11 @@ public class RemoveFileOperation extends RemoteOperation {
             }
             }
             delete.getResponseBodyAsString();   // exhaust the response, although not interesting
             delete.getResponseBodyAsString();   // exhaust the response, although not interesting
             result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status);
             result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status);
-            Log.i(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage());
+            Log_OC.i(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage());
             
             
         } catch (Exception e) {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             result = new RemoteOperationResult(e);
-            Log.e(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Remove " + mFileToRemove.getRemotePath() + ": " + result.getLogMessage(), e);
             
             
         } finally {
         } finally {
             if (delete != null)
             if (delete != null)

+ 4 - 3
src/com/owncloud/android/operations/RenameFileOperation.java

@@ -27,6 +27,7 @@ import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
 import android.accounts.Account;
 import android.accounts.Account;
 import android.util.Log;
 import android.util.Log;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
@@ -138,11 +139,11 @@ public class RenameFileOperation extends RemoteOperation {
             
             
             move.getResponseBodyAsString(); // exhaust response, although not interesting
             move.getResponseBodyAsString(); // exhaust response, although not interesting
             result = new RemoteOperationResult(move.succeeded(), status);
             result = new RemoteOperationResult(move.succeeded(), status);
-            Log.i(TAG, "Rename " + mFile.getRemotePath() + " to " + mNewRemotePath + ": " + result.getLogMessage());
+            Log_OC.i(TAG, "Rename " + mFile.getRemotePath() + " to " + mNewRemotePath + ": " + result.getLogMessage());
             
             
         } catch (Exception e) {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             result = new RemoteOperationResult(e);
-            Log.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Rename " + mFile.getRemotePath() + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + result.getLogMessage(), e);
             
             
         } finally {
         } finally {
             if (move != null)
             if (move != null)
@@ -206,7 +207,7 @@ public class RenameFileOperation extends RemoteOperation {
         try {
         try {
             testFile.createNewFile();   // return value is ignored; it could be 'false' because the file already existed, that doesn't invalidate the name
             testFile.createNewFile();   // return value is ignored; it could be 'false' because the file already existed, that doesn't invalidate the name
         } catch (IOException e) {
         } catch (IOException e) {
-            Log.i(TAG, "Test for validity of name " + mNewName + " in the file system failed");
+            Log_OC.i(TAG, "Test for validity of name " + mNewName + " in the file system failed");
             return false;
             return false;
         }
         }
         boolean result = (testFile.exists() && testFile.isFile());
         boolean result = (testFile.exists() && testFile.isFile());

+ 3 - 2
src/com/owncloud/android/operations/SynchronizeFileOperation.java

@@ -28,6 +28,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
 import android.util.Log;
 import android.util.Log;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader;
@@ -158,11 +159,11 @@ public class SynchronizeFileOperation extends RemoteOperation {
           
           
             }
             }
             
             
-            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) {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             result = new RemoteOperationResult(e);
-            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 {
         } finally {
             if (propfind != null)
             if (propfind != null)

+ 10 - 9
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -37,6 +37,7 @@ import android.accounts.Account;
 import android.content.Context;
 import android.content.Context;
 import android.util.Log;
 import android.util.Log;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
@@ -132,7 +133,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         // code before in FileSyncAdapter.fetchData
         // code before in FileSyncAdapter.fetchData
         PropFindMethod query = null;
         PropFindMethod query = null;
         try {
         try {
-            Log.d(TAG, "Synchronizing " + mAccount.name + ", fetching files in " + mRemotePath);
+            Log_OC.d(TAG, "Synchronizing " + mAccount.name + ", fetching files in " + mRemotePath);
             
             
             // remote request 
             // remote request 
             query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
             query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
@@ -209,9 +210,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                         } else {
                         } else {
                             mFailsInFavouritesFound++;
                             mFailsInFavouritesFound++;
                             if (contentsResult.getException() != null) {
                             if (contentsResult.getException() != null) {
-                                Log.d(TAG, "Error while synchronizing favourites : " +  contentsResult.getLogMessage(), contentsResult.getException());
+                                Log_OC.d(TAG, "Error while synchronizing favourites : " +  contentsResult.getLogMessage(), contentsResult.getException());
                             } else {
                             } else {
-                                Log.d(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage());
+                                Log_OC.d(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage());
                             }
                             }
                         }
                         }
                     }   // won't let these fails break the synchronization process
                     }   // won't let these fails break the synchronization process
@@ -225,7 +226,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                 for (int i=0; i < mChildren.size(); ) {
                 for (int i=0; i < mChildren.size(); ) {
                     file = mChildren.get(i);
                     file = mChildren.get(i);
                     if (file.getLastSyncDateForProperties() != mCurrentSyncTime) {
                     if (file.getLastSyncDateForProperties() != mCurrentSyncTime) {
-                        Log.d(TAG, "removing file: " + file);
+                        Log_OC.d(TAG, "removing file: " + file);
                         mStorageManager.removeFile(file, (file.isDown() && file.getStoragePath().startsWith(currentSavePath)));
                         mStorageManager.removeFile(file, (file.isDown() && file.getStoragePath().startsWith(currentSavePath)));
                         mChildren.remove(i);
                         mChildren.remove(i);
                     } else {
                     } else {
@@ -248,12 +249,12 @@ public class SynchronizeFolderOperation extends RemoteOperation {
             } else {
             } else {
                 result = new RemoteOperationResult(false, status);
                 result = new RemoteOperationResult(false, status);
             }
             }
-            Log.i(TAG, "Synchronizing " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage());
+            Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage());
             
             
             
             
         } catch (Exception e) {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             result = new RemoteOperationResult(e);
-            Log.e(TAG, "Synchronizing " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage(), result.getException());
+            Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage(), result.getException());
 
 
         } finally {
         } finally {
             if (query != null)
             if (query != null)
@@ -329,7 +330,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                     file.setStoragePath(expectedPath);
                     file.setStoragePath(expectedPath);
                     
                     
                 } catch (Exception e) {
                 } catch (Exception e) {
-                    Log.e(TAG, "Exception while copying foreign file " + expectedPath, e);
+                    Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e);
                     mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
                     mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
                     file.setStoragePath(null);
                     file.setStoragePath(null);
                     
                     
@@ -337,12 +338,12 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                     try {
                     try {
                         if (in != null) in.close();
                         if (in != null) in.close();
                     } catch (Exception e) {
                     } catch (Exception e) {
-                        Log.d(TAG, "Weird exception while closing input stream for " + storagePath + " (ignoring)", e);
+                        Log_OC.d(TAG, "Weird exception while closing input stream for " + storagePath + " (ignoring)", e);
                     }
                     }
                     try {
                     try {
                         if (out != null) out.close();
                         if (out != null) out.close();
                     } catch (Exception e) {
                     } 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);
                     }
                     }
                 }
                 }
             }
             }

+ 6 - 5
src/com/owncloud/android/operations/UpdateOCVersionOperation.java

@@ -29,6 +29,7 @@ import android.content.Context;
 import android.util.Log;
 import android.util.Log;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.utils.OwnCloudVersion;
 import com.owncloud.android.utils.OwnCloudVersion;
@@ -76,11 +77,11 @@ public class UpdateOCVersionOperation extends RemoteOperation {
                         OwnCloudVersion ocver = new OwnCloudVersion(json.getString("version"));
                         OwnCloudVersion ocver = new OwnCloudVersion(json.getString("version"));
                         if (ocver.isVersionValid()) {
                         if (ocver.isVersionValid()) {
                             accountMngr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, ocver.toString());
                             accountMngr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, ocver.toString());
-                            Log.d(TAG, "Got new OC version " + ocver.toString());
+                            Log_OC.d(TAG, "Got new OC version " + ocver.toString());
                             result = new RemoteOperationResult(ResultCode.OK);
                             result = new RemoteOperationResult(ResultCode.OK);
                             
                             
                         } else {
                         } else {
-                            Log.w(TAG, "Invalid version number received from server: " + json.getString("version"));
+                            Log_OC.w(TAG, "Invalid version number received from server: " + json.getString("version"));
                             result = new RemoteOperationResult(RemoteOperationResult.ResultCode.BAD_OC_VERSION);
                             result = new RemoteOperationResult(RemoteOperationResult.ResultCode.BAD_OC_VERSION);
                         }
                         }
                     }
                     }
@@ -89,15 +90,15 @@ public class UpdateOCVersionOperation extends RemoteOperation {
                     result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
                     result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
                 }
                 }
             }
             }
-            Log.i(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage());
+            Log_OC.i(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage());
             
             
         } catch (JSONException e) {
         } catch (JSONException e) {
             result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
             result = new RemoteOperationResult(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
-            Log.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
                 
                 
         } catch (Exception e) {
         } catch (Exception e) {
             result = new RemoteOperationResult(e);
             result = new RemoteOperationResult(e);
-            Log.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
+            Log_OC.e(TAG, "Check for update of ownCloud server version at " + client.getBaseUri() + ": " + result.getLogMessage(), e);
             
             
         } finally {
         } finally {
             if (get != null) 
             if (get != null) 

+ 6 - 12
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -33,8 +33,8 @@ import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.http.HttpStatus;
 import org.apache.http.HttpStatus;
 
 
+import com.owncloud.android.Log_OC;
 import android.accounts.Account;
 import android.accounts.Account;
-import android.util.Log;
 
 
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader;
@@ -246,15 +246,13 @@ public class UploadFileOperation extends RemoteOperation {
                                 if (in != null)
                                 if (in != null)
                                     in.close();
                                     in.close();
                             } catch (Exception e) {
                             } 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 {
                             try {
                                 if (out != null)
                                 if (out != null)
                                     out.close();
                                     out.close();
                             } catch (Exception e) {
                             } 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);
                             }
                             }
                         }
                         }
                     }
                     }
@@ -322,8 +320,7 @@ public class UploadFileOperation extends RemoteOperation {
                 temporalFile.delete();
                 temporalFile.delete();
             }
             }
             if (result.isSuccess()) {
             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 {
             } else {
                 if (result.getException() != null) {
                 if (result.getException() != null) {
                     String complement = "";
                     String complement = "";
@@ -333,12 +330,9 @@ public class UploadFileOperation extends RemoteOperation {
                         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 {
                 } else {
-                    Log.e(TAG,
-                            "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
+                    Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
                 }
                 }
             }
             }
         }
         }

+ 290 - 289
src/com/owncloud/android/providers/FileContentProvider.java

@@ -1,289 +1,290 @@
-/* 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.providers;
-
-import java.util.HashMap;
-
-import com.owncloud.android.db.ProviderMeta;
-import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
-
-
-import android.content.ContentProvider;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * The ContentProvider for the ownCloud App.
- * 
- * @author Bartek Przybylski
- * 
- */
-public class FileContentProvider extends ContentProvider {
-
-    private DataBaseHelper mDbHelper;
-
-    private static HashMap<String, String> mProjectionMap;
-    static {
-        mProjectionMap = new HashMap<String, String>();
-        mProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
-        mProjectionMap.put(ProviderTableMeta.FILE_PARENT,
-                ProviderTableMeta.FILE_PARENT);
-        mProjectionMap.put(ProviderTableMeta.FILE_PATH,
-                ProviderTableMeta.FILE_PATH);
-        mProjectionMap.put(ProviderTableMeta.FILE_NAME,
-                ProviderTableMeta.FILE_NAME);
-        mProjectionMap.put(ProviderTableMeta.FILE_CREATION,
-                ProviderTableMeta.FILE_CREATION);
-        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
-                ProviderTableMeta.FILE_MODIFIED);
-        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
-                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
-        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
-                ProviderTableMeta.FILE_CONTENT_LENGTH);
-        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
-                ProviderTableMeta.FILE_CONTENT_TYPE);
-        mProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
-                ProviderTableMeta.FILE_STORAGE_PATH);
-        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
-                ProviderTableMeta.FILE_LAST_SYNC_DATE);
-        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
-                ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
-        mProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
-                ProviderTableMeta.FILE_KEEP_IN_SYNC);
-        mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
-                ProviderTableMeta.FILE_ACCOUNT_OWNER);
-    }
-
-    private static final int SINGLE_FILE = 1;
-    private static final int DIRECTORY = 2;
-    private static final int ROOT_DIRECTORY = 3;
-    private static final UriMatcher mUriMatcher;
-    static {
-        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
-        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "/", ROOT_DIRECTORY);
-        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
-        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
-        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
-    }
-
-    @Override
-    public int delete(Uri uri, String where, String[] whereArgs) {
-        SQLiteDatabase db = mDbHelper.getWritableDatabase();
-        int count = 0;
-        switch (mUriMatcher.match(uri)) {
-        case SINGLE_FILE:
-            count = db.delete(ProviderTableMeta.DB_NAME,
-                    ProviderTableMeta._ID
-                            + "="
-                            + uri.getPathSegments().get(1)
-                            + (!TextUtils.isEmpty(where) ? " AND (" + where
-                                    + ")" : ""), whereArgs);
-            break;
-        case ROOT_DIRECTORY:
-            count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
-            break;
-        default:
-            throw new IllegalArgumentException("Unknown uri: " + uri.toString());
-        }
-        getContext().getContentResolver().notifyChange(uri, null);
-        return count;
-    }
-
-    @Override
-    public String getType(Uri uri) {
-        switch (mUriMatcher.match(uri)) {
-        case ROOT_DIRECTORY:
-            return ProviderTableMeta.CONTENT_TYPE;
-        case SINGLE_FILE:
-            return ProviderTableMeta.CONTENT_TYPE_ITEM;
-        default:
-            throw new IllegalArgumentException("Unknown Uri id."
-                    + uri.toString());
-        }
-    }
-
-    @Override
-    public Uri insert(Uri uri, ContentValues values) {
-        if (mUriMatcher.match(uri) != SINGLE_FILE &&
-            mUriMatcher.match(uri) != ROOT_DIRECTORY) {
-            
-            throw new IllegalArgumentException("Unknown uri id: " + uri);
-        }
-
-        SQLiteDatabase db = mDbHelper.getWritableDatabase();
-        long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
-        if (rowId > 0) {
-            Uri insertedFileUri = ContentUris.withAppendedId(
-                    ProviderTableMeta.CONTENT_URI_FILE, rowId);
-            getContext().getContentResolver().notifyChange(insertedFileUri,
-                    null);
-            return insertedFileUri;
-        }
-        throw new SQLException("ERROR " + uri);
-    }
-
-    @Override
-    public boolean onCreate() {
-        mDbHelper = new DataBaseHelper(getContext());
-        return true;
-    }
-
-    @Override
-    public Cursor query(Uri uri, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) {
-        SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
-
-        sqlQuery.setTables(ProviderTableMeta.DB_NAME);
-        sqlQuery.setProjectionMap(mProjectionMap);
-
-        switch (mUriMatcher.match(uri)) {
-        case ROOT_DIRECTORY:
-            break;
-        case DIRECTORY:
-            sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
-                    + uri.getPathSegments().get(1));
-            break;
-        case SINGLE_FILE:
-            if (uri.getPathSegments().size() > 1) {
-                sqlQuery.appendWhere(ProviderTableMeta._ID + "="
-                        + uri.getPathSegments().get(1));
-            }
-            break;
-        default:
-            throw new IllegalArgumentException("Unknown uri id: " + uri);
-        }
-
-        String order;
-        if (TextUtils.isEmpty(sortOrder)) {
-            order = ProviderTableMeta.DEFAULT_SORT_ORDER;
-        } else {
-            order = sortOrder;
-        }
-
-        SQLiteDatabase db = mDbHelper.getReadableDatabase();
-        Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
-                null, null, order);
-
-        c.setNotificationUri(getContext().getContentResolver(), uri);
-
-        return c;
-    }
-
-    @Override
-    public int update(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs) {
-        return mDbHelper.getWritableDatabase().update(
-                ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
-    }
-
-    class DataBaseHelper extends SQLiteOpenHelper {
-
-        public DataBaseHelper(Context context) {
-            super(context, ProviderMeta.DB_NAME, null, ProviderMeta.DB_VERSION);
-
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            // files table
-            Log.i("SQL", "Entering in onCreate");
-            db.execSQL("CREATE TABLE " + ProviderTableMeta.DB_NAME + "("
-                    + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
-                    + ProviderTableMeta.FILE_NAME + " TEXT, "
-                    + ProviderTableMeta.FILE_PATH + " TEXT, "
-                    + ProviderTableMeta.FILE_PARENT + " INTEGER, "
-                    + ProviderTableMeta.FILE_CREATION + " INTEGER, "
-                    + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
-                    + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
-                    + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
-                    + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
-                    + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
-                    + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
-                    + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
-                    + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
-                    + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER );"
-                    );
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-            Log.i("SQL", "Entering in onUpgrade");
-            boolean upgraded = false; 
-            if (oldVersion == 1 && newVersion >= 2) {
-                Log.i("SQL", "Entering in the #1 ADD in onUpgrade");
-                db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
-                           " ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC  + " INTEGER " +
-                           " DEFAULT 0");
-                upgraded = true;
-            }
-            if (oldVersion < 3 && newVersion >= 3) {
-                Log.i("SQL", "Entering in the #2 ADD in onUpgrade");
-                db.beginTransaction();
-                try {
-                    db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
-                               " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA  + " INTEGER " +
-                               " DEFAULT 0");
-                    
-                    // assume there are not local changes pending to upload
-                    db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME + 
-                            " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() + 
-                            " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
-                 
-                    upgraded = true;
-                    db.setTransactionSuccessful();
-                } finally {
-                    db.endTransaction();
-                }
-            }
-            if (oldVersion < 4 && newVersion >= 4) {
-                Log.i("SQL", "Entering in the #3 ADD in onUpgrade");
-                db.beginTransaction();
-                try {
-                    db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
-                           " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA  + " INTEGER " +
-                           " DEFAULT 0");
-                
-                    db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME + 
-                           " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED + 
-                           " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
-                
-                    upgraded = true;
-                    db.setTransactionSuccessful();
-                } finally {
-                    db.endTransaction();
-                }
-            }
-            if (!upgraded)
-                Log.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
-        }
-
-    }
-
-}
+/* 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.providers;
+
+import java.util.HashMap;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.db.ProviderMeta;
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * The ContentProvider for the ownCloud App.
+ * 
+ * @author Bartek Przybylski
+ * 
+ */
+public class FileContentProvider extends ContentProvider {
+
+    private DataBaseHelper mDbHelper;
+
+    private static HashMap<String, String> mProjectionMap;
+    static {
+        mProjectionMap = new HashMap<String, String>();
+        mProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
+        mProjectionMap.put(ProviderTableMeta.FILE_PARENT,
+                ProviderTableMeta.FILE_PARENT);
+        mProjectionMap.put(ProviderTableMeta.FILE_PATH,
+                ProviderTableMeta.FILE_PATH);
+        mProjectionMap.put(ProviderTableMeta.FILE_NAME,
+                ProviderTableMeta.FILE_NAME);
+        mProjectionMap.put(ProviderTableMeta.FILE_CREATION,
+                ProviderTableMeta.FILE_CREATION);
+        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
+                ProviderTableMeta.FILE_MODIFIED);
+        mProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
+        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
+                ProviderTableMeta.FILE_CONTENT_LENGTH);
+        mProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
+                ProviderTableMeta.FILE_CONTENT_TYPE);
+        mProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
+                ProviderTableMeta.FILE_STORAGE_PATH);
+        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
+                ProviderTableMeta.FILE_LAST_SYNC_DATE);
+        mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
+                ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
+        mProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
+                ProviderTableMeta.FILE_KEEP_IN_SYNC);
+        mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
+                ProviderTableMeta.FILE_ACCOUNT_OWNER);
+    }
+
+    private static final int SINGLE_FILE = 1;
+    private static final int DIRECTORY = 2;
+    private static final int ROOT_DIRECTORY = 3;
+    private static final UriMatcher mUriMatcher;
+    static {
+        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "/", ROOT_DIRECTORY);
+        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/", SINGLE_FILE);
+        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "file/#", SINGLE_FILE);
+        mUriMatcher.addURI(ProviderMeta.AUTHORITY_FILES, "dir/#", DIRECTORY);
+    }
+
+    @Override
+    public int delete(Uri uri, String where, String[] whereArgs) {
+        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        int count = 0;
+        switch (mUriMatcher.match(uri)) {
+        case SINGLE_FILE:
+            count = db.delete(ProviderTableMeta.DB_NAME,
+                    ProviderTableMeta._ID
+                            + "="
+                            + uri.getPathSegments().get(1)
+                            + (!TextUtils.isEmpty(where) ? " AND (" + where
+                                    + ")" : ""), whereArgs);
+            break;
+        case ROOT_DIRECTORY:
+            count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
+            break;
+        default:
+            throw new IllegalArgumentException("Unknown uri: " + uri.toString());
+        }
+        getContext().getContentResolver().notifyChange(uri, null);
+        return count;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        switch (mUriMatcher.match(uri)) {
+        case ROOT_DIRECTORY:
+            return ProviderTableMeta.CONTENT_TYPE;
+        case SINGLE_FILE:
+            return ProviderTableMeta.CONTENT_TYPE_ITEM;
+        default:
+            throw new IllegalArgumentException("Unknown Uri id."
+                    + uri.toString());
+        }
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        if (mUriMatcher.match(uri) != SINGLE_FILE &&
+            mUriMatcher.match(uri) != ROOT_DIRECTORY) {
+            
+            throw new IllegalArgumentException("Unknown uri id: " + uri);
+        }
+
+        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
+        if (rowId > 0) {
+            Uri insertedFileUri = ContentUris.withAppendedId(
+                    ProviderTableMeta.CONTENT_URI_FILE, rowId);
+            getContext().getContentResolver().notifyChange(insertedFileUri,
+                    null);
+            return insertedFileUri;
+        }
+        throw new SQLException("ERROR " + uri);
+    }
+
+    @Override
+    public boolean onCreate() {
+        mDbHelper = new DataBaseHelper(getContext());
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
+
+        sqlQuery.setTables(ProviderTableMeta.DB_NAME);
+        sqlQuery.setProjectionMap(mProjectionMap);
+
+        switch (mUriMatcher.match(uri)) {
+        case ROOT_DIRECTORY:
+            break;
+        case DIRECTORY:
+            sqlQuery.appendWhere(ProviderTableMeta.FILE_PARENT + "="
+                    + uri.getPathSegments().get(1));
+            break;
+        case SINGLE_FILE:
+            if (uri.getPathSegments().size() > 1) {
+                sqlQuery.appendWhere(ProviderTableMeta._ID + "="
+                        + uri.getPathSegments().get(1));
+            }
+            break;
+        default:
+            throw new IllegalArgumentException("Unknown uri id: " + uri);
+        }
+
+        String order;
+        if (TextUtils.isEmpty(sortOrder)) {
+            order = ProviderTableMeta.DEFAULT_SORT_ORDER;
+        } else {
+            order = sortOrder;
+        }
+
+        SQLiteDatabase db = mDbHelper.getReadableDatabase();
+        Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
+                null, null, order);
+
+        c.setNotificationUri(getContext().getContentResolver(), uri);
+
+        return c;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return mDbHelper.getWritableDatabase().update(
+                ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
+    }
+
+    class DataBaseHelper extends SQLiteOpenHelper {
+
+        public DataBaseHelper(Context context) {
+            super(context, ProviderMeta.DB_NAME, null, ProviderMeta.DB_VERSION);
+
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            // files table
+            Log_OC.i("SQL", "Entering in onCreate");
+            db.execSQL("CREATE TABLE " + ProviderTableMeta.DB_NAME + "("
+                    + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
+                    + ProviderTableMeta.FILE_NAME + " TEXT, "
+                    + ProviderTableMeta.FILE_PATH + " TEXT, "
+                    + ProviderTableMeta.FILE_PARENT + " INTEGER, "
+                    + ProviderTableMeta.FILE_CREATION + " INTEGER, "
+                    + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
+                    + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
+                    + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
+                    + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
+                    + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
+                    + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
+                    + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
+                    + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
+                    + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER );"
+                    );
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log_OC.i("SQL", "Entering in onUpgrade");
+            boolean upgraded = false; 
+            if (oldVersion == 1 && newVersion >= 2) {
+                Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade");
+                db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                           " ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC  + " INTEGER " +
+                           " DEFAULT 0");
+                upgraded = true;
+            }
+            if (oldVersion < 3 && newVersion >= 3) {
+                Log_OC.i("SQL", "Entering in the #2 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                               " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA  + " INTEGER " +
+                               " DEFAULT 0");
+                    
+                    // assume there are not local changes pending to upload
+                    db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME + 
+                            " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() + 
+                            " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
+                 
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (oldVersion < 4 && newVersion >= 4) {
+                Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    db .execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +
+                           " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA  + " INTEGER " +
+                           " DEFAULT 0");
+                
+                    db.execSQL("UPDATE " + ProviderTableMeta.DB_NAME + 
+                           " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED + 
+                           " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
+                
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
+        }
+
+    }
+
+}

+ 371 - 370
src/com/owncloud/android/syncadapter/FileSyncAdapter.java

@@ -1,370 +1,371 @@
-/* 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.syncadapter;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.jackrabbit.webdav.DavException;
-
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.DataStorageManager;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.SynchronizeFolderOperation;
-import com.owncloud.android.operations.UpdateOCVersionOperation;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
-import android.accounts.Account;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SyncResult;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * SyncAdapter implementation for syncing sample SyncAdapter contacts to the
- * platform ContactOperations provider.
- * 
- * @author Bartek Przybylski
- */
-public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
-
-    private final static String TAG = "FileSyncAdapter";
-
-    /** 
-     * Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation
-     */
-    private static final int MAX_FAILED_RESULTS = 3; 
-    
-    private long mCurrentSyncTime;
-    private boolean mCancellation;
-    private boolean mIsManualSync;
-    private int mFailedResultsCounter;    
-    private RemoteOperationResult mLastFailedResult;
-    private SyncResult mSyncResult;
-    private int mConflictsFound;
-    private int mFailsInFavouritesFound;
-    private Map<String, String> mForgottenLocalFiles;
-
-    
-    public FileSyncAdapter(Context context, boolean autoInitialize) {
-        super(context, autoInitialize);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public synchronized void onPerformSync(Account account, Bundle extras,
-            String authority, ContentProviderClient provider,
-            SyncResult syncResult) {
-
-        mCancellation = false;
-        mIsManualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
-        mFailedResultsCounter = 0;
-        mLastFailedResult = null;
-        mConflictsFound = 0;
-        mFailsInFavouritesFound = 0;
-        mForgottenLocalFiles = new HashMap<String, String>();
-        mSyncResult = syncResult;
-        mSyncResult.fullSyncRequested = false;
-        mSyncResult.delayUntil = 60*60*24; // sync after 24h
-
-        this.setAccount(account);
-        this.setContentProvider(provider);
-        this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
-        try {
-            this.initClientForCurrentAccount();
-        } catch (UnknownHostException e) {
-            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
-            mSyncResult.tooManyRetries = true;
-            notifyFailedSynchronization();
-            return;
-        }
-        
-        Log.d(TAG, "Synchronization of ownCloud account " + account.name + " starting");
-        sendStickyBroadcast(true, null, null);  // message to signal the start of the synchronization to the UI
-        
-        try {
-            updateOCVersion();
-            mCurrentSyncTime = System.currentTimeMillis();
-            if (!mCancellation) {
-                fetchData(OCFile.PATH_SEPARATOR, DataStorageManager.ROOT_PARENT_ID);
-                
-            } else {
-                Log.d(TAG, "Leaving synchronization before any remote request due to cancellation was requested");
-            }
-            
-            
-        } finally {
-            // it's important making this although very unexpected errors occur; that's the reason for the finally
-            
-            if (mFailedResultsCounter > 0 && mIsManualSync) {
-                /// don't let the system synchronization manager retries MANUAL synchronizations
-                //      (be careful: "MANUAL" currently includes the synchronization requested when a new account is created and when the user changes the current account)
-                mSyncResult.tooManyRetries = true;
-                
-                /// notify the user about the failure of MANUAL synchronization
-                notifyFailedSynchronization();
-                
-            }
-            if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
-                notifyFailsInFavourites();
-            }
-            if (mForgottenLocalFiles.size() > 0) {
-                notifyForgottenLocalFiles();
-                
-            }
-            sendStickyBroadcast(false, null, mLastFailedResult);        // message to signal the end to the UI
-        }
-        
-    }
-
-    
-    /**
-     * Called by system SyncManager when a synchronization is required to be cancelled.
-     * 
-     * Sets the mCancellation flag to 'true'. THe synchronization will be stopped when before a new folder is fetched. Data of the last folder
-     * fetched will be still saved in the database. See onPerformSync implementation.
-     */
-    @Override
-    public void onSyncCanceled() {
-        Log.d(TAG, "Synchronization of " + getAccount().name + " has been requested to cancel");
-        mCancellation = true;
-        super.onSyncCanceled();
-    }
-    
-    
-    /**
-     * Updates the locally stored version value of the ownCloud server
-     */
-    private void updateOCVersion() {
-        UpdateOCVersionOperation update = new UpdateOCVersionOperation(getAccount(), getContext());
-        RemoteOperationResult result = update.execute(getClient());
-        if (!result.isSuccess()) {
-            mLastFailedResult = result; 
-        }
-    }
-
-    
-    
-    /**
-     * Synchronize the properties of files and folders contained in a remote folder given by remotePath.
-     * 
-     * @param remotePath        Remote path to the folder to synchronize.
-     * @param parentId          Database Id of the folder to synchronize.
-     */
-    private void fetchData(String remotePath, long parentId) {
-        
-        if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
-            return;
-        
-        // perform folder synchronization
-        SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation(  remotePath, 
-                                                                                    mCurrentSyncTime, 
-                                                                                    parentId, 
-                                                                                    getStorageManager(), 
-                                                                                    getAccount(), 
-                                                                                    getContext()
-                                                                                  );
-        RemoteOperationResult result = synchFolderOp.execute(getClient());
-        
-        
-        // synchronized folder -> notice to UI - ALWAYS, although !result.isSuccess
-        sendStickyBroadcast(true, remotePath, null);
-        
-        if (result.isSuccess() || result.getCode() == ResultCode.SYNC_CONFLICT) {
-            
-            if (result.getCode() == ResultCode.SYNC_CONFLICT) {
-                mConflictsFound += synchFolderOp.getConflictsFound();
-                mFailsInFavouritesFound += synchFolderOp.getFailsInFavouritesFound();
-            }
-            if (synchFolderOp.getForgottenLocalFiles().size() > 0) {
-                mForgottenLocalFiles.putAll(synchFolderOp.getForgottenLocalFiles());
-            }
-            // synchronize children folders 
-            List<OCFile> children = synchFolderOp.getChildren();
-            fetchChildren(children);    // beware of the 'hidden' recursion here!
-            
-        } else {
-            if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED) {
-                mSyncResult.stats.numAuthExceptions++;
-                
-            } else if (result.getException() instanceof DavException) {
-                mSyncResult.stats.numParseExceptions++;
-                
-            } else if (result.getException() instanceof IOException) { 
-                mSyncResult.stats.numIoExceptions++;
-            }
-            mFailedResultsCounter++;
-            mLastFailedResult = result;
-        }
-            
-    }
-
-    /**
-     * Checks if a failed result should terminate the synchronization process immediately, according to
-     * OUR OWN POLICY
-     * 
-     * @param   failedResult        Remote operation result to check.
-     * @return                      'True' if the result should immediately finish the synchronization
-     */
-    private boolean isFinisher(RemoteOperationResult failedResult) {
-        if  (failedResult != null) {
-            RemoteOperationResult.ResultCode code = failedResult.getCode();
-            return (code.equals(RemoteOperationResult.ResultCode.SSL_ERROR) ||
-                    code.equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) ||
-                    code.equals(RemoteOperationResult.ResultCode.BAD_OC_VERSION) ||
-                    code.equals(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED));
-        }
-        return false;
-    }
-
-    /**
-     * Synchronize data of folders in the list of received files
-     * 
-     * @param files         Files to recursively fetch 
-     */
-    private void fetchChildren(List<OCFile> files) {
-        int i;
-        for (i=0; i < files.size() && !mCancellation; i++) {
-            OCFile newFile = files.get(i);
-            if (newFile.isDirectory()) {
-                fetchData(newFile.getRemotePath(), newFile.getFileId());
-            }
-        }
-        if (mCancellation && i <files.size()) Log.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " because cancelation request");
-    }
-
-    
-    /**
-     * Sends a message to any application component interested in the progress of the synchronization.
-     * 
-     * @param inProgress        'True' when the synchronization progress is not finished.
-     * @param dirRemotePath     Remote path of a folder that was just synchronized (with or without success)
-     */
-    private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
-        Intent i = new Intent(FileSyncService.SYNC_MESSAGE);
-        i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
-        i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name);
-        if (dirRemotePath != null) {
-            i.putExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH, dirRemotePath);
-        }
-        if (result != null) {
-            i.putExtra(FileSyncService.SYNC_RESULT, result);
-        }
-        getContext().sendStickyBroadcast(i);
-    }
-
-    
-    
-    /**
-     * Notifies the user about a failed synchronization through the status notification bar 
-     */
-    private void notifyFailedSynchronization() {
-        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
-        notification.flags |= Notification.FLAG_AUTO_CANCEL;
-        // TODO put something smart in the contentIntent below
-        notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
-        notification.setLatestEventInfo(getContext().getApplicationContext(), 
-                                        getContext().getString(R.string.sync_fail_ticker), 
-                                        String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), 
-                                        notification.contentIntent);
-        ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);
-    }
-
-
-    /**
-     * Notifies the user about conflicts and strange fails when trying to synchronize the contents of kept-in-sync files.
-     * 
-     * By now, we won't consider a failed synchronization.
-     */
-    private void notifyFailsInFavourites() {
-        if (mFailedResultsCounter > 0) {
-            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis());
-            notification.flags |= Notification.FLAG_AUTO_CANCEL;
-            // TODO put something smart in the contentIntent below
-            notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
-            notification.setLatestEventInfo(getContext().getApplicationContext(), 
-                                            getContext().getString(R.string.sync_fail_in_favourites_ticker), 
-                                            String.format(getContext().getString(R.string.sync_fail_in_favourites_content), mFailedResultsCounter + mConflictsFound, mConflictsFound), 
-                                            notification.contentIntent);
-            ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification);
-            
-        } else {
-            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis());
-            notification.flags |= Notification.FLAG_AUTO_CANCEL;
-            // TODO put something smart in the contentIntent below
-            notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
-            notification.setLatestEventInfo(getContext().getApplicationContext(), 
-                                            getContext().getString(R.string.sync_conflicts_in_favourites_ticker), 
-                                            String.format(getContext().getString(R.string.sync_conflicts_in_favourites_content), mConflictsFound), 
-                                            notification.contentIntent);
-            ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_conflicts_in_favourites_ticker, notification);
-        } 
-    }
-
-    
-    /**
-     * Notifies the user about local copies of files out of the ownCloud local directory that were 'forgotten' because 
-     * copying them inside the ownCloud local directory was not possible.
-     * 
-     * We don't want links to files out of the ownCloud local directory (foreign files) anymore. It's easy to have 
-     * synchronization problems if a local file is linked to more than one remote file.
-     * 
-     * We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory.
-     */
-    private void notifyForgottenLocalFiles() {
-        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis());
-        notification.flags |= Notification.FLAG_AUTO_CANCEL;
-
-        /// includes a pending intent in the notification showing a more detailed explanation
-        Intent explanationIntent = new Intent(getContext(), ErrorsWhileCopyingHandlerActivity.class);
-        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_ACCOUNT, getAccount());
-        ArrayList<String> remotePaths = new ArrayList<String>();
-        ArrayList<String> localPaths = new ArrayList<String>();
-        remotePaths.addAll(mForgottenLocalFiles.keySet());
-        localPaths.addAll(mForgottenLocalFiles.values());
-        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_LOCAL_PATHS, localPaths);
-        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_REMOTE_PATHS, remotePaths);  
-        explanationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        
-        notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), explanationIntent, 0);
-        notification.setLatestEventInfo(getContext().getApplicationContext(), 
-                                        getContext().getString(R.string.sync_foreign_files_forgotten_ticker), 
-                                        String.format(getContext().getString(R.string.sync_foreign_files_forgotten_content), mForgottenLocalFiles.size(), getContext().getString(R.string.app_name)), 
-                                        notification.contentIntent);
-        ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_foreign_files_forgotten_ticker, notification);
-        
-    }
-    
-    
-}
+/* 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.syncadapter;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jackrabbit.webdav.DavException;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.operations.SynchronizeFolderOperation;
+import com.owncloud.android.operations.UpdateOCVersionOperation;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
+import android.accounts.Account;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SyncResult;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * SyncAdapter implementation for syncing sample SyncAdapter contacts to the
+ * platform ContactOperations provider.
+ * 
+ * @author Bartek Przybylski
+ */
+public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
+
+    private final static String TAG = "FileSyncAdapter";
+
+    /** 
+     * Maximum number of failed folder synchronizations that are supported before finishing the synchronization operation
+     */
+    private static final int MAX_FAILED_RESULTS = 3; 
+    
+    private long mCurrentSyncTime;
+    private boolean mCancellation;
+    private boolean mIsManualSync;
+    private int mFailedResultsCounter;    
+    private RemoteOperationResult mLastFailedResult;
+    private SyncResult mSyncResult;
+    private int mConflictsFound;
+    private int mFailsInFavouritesFound;
+    private Map<String, String> mForgottenLocalFiles;
+
+    
+    public FileSyncAdapter(Context context, boolean autoInitialize) {
+        super(context, autoInitialize);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized void onPerformSync(Account account, Bundle extras,
+            String authority, ContentProviderClient provider,
+            SyncResult syncResult) {
+
+        mCancellation = false;
+        mIsManualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+        mFailedResultsCounter = 0;
+        mLastFailedResult = null;
+        mConflictsFound = 0;
+        mFailsInFavouritesFound = 0;
+        mForgottenLocalFiles = new HashMap<String, String>();
+        mSyncResult = syncResult;
+        mSyncResult.fullSyncRequested = false;
+        mSyncResult.delayUntil = 60*60*24; // sync after 24h
+
+        this.setAccount(account);
+        this.setContentProvider(provider);
+        this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
+        try {
+            this.initClientForCurrentAccount();
+        } catch (UnknownHostException e) {
+            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
+            mSyncResult.tooManyRetries = true;
+            notifyFailedSynchronization();
+            return;
+        }
+        
+        Log_OC.d(TAG, "Synchronization of ownCloud account " + account.name + " starting");
+        sendStickyBroadcast(true, null, null);  // message to signal the start of the synchronization to the UI
+        
+        try {
+            updateOCVersion();
+            mCurrentSyncTime = System.currentTimeMillis();
+            if (!mCancellation) {
+                fetchData(OCFile.PATH_SEPARATOR, DataStorageManager.ROOT_PARENT_ID);
+                
+            } else {
+                Log_OC.d(TAG, "Leaving synchronization before any remote request due to cancellation was requested");
+            }
+            
+            
+        } finally {
+            // it's important making this although very unexpected errors occur; that's the reason for the finally
+            
+            if (mFailedResultsCounter > 0 && mIsManualSync) {
+                /// don't let the system synchronization manager retries MANUAL synchronizations
+                //      (be careful: "MANUAL" currently includes the synchronization requested when a new account is created and when the user changes the current account)
+                mSyncResult.tooManyRetries = true;
+                
+                /// notify the user about the failure of MANUAL synchronization
+                notifyFailedSynchronization();
+                
+            }
+            if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
+                notifyFailsInFavourites();
+            }
+            if (mForgottenLocalFiles.size() > 0) {
+                notifyForgottenLocalFiles();
+                
+            }
+            sendStickyBroadcast(false, null, mLastFailedResult);        // message to signal the end to the UI
+        }
+        
+    }
+
+    
+    /**
+     * Called by system SyncManager when a synchronization is required to be cancelled.
+     * 
+     * Sets the mCancellation flag to 'true'. THe synchronization will be stopped when before a new folder is fetched. Data of the last folder
+     * fetched will be still saved in the database. See onPerformSync implementation.
+     */
+    @Override
+    public void onSyncCanceled() {
+        Log_OC.d(TAG, "Synchronization of " + getAccount().name + " has been requested to cancel");
+        mCancellation = true;
+        super.onSyncCanceled();
+    }
+    
+    
+    /**
+     * Updates the locally stored version value of the ownCloud server
+     */
+    private void updateOCVersion() {
+        UpdateOCVersionOperation update = new UpdateOCVersionOperation(getAccount(), getContext());
+        RemoteOperationResult result = update.execute(getClient());
+        if (!result.isSuccess()) {
+            mLastFailedResult = result; 
+        }
+    }
+
+    
+    
+    /**
+     * Synchronize the properties of files and folders contained in a remote folder given by remotePath.
+     * 
+     * @param remotePath        Remote path to the folder to synchronize.
+     * @param parentId          Database Id of the folder to synchronize.
+     */
+    private void fetchData(String remotePath, long parentId) {
+        
+        if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
+            return;
+        
+        // perform folder synchronization
+        SynchronizeFolderOperation synchFolderOp = new SynchronizeFolderOperation(  remotePath, 
+                                                                                    mCurrentSyncTime, 
+                                                                                    parentId, 
+                                                                                    getStorageManager(), 
+                                                                                    getAccount(), 
+                                                                                    getContext()
+                                                                                  );
+        RemoteOperationResult result = synchFolderOp.execute(getClient());
+        
+        
+        // synchronized folder -> notice to UI - ALWAYS, although !result.isSuccess
+        sendStickyBroadcast(true, remotePath, null);
+        
+        if (result.isSuccess() || result.getCode() == ResultCode.SYNC_CONFLICT) {
+            
+            if (result.getCode() == ResultCode.SYNC_CONFLICT) {
+                mConflictsFound += synchFolderOp.getConflictsFound();
+                mFailsInFavouritesFound += synchFolderOp.getFailsInFavouritesFound();
+            }
+            if (synchFolderOp.getForgottenLocalFiles().size() > 0) {
+                mForgottenLocalFiles.putAll(synchFolderOp.getForgottenLocalFiles());
+            }
+            // synchronize children folders 
+            List<OCFile> children = synchFolderOp.getChildren();
+            fetchChildren(children);    // beware of the 'hidden' recursion here!
+            
+        } else {
+            if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED) {
+                mSyncResult.stats.numAuthExceptions++;
+                
+            } else if (result.getException() instanceof DavException) {
+                mSyncResult.stats.numParseExceptions++;
+                
+            } else if (result.getException() instanceof IOException) { 
+                mSyncResult.stats.numIoExceptions++;
+            }
+            mFailedResultsCounter++;
+            mLastFailedResult = result;
+        }
+            
+    }
+
+    /**
+     * Checks if a failed result should terminate the synchronization process immediately, according to
+     * OUR OWN POLICY
+     * 
+     * @param   failedResult        Remote operation result to check.
+     * @return                      'True' if the result should immediately finish the synchronization
+     */
+    private boolean isFinisher(RemoteOperationResult failedResult) {
+        if  (failedResult != null) {
+            RemoteOperationResult.ResultCode code = failedResult.getCode();
+            return (code.equals(RemoteOperationResult.ResultCode.SSL_ERROR) ||
+                    code.equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) ||
+                    code.equals(RemoteOperationResult.ResultCode.BAD_OC_VERSION) ||
+                    code.equals(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED));
+        }
+        return false;
+    }
+
+    /**
+     * Synchronize data of folders in the list of received files
+     * 
+     * @param files         Files to recursively fetch 
+     */
+    private void fetchChildren(List<OCFile> files) {
+        int i;
+        for (i=0; i < files.size() && !mCancellation; i++) {
+            OCFile newFile = files.get(i);
+            if (newFile.isDirectory()) {
+                fetchData(newFile.getRemotePath(), newFile.getFileId());
+            }
+        }
+        if (mCancellation && i <files.size()) Log_OC.d(TAG, "Leaving synchronization before synchronizing " + files.get(i).getRemotePath() + " because cancelation request");
+    }
+
+    
+    /**
+     * Sends a message to any application component interested in the progress of the synchronization.
+     * 
+     * @param inProgress        'True' when the synchronization progress is not finished.
+     * @param dirRemotePath     Remote path of a folder that was just synchronized (with or without success)
+     */
+    private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) {
+        Intent i = new Intent(FileSyncService.SYNC_MESSAGE);
+        i.putExtra(FileSyncService.IN_PROGRESS, inProgress);
+        i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name);
+        if (dirRemotePath != null) {
+            i.putExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH, dirRemotePath);
+        }
+        if (result != null) {
+            i.putExtra(FileSyncService.SYNC_RESULT, result);
+        }
+        getContext().sendStickyBroadcast(i);
+    }
+
+    
+    
+    /**
+     * Notifies the user about a failed synchronization through the status notification bar 
+     */
+    private void notifyFailedSynchronization() {
+        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
+        notification.flags |= Notification.FLAG_AUTO_CANCEL;
+        // TODO put something smart in the contentIntent below
+        notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+        notification.setLatestEventInfo(getContext().getApplicationContext(), 
+                                        getContext().getString(R.string.sync_fail_ticker), 
+                                        String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), 
+                                        notification.contentIntent);
+        ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);
+    }
+
+
+    /**
+     * Notifies the user about conflicts and strange fails when trying to synchronize the contents of kept-in-sync files.
+     * 
+     * By now, we won't consider a failed synchronization.
+     */
+    private void notifyFailsInFavourites() {
+        if (mFailedResultsCounter > 0) {
+            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis());
+            notification.flags |= Notification.FLAG_AUTO_CANCEL;
+            // TODO put something smart in the contentIntent below
+            notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+            notification.setLatestEventInfo(getContext().getApplicationContext(), 
+                                            getContext().getString(R.string.sync_fail_in_favourites_ticker), 
+                                            String.format(getContext().getString(R.string.sync_fail_in_favourites_content), mFailedResultsCounter + mConflictsFound, mConflictsFound), 
+                                            notification.contentIntent);
+            ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification);
+            
+        } else {
+            Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis());
+            notification.flags |= Notification.FLAG_AUTO_CANCEL;
+            // TODO put something smart in the contentIntent below
+            notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+            notification.setLatestEventInfo(getContext().getApplicationContext(), 
+                                            getContext().getString(R.string.sync_conflicts_in_favourites_ticker), 
+                                            String.format(getContext().getString(R.string.sync_conflicts_in_favourites_content), mConflictsFound), 
+                                            notification.contentIntent);
+            ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_conflicts_in_favourites_ticker, notification);
+        } 
+    }
+
+    
+    /**
+     * Notifies the user about local copies of files out of the ownCloud local directory that were 'forgotten' because 
+     * copying them inside the ownCloud local directory was not possible.
+     * 
+     * We don't want links to files out of the ownCloud local directory (foreign files) anymore. It's easy to have 
+     * synchronization problems if a local file is linked to more than one remote file.
+     * 
+     * We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory.
+     */
+    private void notifyForgottenLocalFiles() {
+        Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis());
+        notification.flags |= Notification.FLAG_AUTO_CANCEL;
+
+        /// includes a pending intent in the notification showing a more detailed explanation
+        Intent explanationIntent = new Intent(getContext(), ErrorsWhileCopyingHandlerActivity.class);
+        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_ACCOUNT, getAccount());
+        ArrayList<String> remotePaths = new ArrayList<String>();
+        ArrayList<String> localPaths = new ArrayList<String>();
+        remotePaths.addAll(mForgottenLocalFiles.keySet());
+        localPaths.addAll(mForgottenLocalFiles.values());
+        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_LOCAL_PATHS, localPaths);
+        explanationIntent.putExtra(ErrorsWhileCopyingHandlerActivity.EXTRA_REMOTE_PATHS, remotePaths);  
+        explanationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        
+        notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), explanationIntent, 0);
+        notification.setLatestEventInfo(getContext().getApplicationContext(), 
+                                        getContext().getString(R.string.sync_foreign_files_forgotten_ticker), 
+                                        String.format(getContext().getString(R.string.sync_foreign_files_forgotten_content), mForgottenLocalFiles.size(), getContext().getString(R.string.app_name)), 
+                                        notification.contentIntent);
+        ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_foreign_files_forgotten_ticker, notification);
+        
+    }
+    
+    
+}

+ 2 - 1
src/com/owncloud/android/ui/activity/AccountSelectActivity.java

@@ -50,6 +50,7 @@ import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.authenticator.AccountAuthenticator;
 
 
 import com.owncloud.android.R;
 import com.owncloud.android.R;
@@ -153,7 +154,7 @@ public class AccountSelectActivity extends SherlockListActivity implements
         try {
         try {
             map = (HashMap<String, String>) getListAdapter().getItem(index);
             map = (HashMap<String, String>) getListAdapter().getItem(index);
         } catch (ClassCastException e) {
         } catch (ClassCastException e) {
-            Log.wtf(TAG, "getitem(index) from list adapter did not return hashmap, bailing out");
+            Log_OC.wtf(TAG, "getitem(index) from list adapter did not return hashmap, bailing out");
             return false;
             return false;
         }
         }
         
         

+ 610 - 609
src/com/owncloud/android/ui/activity/AuthenticatorActivity.java

@@ -1,609 +1,610 @@
-/* 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.ui.activity;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import com.owncloud.android.AccountUtils;
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.authenticator.AuthenticationRunnable;
-import com.owncloud.android.authenticator.OnAuthenticationResultListener;
-import com.owncloud.android.authenticator.OnConnectCheckListener;
-import com.owncloud.android.ui.dialog.SslValidatorDialog;
-import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
-import com.owncloud.android.network.OwnCloudClientUtils;
-import com.owncloud.android.operations.ConnectionCheckOperation;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-
-import android.accounts.Account;
-import android.accounts.AccountAuthenticatorActivity;
-import android.accounts.AccountManager;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.ContentResolver;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.preference.PreferenceManager;
-import android.text.InputType;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnFocusChangeListener;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.TextView;
-import com.owncloud.android.R;
-
-import eu.alefzero.webdav.WebdavClient;
-
-/**
- * This Activity is used to add an ownCloud account to the App
- * 
- * @author Bartek Przybylski
- * 
- */
-public class AuthenticatorActivity extends AccountAuthenticatorActivity
-        implements OnAuthenticationResultListener, OnConnectCheckListener, OnRemoteOperationListener, OnSslValidatorListener, 
-        OnFocusChangeListener, OnClickListener {
-
-    private static final int DIALOG_LOGIN_PROGRESS = 0;
-    private static final int DIALOG_SSL_VALIDATOR = 1;
-    private static final int DIALOG_CERT_NOT_SAVED = 2;
-
-    private static final String TAG = "AuthActivity";
-
-    private Thread mAuthThread;
-    private AuthenticationRunnable mAuthRunnable;
-    //private ConnectionCheckerRunnable mConnChkRunnable = null;
-    private ConnectionCheckOperation mConnChkRunnable;
-    private final Handler mHandler = new Handler();
-    private String mBaseUrl;
-    
-    private static final String STATUS_TEXT = "STATUS_TEXT";
-    private static final String STATUS_ICON = "STATUS_ICON";
-    private static final String STATUS_CORRECT = "STATUS_CORRECT";
-    private static final String IS_SSL_CONN = "IS_SSL_CONN";
-    private int mStatusText, mStatusIcon;
-    private boolean mStatusCorrect, mIsSslConn;
-    private RemoteOperationResult mLastSslUntrustedServerResult;
-
-    public static final String PARAM_USERNAME = "param_Username";
-    public static final String PARAM_HOSTNAME = "param_Hostname";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
-        setContentView(R.layout.account_setup);
-        ImageView iv = (ImageView) findViewById(R.id.refreshButton);
-        ImageView iv2 = (ImageView) findViewById(R.id.viewPassword);
-        TextView tv = (TextView) findViewById(R.id.host_URL);
-        TextView tv2 = (TextView) findViewById(R.id.account_password);
-
-        if (savedInstanceState != null) {
-            mStatusIcon = savedInstanceState.getInt(STATUS_ICON);
-            mStatusText = savedInstanceState.getInt(STATUS_TEXT);
-            mStatusCorrect = savedInstanceState.getBoolean(STATUS_CORRECT);
-            mIsSslConn = savedInstanceState.getBoolean(IS_SSL_CONN);
-            setResultIconAndText(mStatusIcon, mStatusText);
-            findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
-            if (!mStatusCorrect)
-                iv.setVisibility(View.VISIBLE);
-            else
-                iv.setVisibility(View.INVISIBLE);
-
-        } else {
-            mStatusText = mStatusIcon = 0;
-            mStatusCorrect = false;
-            mIsSslConn = false;
-        }
-        iv.setOnClickListener(this);
-        iv2.setOnClickListener(this);
-        tv.setOnFocusChangeListener(this);
-        tv2.setOnFocusChangeListener(this);
-
-        Button b = (Button) findViewById(R.id.account_register);
-        if (b != null) {
-            b.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));
-        }
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        outState.putInt(STATUS_ICON, mStatusIcon);
-        outState.putInt(STATUS_TEXT, mStatusText);
-        outState.putBoolean(STATUS_CORRECT, mStatusCorrect);
-        super.onSaveInstanceState(outState);
-    }
-
-    @Override
-    protected Dialog onCreateDialog(int id) {
-        Dialog dialog = null;
-        switch (id) {
-        case DIALOG_LOGIN_PROGRESS: {
-            ProgressDialog working_dialog = new ProgressDialog(this);
-            working_dialog.setMessage(getResources().getString(
-                    R.string.auth_trying_to_login));
-            working_dialog.setIndeterminate(true);
-            working_dialog.setCancelable(true);
-            working_dialog
-                    .setOnCancelListener(new DialogInterface.OnCancelListener() {
-                        @Override
-                        public void onCancel(DialogInterface dialog) {
-                            Log.i(TAG, "Login canceled");
-                            if (mAuthThread != null) {
-                                mAuthThread.interrupt();
-                                finish();
-                            }
-                        }
-                    });
-            dialog = working_dialog;
-            break;
-        }
-        case DIALOG_SSL_VALIDATOR: {
-            dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this);
-            break;
-        }
-        case DIALOG_CERT_NOT_SAVED: {
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            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();
-                    };
-                });
-            dialog = builder.create();
-            break;
-        }
-        default:
-            Log.e(TAG, "Incorrect dialog called with id = " + id);
-        }
-        return dialog;
-    }
-
-    @Override
-    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
-        switch (id) {
-        case DIALOG_LOGIN_PROGRESS:
-        case DIALOG_CERT_NOT_SAVED:
-            break;
-        case DIALOG_SSL_VALIDATOR: {
-            ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);
-            break;
-        }
-        default:
-            Log.e(TAG, "Incorrect dialog called with id = " + id);
-        }
-    }
-
-    public void onAuthenticationResult(boolean success, String message) {
-        if (success) {
-            TextView username_text = (TextView) findViewById(R.id.account_username), password_text = (TextView) findViewById(R.id.account_password);
-
-            URL url;
-            try {
-                url = new URL(message);
-            } catch (MalformedURLException e) {
-                // should never happen
-                Log.e(getClass().getName(), "Malformed URL: " + message);
-                return;
-            }
-
-            String username = username_text.getText().toString().trim();
-            String accountName = username + "@" + url.getHost();
-            if (url.getPort() >= 0) {
-                accountName += ":" + url.getPort();
-            }
-            Account account = new Account(accountName,
-                    AccountAuthenticator.ACCOUNT_TYPE);
-            AccountManager accManager = AccountManager.get(this);
-            accManager.addAccountExplicitly(account, password_text.getText()
-                    .toString(), null);
-
-            // Add this account as default in the preferences, if there is none
-            // already
-            Account defaultAccount = AccountUtils
-                    .getCurrentOwnCloudAccount(this);
-            if (defaultAccount == null) {
-                SharedPreferences.Editor editor = PreferenceManager
-                        .getDefaultSharedPreferences(this).edit();
-                editor.putString("select_oc_account", accountName);
-                editor.commit();
-            }
-
-            final Intent intent = new Intent();
-            intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE,
-                    AccountAuthenticator.ACCOUNT_TYPE);
-            intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
-            intent.putExtra(AccountManager.KEY_AUTHTOKEN,
-                    AccountAuthenticator.ACCOUNT_TYPE);
-            intent.putExtra(AccountManager.KEY_USERDATA, username);
-
-            accManager.setUserData(account,
-                    AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable
-                            .getDiscoveredVersion().toString());
-            
-            accManager.setUserData(account,
-                    AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);
-
-            setAccountAuthenticatorResult(intent.getExtras());
-            setResult(RESULT_OK, intent);
-            Bundle bundle = new Bundle();
-            bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-            //getContentResolver().startSync(ProviderTableMeta.CONTENT_URI,
-            //        bundle);
-            ContentResolver.requestSync(account, "org.owncloud", bundle);
-
-            /*
-             * if
-             * (mConnChkRunnable.getDiscoveredVersion().compareTo(OwnCloudVersion
-             * .owncloud_v2) >= 0) { Intent i = new Intent(this,
-             * ExtensionsAvailableActivity.class); startActivity(i); }
-             */
-
-            finish();
-        } else {
-            try {
-                dismissDialog(DIALOG_LOGIN_PROGRESS);
-            } catch (IllegalArgumentException e) {
-                // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens
-            }
-            TextView tv = (TextView) findViewById(R.id.account_username);
-            tv.setError(message + "        ");  // the extra spaces are a workaround for an ugly bug: 
-                                                // 1. insert wrong credentials and connect
-                                                // 2. put the focus on the user name field with using hardware controls (don't touch the screen); the error is shown UNDER the field
-                                                // 3. touch the user name field; the software keyboard appears; the error popup is moved OVER the field and SHRINKED in width, losing the last word
-                                                // Seen, at least, in Android 2.x devices
-        }
-    }
-    public void onCancelClick(View view) {
-        setResult(RESULT_CANCELED);
-        finish();
-    }
-    
-    public void onOkClick(View view) {
-        String prefix = "";
-        String url = ((TextView) findViewById(R.id.host_URL)).getText()
-                .toString().trim();
-        if (mIsSslConn) {
-            prefix = "https://";
-        } else {
-            prefix = "http://";
-        }
-        if (url.toLowerCase().startsWith("http://")
-                || url.toLowerCase().startsWith("https://")) {
-            prefix = "";
-        }
-        continueConnection(prefix);
-    }
-    
-    public void onRegisterClick(View view) {
-        Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_account_register)));
-        setResult(RESULT_CANCELED);
-        startActivity(register);
-    }
-
-    private void continueConnection(String prefix) {
-        String url = ((TextView) findViewById(R.id.host_URL)).getText()
-                .toString().trim();
-        String username = ((TextView) findViewById(R.id.account_username))
-                .getText().toString();
-        String password = ((TextView) findViewById(R.id.account_password))
-                .getText().toString();
-        if (url.endsWith("/"))
-            url = url.substring(0, url.length() - 1);
-
-        URL uri = null;
-        String webdav_path = AccountUtils.getWebdavPath(mConnChkRunnable
-                .getDiscoveredVersion());
-        
-        if (webdav_path == null) {
-            onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));
-            return;
-        }
-        
-        try {
-            mBaseUrl = prefix + url;
-            String url_str = prefix + url + webdav_path;
-            uri = new URL(url_str);
-        } catch (MalformedURLException e) {
-            // should never happen
-            onAuthenticationResult(false, getString(R.string.auth_incorrect_address_title));
-            return;
-        }
-
-        showDialog(DIALOG_LOGIN_PROGRESS);
-        mAuthRunnable = new AuthenticationRunnable(uri, username, password, this);
-        mAuthRunnable.setOnAuthenticationResultListener(this, mHandler);
-        mAuthThread = new Thread(mAuthRunnable);
-        mAuthThread.start();
-    }
-
-    @Override
-    public void onConnectionCheckResult(ResultType type) {
-        mStatusText = mStatusIcon = 0;
-        mStatusCorrect = false;
-        String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
-                .toString().trim().toLowerCase();
-
-        switch (type) {
-        case OK_SSL:
-            mIsSslConn = true;
-            mStatusIcon = android.R.drawable.ic_secure;
-            mStatusText = R.string.auth_secure_connection;
-            mStatusCorrect = true;
-            break;
-        case OK_NO_SSL:
-            mIsSslConn = false;
-            mStatusCorrect = true;
-            if (t_url.startsWith("http://") ) {
-                mStatusText = R.string.auth_connection_established;
-                mStatusIcon = R.drawable.ic_ok;
-            } else {
-                mStatusText = R.string.auth_nossl_plain_ok_title;
-                mStatusIcon = android.R.drawable.ic_partial_secure;
-            }
-            break;
-        case BAD_OC_VERSION:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_bad_oc_version_title;
-            break;
-        case WRONG_CONNECTION:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_wrong_connection_title;
-            break;
-        case TIMEOUT:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_timeout_title;
-            break;
-        case INCORRECT_ADDRESS:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_incorrect_address_title;
-            break;
-        case SSL_UNVERIFIED_SERVER:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_ssl_unverified_server_title;
-            break;
-        case SSL_INIT_ERROR:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_ssl_general_error_title;
-            break;
-        case HOST_NOT_AVAILABLE:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_unknown_host_title;
-            break;
-        case NO_NETWORK_CONNECTION:
-            mStatusIcon = R.drawable.no_network;
-            mStatusText = R.string.auth_no_net_conn_title;
-            break;
-        case INSTANCE_NOT_CONFIGURED:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_not_configured_title;
-            break;
-        case UNKNOWN_ERROR:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_unknown_error_title;
-            break;
-        case FILE_NOT_FOUND:
-            mStatusIcon = R.drawable.common_error;
-            mStatusText = R.string.auth_incorrect_path_title;
-            break;
-        default:
-            Log.e(TAG, "Incorrect connection checker result type: " + type);
-        }
-        setResultIconAndText(mStatusIcon, mStatusText);
-        if (!mStatusCorrect)
-            findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
-        else
-            findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
-        findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
-    }
-
-    @Override
-    public void onFocusChange(View view, boolean hasFocus) {
-        if (view.getId() == R.id.host_URL) {
-            if (!hasFocus) {
-                TextView tv = ((TextView) findViewById(R.id.host_URL));
-                String uri = tv.getText().toString().trim();
-                if (uri.length() != 0) {
-                    setResultIconAndText(R.drawable.progress_small,
-                            R.string.auth_testing_connection);
-                    //mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);
-                    mConnChkRunnable = new ConnectionCheckOperation(uri, this);
-                    //mConnChkRunnable.setListener(this, mHandler);
-                    //mAuthThread = new Thread(mConnChkRunnable);
-                    //mAuthThread.start();
-            		WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);
-                    mAuthThread = mConnChkRunnable.execute(client, this, mHandler);
-                } else {
-                    findViewById(R.id.refreshButton).setVisibility(
-                            View.INVISIBLE);
-                    setResultIconAndText(0, 0);
-                }
-            } else {
-                // avoids that the 'connect' button can be clicked if the test was previously passed
-                findViewById(R.id.buttonOK).setEnabled(false); 
-            }
-        } else if (view.getId() == R.id.account_password) {
-            ImageView iv = (ImageView) findViewById(R.id.viewPassword);
-            if (hasFocus) {
-                iv.setVisibility(View.VISIBLE);
-            } else {
-                TextView v = (TextView) findViewById(R.id.account_password);
-                int input_type = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_PASSWORD;
-                v.setInputType(input_type);
-                iv.setVisibility(View.INVISIBLE);
-            }
-        }
-    }
-
-    private void setResultIconAndText(int drawable_id, int text_id) {
-        ImageView iv = (ImageView) findViewById(R.id.action_indicator);
-        TextView tv = (TextView) findViewById(R.id.status_text);
-
-        if (drawable_id == 0 && text_id == 0) {
-            iv.setVisibility(View.INVISIBLE);
-            tv.setVisibility(View.INVISIBLE);
-        } else {
-            iv.setImageResource(drawable_id);
-            tv.setText(text_id);
-            iv.setVisibility(View.VISIBLE);
-            tv.setVisibility(View.VISIBLE);
-        }
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.refreshButton) {
-            onFocusChange(findViewById(R.id.host_URL), false);
-        } else if (v.getId() == R.id.viewPassword) {
-            EditText view = (EditText) findViewById(R.id.account_password);
-            int selectionStart = view.getSelectionStart();
-            int selectionEnd = view.getSelectionEnd();
-            int input_type = view.getInputType();
-            if ((input_type & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
-                input_type = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_PASSWORD;
-            } else {
-                input_type = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
-            }
-            view.setInputType(input_type);
-            view.setSelection(selectionStart, selectionEnd);
-        }
-    }
-
-	@Override
-	public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
-		if (operation.equals(mConnChkRunnable)) {
-		    
-	        mStatusText = mStatusIcon = 0;
-	        mStatusCorrect = false;
-	        String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
-	                .toString().trim().toLowerCase();
-	        
-	        switch (result.getCode()) {
-	        case OK_SSL:
-	            mIsSslConn = true;
-	            mStatusIcon = android.R.drawable.ic_secure;
-	            mStatusText = R.string.auth_secure_connection;
-	            mStatusCorrect = true;
-	            break;
-	            
-	        case OK_NO_SSL:
-	        case OK:
-	            mIsSslConn = false;
-	            mStatusCorrect = true;
-	            if (t_url.startsWith("http://") ) {
-	                mStatusText = R.string.auth_connection_established;
-	                mStatusIcon = R.drawable.ic_ok;
-	            } else {
-	                mStatusText = R.string.auth_nossl_plain_ok_title;
-	                mStatusIcon = android.R.drawable.ic_partial_secure;
-	            }
-	            break;
-	        
-	            
-	        case BAD_OC_VERSION:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_bad_oc_version_title;
-	            break;
-	        case WRONG_CONNECTION:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_wrong_connection_title;
-	            break;
-	        case TIMEOUT:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_timeout_title;
-	            break;
-	        case INCORRECT_ADDRESS:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_incorrect_address_title;
-	            break;
-	            
-            case SSL_RECOVERABLE_PEER_UNVERIFIED:
-                mStatusIcon = R.drawable.common_error;
-                mStatusText = R.string.auth_ssl_unverified_server_title;
-                mLastSslUntrustedServerResult = result;
-                showDialog(DIALOG_SSL_VALIDATOR); 
-                break;
-	            
-            case SSL_ERROR:
-                mStatusIcon = R.drawable.common_error;
-                mStatusText = R.string.auth_ssl_general_error_title;
-                break;
-                
-	        case HOST_NOT_AVAILABLE:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_unknown_host_title;
-	            break;
-	        case NO_NETWORK_CONNECTION:
-	            mStatusIcon = R.drawable.no_network;
-	            mStatusText = R.string.auth_no_net_conn_title;
-	            break;
-	        case INSTANCE_NOT_CONFIGURED:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_not_configured_title;
-	            break;
-	        case FILE_NOT_FOUND:
-	            mStatusIcon = R.drawable.common_error;
-	            mStatusText = R.string.auth_incorrect_path_title;
-	            break;
-            case UNHANDLED_HTTP_CODE:
-            case UNKNOWN_ERROR:
-                mStatusIcon = R.drawable.common_error;
-                mStatusText = R.string.auth_unknown_error_title;
-                break;
-	        default:
-	            Log.e(TAG, "Incorrect connection checker result type: " + result.getHttpCode());
-	        }
-	        setResultIconAndText(mStatusIcon, mStatusText);
-	        if (!mStatusCorrect)
-	            findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
-	        else
-	            findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
-	        findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
-		}
-	}
-
-	
-    public void onSavedCertificate() {
-        mAuthThread = mConnChkRunnable.retry(this, mHandler);                
-    }
-
-    @Override
-    public void onFailedSavingCertificate() {
-        showDialog(DIALOG_CERT_NOT_SAVED);
-    }
-    
-}
+/* 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.ui.activity;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.authenticator.AuthenticationRunnable;
+import com.owncloud.android.authenticator.OnAuthenticationResultListener;
+import com.owncloud.android.authenticator.OnConnectCheckListener;
+import com.owncloud.android.ui.dialog.SslValidatorDialog;
+import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.ConnectionCheckOperation;
+import com.owncloud.android.operations.OnRemoteOperationListener;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
+
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorActivity;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.ContentResolver;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.text.InputType;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.owncloud.android.R;
+
+import eu.alefzero.webdav.WebdavClient;
+
+/**
+ * This Activity is used to add an ownCloud account to the App
+ * 
+ * @author Bartek Przybylski
+ * 
+ */
+public class AuthenticatorActivity extends AccountAuthenticatorActivity
+        implements OnAuthenticationResultListener, OnConnectCheckListener, OnRemoteOperationListener, OnSslValidatorListener, 
+        OnFocusChangeListener, OnClickListener {
+
+    private static final int DIALOG_LOGIN_PROGRESS = 0;
+    private static final int DIALOG_SSL_VALIDATOR = 1;
+    private static final int DIALOG_CERT_NOT_SAVED = 2;
+
+    private static final String TAG = "AuthActivity";
+
+    private Thread mAuthThread;
+    private AuthenticationRunnable mAuthRunnable;
+    //private ConnectionCheckerRunnable mConnChkRunnable = null;
+    private ConnectionCheckOperation mConnChkRunnable;
+    private final Handler mHandler = new Handler();
+    private String mBaseUrl;
+    
+    private static final String STATUS_TEXT = "STATUS_TEXT";
+    private static final String STATUS_ICON = "STATUS_ICON";
+    private static final String STATUS_CORRECT = "STATUS_CORRECT";
+    private static final String IS_SSL_CONN = "IS_SSL_CONN";
+    private int mStatusText, mStatusIcon;
+    private boolean mStatusCorrect, mIsSslConn;
+    private RemoteOperationResult mLastSslUntrustedServerResult;
+
+    public static final String PARAM_USERNAME = "param_Username";
+    public static final String PARAM_HOSTNAME = "param_Hostname";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.account_setup);
+        ImageView iv = (ImageView) findViewById(R.id.refreshButton);
+        ImageView iv2 = (ImageView) findViewById(R.id.viewPassword);
+        TextView tv = (TextView) findViewById(R.id.host_URL);
+        TextView tv2 = (TextView) findViewById(R.id.account_password);
+
+        if (savedInstanceState != null) {
+            mStatusIcon = savedInstanceState.getInt(STATUS_ICON);
+            mStatusText = savedInstanceState.getInt(STATUS_TEXT);
+            mStatusCorrect = savedInstanceState.getBoolean(STATUS_CORRECT);
+            mIsSslConn = savedInstanceState.getBoolean(IS_SSL_CONN);
+            setResultIconAndText(mStatusIcon, mStatusText);
+            findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
+            if (!mStatusCorrect)
+                iv.setVisibility(View.VISIBLE);
+            else
+                iv.setVisibility(View.INVISIBLE);
+
+        } else {
+            mStatusText = mStatusIcon = 0;
+            mStatusCorrect = false;
+            mIsSslConn = false;
+        }
+        iv.setOnClickListener(this);
+        iv2.setOnClickListener(this);
+        tv.setOnFocusChangeListener(this);
+        tv2.setOnFocusChangeListener(this);
+
+        Button b = (Button) findViewById(R.id.account_register);
+        if (b != null) {
+            b.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putInt(STATUS_ICON, mStatusIcon);
+        outState.putInt(STATUS_TEXT, mStatusText);
+        outState.putBoolean(STATUS_CORRECT, mStatusCorrect);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        Dialog dialog = null;
+        switch (id) {
+        case DIALOG_LOGIN_PROGRESS: {
+            ProgressDialog working_dialog = new ProgressDialog(this);
+            working_dialog.setMessage(getResources().getString(
+                    R.string.auth_trying_to_login));
+            working_dialog.setIndeterminate(true);
+            working_dialog.setCancelable(true);
+            working_dialog
+                    .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            Log_OC.i(TAG, "Login canceled");
+                            if (mAuthThread != null) {
+                                mAuthThread.interrupt();
+                                finish();
+                            }
+                        }
+                    });
+            dialog = working_dialog;
+            break;
+        }
+        case DIALOG_SSL_VALIDATOR: {
+            dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this);
+            break;
+        }
+        case DIALOG_CERT_NOT_SAVED: {
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            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();
+                    };
+                });
+            dialog = builder.create();
+            break;
+        }
+        default:
+            Log_OC.e(TAG, "Incorrect dialog called with id = " + id);
+        }
+        return dialog;
+    }
+
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+        switch (id) {
+        case DIALOG_LOGIN_PROGRESS:
+        case DIALOG_CERT_NOT_SAVED:
+            break;
+        case DIALOG_SSL_VALIDATOR: {
+            ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);
+            break;
+        }
+        default:
+            Log_OC.e(TAG, "Incorrect dialog called with id = " + id);
+        }
+    }
+
+    public void onAuthenticationResult(boolean success, String message) {
+        if (success) {
+            TextView username_text = (TextView) findViewById(R.id.account_username), password_text = (TextView) findViewById(R.id.account_password);
+
+            URL url;
+            try {
+                url = new URL(message);
+            } catch (MalformedURLException e) {
+                // should never happen
+                Log_OC.e(getClass().getName(), "Malformed URL: " + message);
+                return;
+            }
+
+            String username = username_text.getText().toString().trim();
+            String accountName = username + "@" + url.getHost();
+            if (url.getPort() >= 0) {
+                accountName += ":" + url.getPort();
+            }
+            Account account = new Account(accountName,
+                    AccountAuthenticator.ACCOUNT_TYPE);
+            AccountManager accManager = AccountManager.get(this);
+            accManager.addAccountExplicitly(account, password_text.getText()
+                    .toString(), null);
+
+            // Add this account as default in the preferences, if there is none
+            // already
+            Account defaultAccount = AccountUtils
+                    .getCurrentOwnCloudAccount(this);
+            if (defaultAccount == null) {
+                SharedPreferences.Editor editor = PreferenceManager
+                        .getDefaultSharedPreferences(this).edit();
+                editor.putString("select_oc_account", accountName);
+                editor.commit();
+            }
+
+            final Intent intent = new Intent();
+            intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE,
+                    AccountAuthenticator.ACCOUNT_TYPE);
+            intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);
+            intent.putExtra(AccountManager.KEY_AUTHTOKEN,
+                    AccountAuthenticator.ACCOUNT_TYPE);
+            intent.putExtra(AccountManager.KEY_USERDATA, username);
+
+            accManager.setUserData(account,
+                    AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable
+                            .getDiscoveredVersion().toString());
+            
+            accManager.setUserData(account,
+                    AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);
+
+            setAccountAuthenticatorResult(intent.getExtras());
+            setResult(RESULT_OK, intent);
+            Bundle bundle = new Bundle();
+            bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+            //getContentResolver().startSync(ProviderTableMeta.CONTENT_URI,
+            //        bundle);
+            ContentResolver.requestSync(account, "org.owncloud", bundle);
+
+            /*
+             * if
+             * (mConnChkRunnable.getDiscoveredVersion().compareTo(OwnCloudVersion
+             * .owncloud_v2) >= 0) { Intent i = new Intent(this,
+             * ExtensionsAvailableActivity.class); startActivity(i); }
+             */
+
+            finish();
+        } else {
+            try {
+                dismissDialog(DIALOG_LOGIN_PROGRESS);
+            } catch (IllegalArgumentException e) {
+                // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens
+            }
+            TextView tv = (TextView) findViewById(R.id.account_username);
+            tv.setError(message + "        ");  // the extra spaces are a workaround for an ugly bug: 
+                                                // 1. insert wrong credentials and connect
+                                                // 2. put the focus on the user name field with using hardware controls (don't touch the screen); the error is shown UNDER the field
+                                                // 3. touch the user name field; the software keyboard appears; the error popup is moved OVER the field and SHRINKED in width, losing the last word
+                                                // Seen, at least, in Android 2.x devices
+        }
+    }
+    public void onCancelClick(View view) {
+        setResult(RESULT_CANCELED);
+        finish();
+    }
+    
+    public void onOkClick(View view) {
+        String prefix = "";
+        String url = ((TextView) findViewById(R.id.host_URL)).getText()
+                .toString().trim();
+        if (mIsSslConn) {
+            prefix = "https://";
+        } else {
+            prefix = "http://";
+        }
+        if (url.toLowerCase().startsWith("http://")
+                || url.toLowerCase().startsWith("https://")) {
+            prefix = "";
+        }
+        continueConnection(prefix);
+    }
+    
+    public void onRegisterClick(View view) {
+        Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_account_register)));
+        setResult(RESULT_CANCELED);
+        startActivity(register);
+    }
+
+    private void continueConnection(String prefix) {
+        String url = ((TextView) findViewById(R.id.host_URL)).getText()
+                .toString().trim();
+        String username = ((TextView) findViewById(R.id.account_username))
+                .getText().toString();
+        String password = ((TextView) findViewById(R.id.account_password))
+                .getText().toString();
+        if (url.endsWith("/"))
+            url = url.substring(0, url.length() - 1);
+
+        URL uri = null;
+        String webdav_path = AccountUtils.getWebdavPath(mConnChkRunnable
+                .getDiscoveredVersion());
+        
+        if (webdav_path == null) {
+            onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));
+            return;
+        }
+        
+        try {
+            mBaseUrl = prefix + url;
+            String url_str = prefix + url + webdav_path;
+            uri = new URL(url_str);
+        } catch (MalformedURLException e) {
+            // should never happen
+            onAuthenticationResult(false, getString(R.string.auth_incorrect_address_title));
+            return;
+        }
+
+        showDialog(DIALOG_LOGIN_PROGRESS);
+        mAuthRunnable = new AuthenticationRunnable(uri, username, password, this);
+        mAuthRunnable.setOnAuthenticationResultListener(this, mHandler);
+        mAuthThread = new Thread(mAuthRunnable);
+        mAuthThread.start();
+    }
+
+    @Override
+    public void onConnectionCheckResult(ResultType type) {
+        mStatusText = mStatusIcon = 0;
+        mStatusCorrect = false;
+        String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
+                .toString().trim().toLowerCase();
+
+        switch (type) {
+        case OK_SSL:
+            mIsSslConn = true;
+            mStatusIcon = android.R.drawable.ic_secure;
+            mStatusText = R.string.auth_secure_connection;
+            mStatusCorrect = true;
+            break;
+        case OK_NO_SSL:
+            mIsSslConn = false;
+            mStatusCorrect = true;
+            if (t_url.startsWith("http://") ) {
+                mStatusText = R.string.auth_connection_established;
+                mStatusIcon = R.drawable.ic_ok;
+            } else {
+                mStatusText = R.string.auth_nossl_plain_ok_title;
+                mStatusIcon = android.R.drawable.ic_partial_secure;
+            }
+            break;
+        case BAD_OC_VERSION:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_bad_oc_version_title;
+            break;
+        case WRONG_CONNECTION:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_wrong_connection_title;
+            break;
+        case TIMEOUT:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_timeout_title;
+            break;
+        case INCORRECT_ADDRESS:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_incorrect_address_title;
+            break;
+        case SSL_UNVERIFIED_SERVER:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_ssl_unverified_server_title;
+            break;
+        case SSL_INIT_ERROR:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_ssl_general_error_title;
+            break;
+        case HOST_NOT_AVAILABLE:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_unknown_host_title;
+            break;
+        case NO_NETWORK_CONNECTION:
+            mStatusIcon = R.drawable.no_network;
+            mStatusText = R.string.auth_no_net_conn_title;
+            break;
+        case INSTANCE_NOT_CONFIGURED:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_not_configured_title;
+            break;
+        case UNKNOWN_ERROR:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_unknown_error_title;
+            break;
+        case FILE_NOT_FOUND:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_incorrect_path_title;
+            break;
+        default:
+            Log_OC.e(TAG, "Incorrect connection checker result type: " + type);
+        }
+        setResultIconAndText(mStatusIcon, mStatusText);
+        if (!mStatusCorrect)
+            findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
+        else
+            findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
+        findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
+    }
+
+    @Override
+    public void onFocusChange(View view, boolean hasFocus) {
+        if (view.getId() == R.id.host_URL) {
+            if (!hasFocus) {
+                TextView tv = ((TextView) findViewById(R.id.host_URL));
+                String uri = tv.getText().toString().trim();
+                if (uri.length() != 0) {
+                    setResultIconAndText(R.drawable.progress_small,
+                            R.string.auth_testing_connection);
+                    //mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);
+                    mConnChkRunnable = new ConnectionCheckOperation(uri, this);
+                    //mConnChkRunnable.setListener(this, mHandler);
+                    //mAuthThread = new Thread(mConnChkRunnable);
+                    //mAuthThread.start();
+            		WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);
+                    mAuthThread = mConnChkRunnable.execute(client, this, mHandler);
+                } else {
+                    findViewById(R.id.refreshButton).setVisibility(
+                            View.INVISIBLE);
+                    setResultIconAndText(0, 0);
+                }
+            } else {
+                // avoids that the 'connect' button can be clicked if the test was previously passed
+                findViewById(R.id.buttonOK).setEnabled(false); 
+            }
+        } else if (view.getId() == R.id.account_password) {
+            ImageView iv = (ImageView) findViewById(R.id.viewPassword);
+            if (hasFocus) {
+                iv.setVisibility(View.VISIBLE);
+            } else {
+                TextView v = (TextView) findViewById(R.id.account_password);
+                int input_type = InputType.TYPE_CLASS_TEXT
+                        | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+                v.setInputType(input_type);
+                iv.setVisibility(View.INVISIBLE);
+            }
+        }
+    }
+
+    private void setResultIconAndText(int drawable_id, int text_id) {
+        ImageView iv = (ImageView) findViewById(R.id.action_indicator);
+        TextView tv = (TextView) findViewById(R.id.status_text);
+
+        if (drawable_id == 0 && text_id == 0) {
+            iv.setVisibility(View.INVISIBLE);
+            tv.setVisibility(View.INVISIBLE);
+        } else {
+            iv.setImageResource(drawable_id);
+            tv.setText(text_id);
+            iv.setVisibility(View.VISIBLE);
+            tv.setVisibility(View.VISIBLE);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.refreshButton) {
+            onFocusChange(findViewById(R.id.host_URL), false);
+        } else if (v.getId() == R.id.viewPassword) {
+            EditText view = (EditText) findViewById(R.id.account_password);
+            int selectionStart = view.getSelectionStart();
+            int selectionEnd = view.getSelectionEnd();
+            int input_type = view.getInputType();
+            if ((input_type & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
+                input_type = InputType.TYPE_CLASS_TEXT
+                        | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+            } else {
+                input_type = InputType.TYPE_CLASS_TEXT
+                        | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
+            }
+            view.setInputType(input_type);
+            view.setSelection(selectionStart, selectionEnd);
+        }
+    }
+
+	@Override
+	public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+		if (operation.equals(mConnChkRunnable)) {
+		    
+	        mStatusText = mStatusIcon = 0;
+	        mStatusCorrect = false;
+	        String t_url = ((TextView) findViewById(R.id.host_URL)).getText()
+	                .toString().trim().toLowerCase();
+	        
+	        switch (result.getCode()) {
+	        case OK_SSL:
+	            mIsSslConn = true;
+	            mStatusIcon = android.R.drawable.ic_secure;
+	            mStatusText = R.string.auth_secure_connection;
+	            mStatusCorrect = true;
+	            break;
+	            
+	        case OK_NO_SSL:
+	        case OK:
+	            mIsSslConn = false;
+	            mStatusCorrect = true;
+	            if (t_url.startsWith("http://") ) {
+	                mStatusText = R.string.auth_connection_established;
+	                mStatusIcon = R.drawable.ic_ok;
+	            } else {
+	                mStatusText = R.string.auth_nossl_plain_ok_title;
+	                mStatusIcon = android.R.drawable.ic_partial_secure;
+	            }
+	            break;
+	        
+	            
+	        case BAD_OC_VERSION:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_bad_oc_version_title;
+	            break;
+	        case WRONG_CONNECTION:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_wrong_connection_title;
+	            break;
+	        case TIMEOUT:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_timeout_title;
+	            break;
+	        case INCORRECT_ADDRESS:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_incorrect_address_title;
+	            break;
+	            
+            case SSL_RECOVERABLE_PEER_UNVERIFIED:
+                mStatusIcon = R.drawable.common_error;
+                mStatusText = R.string.auth_ssl_unverified_server_title;
+                mLastSslUntrustedServerResult = result;
+                showDialog(DIALOG_SSL_VALIDATOR); 
+                break;
+	            
+            case SSL_ERROR:
+                mStatusIcon = R.drawable.common_error;
+                mStatusText = R.string.auth_ssl_general_error_title;
+                break;
+                
+	        case HOST_NOT_AVAILABLE:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_unknown_host_title;
+	            break;
+	        case NO_NETWORK_CONNECTION:
+	            mStatusIcon = R.drawable.no_network;
+	            mStatusText = R.string.auth_no_net_conn_title;
+	            break;
+	        case INSTANCE_NOT_CONFIGURED:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_not_configured_title;
+	            break;
+	        case FILE_NOT_FOUND:
+	            mStatusIcon = R.drawable.common_error;
+	            mStatusText = R.string.auth_incorrect_path_title;
+	            break;
+            case UNHANDLED_HTTP_CODE:
+            case UNKNOWN_ERROR:
+                mStatusIcon = R.drawable.common_error;
+                mStatusText = R.string.auth_unknown_error_title;
+                break;
+	        default:
+	            Log_OC.e(TAG, "Incorrect connection checker result type: " + result.getHttpCode());
+	        }
+	        setResultIconAndText(mStatusIcon, mStatusText);
+	        if (!mStatusCorrect)
+	            findViewById(R.id.refreshButton).setVisibility(View.VISIBLE);
+	        else
+	            findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);
+	        findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);
+		}
+	}
+
+	
+    public void onSavedCertificate() {
+        mAuthThread = mConnChkRunnable.retry(this, mHandler);                
+    }
+
+    @Override
+    public void onFailedSavingCertificate() {
+        showDialog(DIALOG_CERT_NOT_SAVED);
+    }
+    
+}

+ 2 - 2
src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java

@@ -20,6 +20,7 @@
 package com.owncloud.android.ui.activity;
 package com.owncloud.android.ui.activity;
 
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
@@ -29,7 +30,6 @@ import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionM
 import android.accounts.Account;
 import android.accounts.Account;
 import android.content.Intent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Bundle;
-import android.util.Log;
 
 
 /**
 /**
  * Wrapper activity which will be launched if keep-in-sync file will be modified by external
  * Wrapper activity which will be launched if keep-in-sync file will be modified by external
@@ -79,7 +79,7 @@ public class ConflictsResolveActivity extends SherlockFragmentActivity implement
                 i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
                 i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
                 break;
                 break;
             default:
             default:
-                Log.wtf(TAG, "Unhandled conflict decision " + decision);
+                Log_OC.wtf(TAG, "Unhandled conflict decision " + decision);
                 return;
                 return;
         }
         }
         i.putExtra(FileUploader.KEY_ACCOUNT, mOCAccount);
         i.putExtra(FileUploader.KEY_ACCOUNT, mOCAccount);

+ 4 - 3
src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java

@@ -41,6 +41,7 @@ import android.widget.TextView;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
@@ -182,16 +183,16 @@ public class ErrorsWhileCopyingHandlerActivity  extends SherlockFragmentActivity
     public void onClick(View v) {
     public void onClick(View v) {
         if (v.getId() == R.id.ok) {
         if (v.getId() == R.id.ok) {
             /// perform movement operation in background thread
             /// perform movement operation in background thread
-            Log.d(TAG, "Clicked MOVE, start movement");
+            Log_OC.d(TAG, "Clicked MOVE, start movement");
             new MoveFilesTask().execute();            
             new MoveFilesTask().execute();            
             
             
         } else if (v.getId() == R.id.cancel) {
         } else if (v.getId() == R.id.cancel) {
             /// just finish
             /// just finish
-            Log.d(TAG, "Clicked CANCEL, bye");
+            Log_OC.d(TAG, "Clicked CANCEL, bye");
             finish();
             finish();
             
             
         } else {
         } else {
-            Log.e(TAG, "Clicked phantom button, id: " + v.getId());
+            Log_OC.e(TAG, "Clicked phantom button, id: " + v.getId());
         }
         }
     }
     }
 
 

+ 392 - 395
src/com/owncloud/android/ui/activity/FileDetailActivity.java

@@ -1,395 +1,392 @@
-/* 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.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 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) {
-            setContentView(R.layout.file_activity_details);
-        
-            ActionBar actionBar = getSupportActionBar();
-            actionBar.setDisplayHomeAsUpEnabled(true);
-
-            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(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.d(TAG, "Download service connected");
-                mDownloaderBinder = (FileDownloaderBinder) service;
-                if (mWaitingToPreview) {
-                    requestForDownload();
-                }
-                    
-            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
-                Log.d(TAG, "Upload service connected");
-                mUploaderBinder = (FileUploaderBinder) service;
-            } else {
-                return;
-            }
-            
-            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.d(TAG, "Download service disconnected");
-                mDownloaderBinder = null;
-            } else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
-                Log.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(true);
-            returnValue = true;
-            break;
-        default:
-        	returnValue = super.onOptionsItemSelected(item);
-        }
-        
-        return returnValue;
-    }
-
-
-
-    private void backToDisplayActivity(boolean moveToParent) {
-        Intent intent = new Intent(this, FileDisplayActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        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 )
-        
-        
-    }
-
-}
+/* 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 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) {
+            setContentView(R.layout.file_activity_details);
+        
+            ActionBar actionBar = getSupportActionBar();
+            actionBar.setDisplayHomeAsUpEnabled(true);
+
+            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(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;
+            }
+            
+            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(true);
+            returnValue = true;
+            break;
+        default:
+            returnValue = super.onOptionsItemSelected(item);
+        }
+        
+        return returnValue;
+    }
+
+    private void backToDisplayActivity(boolean moveToParent) {
+        Intent intent = new Intent(this, FileDisplayActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        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 )
+        
+    }
+
+}

+ 23 - 74
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -38,11 +38,8 @@ import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.content.SharedPreferences.Editor;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Handler;
@@ -67,6 +64,8 @@ import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.Window;
 import com.actionbarsherlock.view.Window;
 import com.owncloud.android.AccountUtils;
 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.authenticator.AccountAuthenticator;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -97,7 +96,6 @@ import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 
 
-import com.owncloud.android.R;
 import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavClient;
 
 
 /**
 /**
@@ -130,7 +128,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
     
     
     private static final int DIALOG_SETUP_ACCOUNT = 0;
     private static final int DIALOG_SETUP_ACCOUNT = 0;
     private static final int DIALOG_CREATE_DIR = 1;
     private static final int DIALOG_CREATE_DIR = 1;
-    private static final int DIALOG_ABOUT_APP = 2;
     public static final int DIALOG_SHORT_WAIT = 3;
     public static final int DIALOG_SHORT_WAIT = 3;
     private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
     private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
     private static final int DIALOG_SSL_VALIDATOR = 5;
     private static final int DIALOG_SSL_VALIDATOR = 5;
@@ -143,15 +140,12 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
     
     
     private static final String TAG = "FileDisplayActivity";
     private static final String TAG = "FileDisplayActivity";
 
 
-    private static int[] mMenuIdentifiersToPatch = {R.id.action_about_app};
-    
     private OCFile mWaitingToPreview;
     private OCFile mWaitingToPreview;
     private Handler mHandler;
     private Handler mHandler;
 
 
-    
     @Override
     @Override
     public void onCreate(Bundle savedInstanceState) {
     public void onCreate(Bundle savedInstanceState) {
-        Log.d(getClass().toString(), "onCreate() start");
+        Log_OC.d(getClass().toString(), "onCreate() start");
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
 
 
         /// Load of parameters from received intent
         /// Load of parameters from received intent
@@ -244,7 +238,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         //showChangeLog();
         //showChangeLog();
         mBackFromCreatingFirstAccount = false;
         mBackFromCreatingFirstAccount = false;
         
         
-        Log.d(getClass().toString(), "onCreate() end");
+        Log_OC.d(getClass().toString(), "onCreate() end");
     }
     }
 
 
     
     
@@ -355,31 +349,9 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         MenuInflater inflater = getSherlock().getMenuInflater();
         MenuInflater inflater = getSherlock().getMenuInflater();
             inflater.inflate(R.menu.main_menu, menu);
             inflater.inflate(R.menu.main_menu, menu);
             
             
-            patchHiddenAccents(menu);
-            
             return true;
             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
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
     public boolean onOptionsItemSelected(MenuItem item) {
         boolean retval = true;
         boolean retval = true;
@@ -402,10 +374,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
                 startActivity(settingsIntent);
                 startActivity(settingsIntent);
                 break;
                 break;
             }
             }
-            case R.id.action_about_app: {
-                showDialog(DIALOG_ABOUT_APP);
-                break;
-            }
             case android.R.id.home: {
             case android.R.id.home: {
                 if(mCurrentDir != null && mCurrentDir.getParentId() != 0){
                 if(mCurrentDir != null && mCurrentDir.getParentId() != 0){
                     onBackPressed(); 
                     onBackPressed(); 
@@ -480,7 +448,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             startService(i);
             startService(i);
             
             
         } else {
         } 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);
             Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), Toast.LENGTH_LONG);
             t.show();
             t.show();
             return;
             return;
@@ -502,12 +470,12 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
                 filepath = filemanagerstring;
                 filepath = filemanagerstring;
             
             
         } catch (Exception e) {
         } 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();
             e.printStackTrace();
             
             
         } finally {
         } finally {
             if (filepath == null) {
             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);
                 Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
                 t.show();
                 t.show();
                 return;
                 return;
@@ -563,7 +531,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
     @Override
     @Override
     protected void onSaveInstanceState(Bundle outState) {
     protected void onSaveInstanceState(Bundle outState) {
         // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
         // 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);
         super.onSaveInstanceState(outState);
         outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir);
         outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir);
         if (mDualPane) {
         if (mDualPane) {
@@ -576,13 +544,13 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             }
             }
         }
         }
         outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
         outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
-        Log.d(getClass().toString(), "onSaveInstanceState() end");
+        Log_OC.d(getClass().toString(), "onSaveInstanceState() end");
     }
     }
 
 
     
     
     @Override
     @Override
-    public void onResume() {
-        Log.d(getClass().toString(), "onResume() start");
+    protected void onResume() {
+        Log_OC.d(getClass().toString(), "onResume() start");
         super.onResume();
         super.onResume();
 
 
         if (AccountUtils.accountsAreSetup(this)) {
         if (AccountUtils.accountsAreSetup(this)) {
@@ -621,13 +589,13 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             showDialog(DIALOG_SETUP_ACCOUNT);
             showDialog(DIALOG_SETUP_ACCOUNT);
             
             
         }
         }
-        Log.d(getClass().toString(), "onResume() end");
+        Log_OC.d(getClass().toString(), "onResume() end");
     }
     }
 
 
     
     
     @Override
     @Override
-    public void onPause() {
-        Log.d(getClass().toString(), "onPause() start");
+    protected void onPause() {
+        Log_OC.d(getClass().toString(), "onPause() start");
         super.onPause();
         super.onPause();
         if (mSyncBroadcastReceiver != null) {
         if (mSyncBroadcastReceiver != null) {
             unregisterReceiver(mSyncBroadcastReceiver);
             unregisterReceiver(mSyncBroadcastReceiver);
@@ -645,7 +613,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             dismissDialog(DIALOG_SETUP_ACCOUNT);
             dismissDialog(DIALOG_SETUP_ACCOUNT);
         }
         }
         
         
-        Log.d(getClass().toString(), "onPause() end");
+        Log_OC.d(getClass().toString(), "onPause() end");
     }
     }
 
 
     
     
@@ -684,22 +652,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             dialog = builder.create();
             dialog = builder.create();
             break;
             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: {
         case DIALOG_CREATE_DIR: {
             builder = new Builder(this);
             builder = new Builder(this);
             final EditText dirNameInput = new EditText(getBaseContext());
             final EditText dirNameInput = new EditText(getBaseContext());
@@ -909,7 +861,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
                             msg.show();
                             msg.show();
                         
                         
                         } catch (NotFoundException e) {
                         } 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);
                         }
                         }
                     }
                     }
                 });
                 });
@@ -952,13 +904,10 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
          */
          */
         @Override
         @Override
         public void onReceive(Context context, Intent intent) {
         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)) {  
             if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {  
             
             
@@ -1252,14 +1201,14 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         @Override
         @Override
         public void onServiceConnected(ComponentName component, IBinder service) {
         public void onServiceConnected(ComponentName component, IBinder service) {
             if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
             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;
                 mDownloaderBinder = (FileDownloaderBinder) service;
                 if (mWaitingToPreview != null) {
                 if (mWaitingToPreview != null) {
                     requestForDownload();
                     requestForDownload();
                 }
                 }
                 
                 
             } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
             } 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;
                 mUploaderBinder = (FileUploaderBinder) service;
             } else {
             } else {
                 return;
                 return;
@@ -1280,10 +1229,10 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         @Override
         @Override
         public void onServiceDisconnected(ComponentName component) {
         public void onServiceDisconnected(ComponentName component) {
             if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
             if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
-                Log.d(TAG, "Download service disconnected");
+                Log_OC.d(TAG, "Download service disconnected");
                 mDownloaderBinder = null;
                 mDownloaderBinder = null;
             } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
             } 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;
                 mUploaderBinder = null;
             }
             }
         }
         }

+ 14 - 13
src/com/owncloud/android/ui/activity/InstantUploadActivity.java

@@ -44,6 +44,7 @@ import android.widget.TextView;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.InstantUploadBroadcastReceiver;
 import com.owncloud.android.files.InstantUploadBroadcastReceiver;
@@ -132,7 +133,7 @@ public class InstantUploadActivity extends Activity {
                     rowLayout.addView(getImageButton(imp_path, lastLoadImageIdx));
                     rowLayout.addView(getImageButton(imp_path, lastLoadImageIdx));
                     rowLayout.addView(getFileButton(imp_path, message, lastLoadImageIdx));
                     rowLayout.addView(getFileButton(imp_path, message, lastLoadImageIdx));
                     listView.addView(rowLayout);
                     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) {
                     if (lastLoadImageIdx % MAX_LOAD_IMAGES == 0) {
                         break;
                         break;
                     }
                     }
@@ -183,12 +184,12 @@ public class InstantUploadActivity extends Activity {
     private List<CheckBox> getCheckboxList() {
     private List<CheckBox> getCheckboxList() {
         List<CheckBox> list = new ArrayList<CheckBox>();
         List<CheckBox> list = new ArrayList<CheckBox>();
         for (int i = 0; i < listView.getChildCount(); i++) {
         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);
             View childView = listView.getChildAt(i);
             if (childView != null && childView instanceof ViewGroup) {
             if (childView != null && childView instanceof ViewGroup) {
                 View checkboxView = getChildViews((ViewGroup) childView);
                 View checkboxView = getChildViews((ViewGroup) childView);
                 if (checkboxView != null && checkboxView instanceof CheckBox) {
                 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);
                     list.add((CheckBox) checkboxView);
                 }
                 }
             }
             }
@@ -251,12 +252,12 @@ public class InstantUploadActivity extends Activity {
                     for (CheckBox checkbox : list) {
                     for (CheckBox checkbox : list) {
                         boolean to_retry = checkbox.isChecked();
                         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());
                         String img_path = fileList.get(checkbox.getId());
                         if (to_retry) {
                         if (to_retry) {
 
 
                             final String msg = "Image-Path " + checkbox.getId() + " was checked: " + img_path;
                             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);
                             startUpload(img_path);
                         }
                         }
 
 
@@ -292,12 +293,12 @@ public class InstantUploadActivity extends Activity {
                     for (CheckBox checkbox : list) {
                     for (CheckBox checkbox : list) {
                         boolean to_be_delete = checkbox.isChecked();
                         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());
                         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) {
                         if (to_be_delete) {
                             boolean deleted = dbh.removeIUPendingFile(img_path);
                             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);
 
 
                         }
                         }
 
 
@@ -391,7 +392,7 @@ public class InstantUploadActivity extends Activity {
         // scale and add a thumbnail to the imagebutton
         // scale and add a thumbnail to the imagebutton
         int base_scale_size = 32;
         int base_scale_size = 32;
         if (img_path != null) {
         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();
             BitmapFactory.Options options = new BitmapFactory.Options();
             options.inJustDecodeBounds = true;
             options.inJustDecodeBounds = true;
             Bitmap bitmap = BitmapFactory.decodeFile(img_path, options);
             Bitmap bitmap = BitmapFactory.decodeFile(img_path, options);
@@ -406,16 +407,16 @@ public class InstantUploadActivity extends Activity {
                 scale++;
                 scale++;
             }
             }
 
 
-            Log.d(LOG_TAG, "scale Imgae with: " + scale);
+            Log_OC.d(LOG_TAG, "scale Imgae with: " + scale);
             BitmapFactory.Options options2 = new BitmapFactory.Options();
             BitmapFactory.Options options2 = new BitmapFactory.Options();
             options2.inSampleSize = scale;
             options2.inSampleSize = scale;
             bitmap = BitmapFactory.decodeFile(img_path, options2);
             bitmap = BitmapFactory.decodeFile(img_path, options2);
 
 
             if (bitmap != null) {
             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);
                 imageButton.setImageBitmap(bitmap);
             } else {
             } else {
-                Log.d(LOG_TAG, "could not load imgage: " + img_path);
+                Log_OC.d(LOG_TAG, "could not load imgage: " + img_path);
             }
             }
         }
         }
         return imageButton;
         return imageButton;
@@ -459,7 +460,7 @@ public class InstantUploadActivity extends Activity {
             i.putExtra(com.owncloud.android.files.services.FileUploader.KEY_INSTANT_UPLOAD, true);
             i.putExtra(com.owncloud.android.files.services.FileUploader.KEY_INSTANT_UPLOAD, true);
 
 
             final String msg = "try to upload file with name :" + filename;
             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)
             Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
                     + filename, Toast.LENGTH_LONG);
                     + filename, Toast.LENGTH_LONG);
             toast.show();
             toast.show();

+ 119 - 0
src/com/owncloud/android/ui/activity/LogHistoryActivity.java

@@ -0,0 +1,119 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License 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 java.io.File;
+import java.util.ArrayList;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ListView;
+
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.R;
+import com.owncloud.android.ui.adapter.LogListAdapter;
+import com.owncloud.android.utils.FileStorageUtils;
+
+
+
+public class LogHistoryActivity extends SherlockPreferenceActivity implements OnPreferenceChangeListener {
+    String logpath = FileStorageUtils.getLogPath();
+    File logDIR = null;
+    
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.log_send_file);
+        setTitle("Log History");
+        ActionBar actionBar = getSherlock().getActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(true);
+        ListView listView = (ListView) findViewById(android.R.id.list);
+        Button deleteHistoryButton = (Button) findViewById(R.id.deleteLogHistoryButton);
+        deleteHistoryButton.setOnClickListener(new OnClickListener() {
+            
+            @Override
+            public void onClick(View v) {
+                File dir = new File(logpath);
+                if (dir != null) {
+                    File[] files = dir.listFiles();
+                    if(files!=null) { 
+                        for(File f: files) {
+                                f.delete();
+                        }
+                    }
+                    dir.delete();
+                }
+                Intent intent = new Intent(getBaseContext(), Preferences.class);
+                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
+            }
+            
+        });
+        
+       
+        if(logpath != null){
+        logDIR = new File(logpath);
+        }
+        
+        if(logDIR != null && logDIR.isDirectory()) {
+            File[] files = logDIR.listFiles();
+          
+            if (files != null && files.length != 0) {
+                ArrayList<String> logfiles_name = new ArrayList<String>();
+                for (File file : files) {
+                    logfiles_name.add(file.getName());
+                }
+                    String[] logFiles2Array = logfiles_name.toArray(new String[logfiles_name.size()]);
+                    LogListAdapter listadapter = new LogListAdapter(this,logFiles2Array);
+                    listView.setAdapter(listadapter);
+            }
+        }
+    }
+
+    
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        super.onMenuItemSelected(featureId, item);
+        Intent intent;
+
+        switch (item.getItemId()) {
+       
+        case android.R.id.home:
+            intent = new Intent(getBaseContext(), Preferences.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            startActivity(intent);
+            break;
+        default:
+            return false;
+        }
+        return true;
+    }
+    @Override
+    public boolean onPreferenceChange(Preference arg0, Object arg1) {
+        return false;
+    }
+}

+ 241 - 237
src/com/owncloud/android/ui/activity/Preferences.java

@@ -1,237 +1,241 @@
-/* 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 java.util.Vector;
-
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceManager;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.util.Log;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.app.SherlockPreferenceActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.OwnCloudSession;
-import com.owncloud.android.db.DbHandler;
-
-import com.owncloud.android.R;
-
-/**
- * An Activity that allows the user to change the application's settings.
- * 
- * @author Bartek Przybylski
- * 
- */
-public class Preferences extends SherlockPreferenceActivity implements
-        OnPreferenceChangeListener{
-    private static final String TAG = "OwnCloudPreferences";
-    private final int mNewSession = 47;
-    private final int mEditSession = 48;
-    private DbHandler mDbHandler;
-    private Vector<OwnCloudSession> mSessions;
-    //private Account[] mAccounts;
-    //private ListPreference mAccountList;
-    private ListPreference mTrackingUpdateInterval;
-    private CheckBoxPreference mDeviceTracking;
-    private CheckBoxPreference pCode;
-    private int mSelectedMenuItem;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mDbHandler = new DbHandler(getBaseContext());
-        mSessions = new Vector<OwnCloudSession>();
-        addPreferencesFromResource(R.xml.preferences);
-        //populateAccountList();
-        ActionBar actionBar = getSherlock().getActionBar();
-        actionBar.setDisplayHomeAsUpEnabled(true);
-        Preference p = findPreference("manage_account");
-        if (p != null)
-        p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-            @Override
-            public boolean onPreferenceClick(Preference preference) {
-                Intent i = new Intent(getApplicationContext(), AccountSelectActivity.class);
-                startActivity(i);
-                return true;
-            }
-        });
-        
-        pCode = (CheckBoxPreference) findPreference("set_pincode");
-         
-        
-        if (pCode != null){
-            
-            pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-                @Override
-                public boolean onPreferenceChange(Preference preference, Object newValue) {
-                                          
-                    Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
-                    i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "preferences");
-                    i.putExtra(PinCodeActivity.EXTRA_NEW_STATE, newValue.toString());
-                    
-                    startActivity(i);
-                    
-                    return true;
-                }
-            });            
-            
-        }
-        
-    }
-
-
-    @Override
-    protected void onResume() {
-        // TODO Auto-generated method stub
-        SharedPreferences appPrefs = PreferenceManager
-                .getDefaultSharedPreferences(getApplicationContext());
-        
-        boolean state = appPrefs.getBoolean("set_pincode", false);
-        pCode.setChecked(state);
-        
-        super.onResume();
-    }
-
-
-
-    /**
-     * Populates the account selector
-     *-/
-    private void populateAccountList() {
-        AccountManager accMan = AccountManager.get(this);
-        mAccounts = accMan.getAccountsByType(AccountAuthenticator.ACCOUNT_TYPE);
-        mAccountList = (ListPreference) findPreference("select_oc_account");
-        mAccountList.setOnPreferenceChangeListener(this);
-
-        // Display the name of the current account if there is any
-        Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this);
-        if (defaultAccount != null) {
-            mAccountList.setSummary(defaultAccount.name);
-        }
-        
-        // Transform accounts into array of string for preferences to use
-        String[] accNames = new String[mAccounts.length];
-        for (int i = 0; i < mAccounts.length; i++) {
-            Account account = mAccounts[i];
-            accNames[i] = account.name;
-        }
-
-        mAccountList.setEntries(accNames);
-        mAccountList.setEntryValues(accNames);
-    }*/
-
-    
-    
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        //MenuInflater inflater = getSherlock().getMenuInflater();
-        //inflater.inflate(R.menu.prefs_menu, menu);
-        return true;
-    }
-
-    @Override
-    public boolean onMenuItemSelected(int featureId, MenuItem item) {
-        super.onMenuItemSelected(featureId, item);
-        Intent intent;
-
-        switch (item.getItemId()) {
-        //case R.id.addSessionItem:
-        case 1:
-            intent = new Intent(this, PreferencesNewSession.class);
-            startActivityForResult(intent, mNewSession);
-            break;
-        case R.id.SessionContextEdit:
-            intent = new Intent(this, PreferencesNewSession.class);
-            intent.putExtra("sessionId", mSessions.get(mSelectedMenuItem)
-                    .getEntryId());
-            intent.putExtra("sessionName", mSessions.get(mSelectedMenuItem)
-                    .getName());
-            intent.putExtra("sessionURL", mSessions.get(mSelectedMenuItem)
-                    .getUrl());
-            startActivityForResult(intent, mEditSession);
-            break;
-        case android.R.id.home:
-            intent = new Intent(getBaseContext(), FileDisplayActivity.class);
-            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            startActivity(intent);
-            break;
-        default:
-            Log.w(TAG, "Unknown menu item triggered");
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-    }
-
-    @Override
-    protected void onDestroy() {
-        mDbHandler.close();
-        super.onDestroy();
-    }
-
-    
-    
-    @Override
-    /**
-     * Updates various summaries after updates. Also starts and stops 
-     * the
-     */
-    public boolean onPreferenceChange(Preference preference, Object newValue) {
-        // Update current account summary
-        /*if (preference.equals(mAccountList)) {
-            mAccountList.setSummary(newValue.toString());
-        }
-
-        // Update tracking interval summary
-        else*/ if (preference.equals(mTrackingUpdateInterval)) {
-            String trackingSummary = getResources().getString(
-                    R.string.prefs_trackmydevice_interval_summary);
-            trackingSummary = String.format(trackingSummary,
-                    newValue.toString());
-            mTrackingUpdateInterval.setSummary(trackingSummary);
-        }
-
-        // Start or stop tracking service
-        else if (preference.equals(mDeviceTracking)) {
-            Intent locationServiceIntent = new Intent();
-            locationServiceIntent
-                    .setAction("com.owncloud.android.location.LocationLauncher");
-            locationServiceIntent.putExtra("TRACKING_SETTING",
-                    (Boolean) newValue);
-            sendBroadcast(locationServiceIntent);
-        } 
-        return true;
-    }
-    
-    
-
-}
+/* 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 java.io.File;
+import java.util.Vector;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.Environment;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceManager;
+
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.OwnCloudSession;
+import com.owncloud.android.R;
+import com.owncloud.android.db.DbHandler;
+
+/**
+ * An Activity that allows the user to change the application's settings.
+ * 
+ * @author Bartek Przybylski
+ * 
+ */
+public class Preferences extends SherlockPreferenceActivity implements OnPreferenceChangeListener {
+    
+    private static final String TAG = "OwnCloudPreferences";
+    private final int mNewSession = 47;
+    private final int mEditSession = 48;
+    private DbHandler mDbHandler;
+    private Vector<OwnCloudSession> mSessions;
+    private ListPreference mTrackingUpdateInterval;
+    private CheckBoxPreference mDeviceTracking;
+    private CheckBoxPreference pCode;
+    private CheckBoxPreference pLogging;
+    private Preference pLoggingHistory;
+    private Preference pAboutApp;
+    private int mSelectedMenuItem;
+
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDbHandler = new DbHandler(getBaseContext());
+        mSessions = new Vector<OwnCloudSession>();
+        addPreferencesFromResource(R.xml.preferences);
+        //populateAccountList();
+        ActionBar actionBar = getSherlock().getActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(true);
+        Preference p = findPreference("manage_account");
+        if (p != null)
+        p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                Intent i = new Intent(getApplicationContext(), AccountSelectActivity.class);
+                startActivity(i);
+                return true;
+            }
+        });
+        
+        pCode = (CheckBoxPreference) findPreference("set_pincode");
+        if (pCode != null){
+            pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
+                    i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "preferences");
+                    i.putExtra(PinCodeActivity.EXTRA_NEW_STATE, newValue.toString());
+                    startActivity(i);
+                    return true;
+                }
+            });
+            
+           /* About App */
+       pAboutApp = (Preference) findPreference("about_app");
+       if (pAboutApp != null) { 
+               pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
+               PackageInfo pkg;
+               try {
+                   pkg = getPackageManager().getPackageInfo(getPackageName(), 0);
+                   pAboutApp.setSummary(String.format(getString(R.string.about_version), pkg.versionName));
+               } catch (NameNotFoundException e) {
+                   Log_OC.e(TAG, "Error while showing about dialog", e);
+               }
+       }
+       
+       pLogging = (CheckBoxPreference) findPreference("log_to_file");
+       if (pLogging != null) {
+           pLogging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+               @Override
+               public boolean onPreferenceChange(Preference preference, Object newValue) {
+                   
+                   String logpath = Environment.getExternalStorageDirectory()+File.separator+"owncloud"+File.separator+"log";
+                
+                   if(!pLogging.isChecked()) {
+                       Log_OC.d("Debug", "start logging");
+                       Log_OC.v("PATH", logpath);
+                       Log_OC.startLogging(logpath);
+                   }
+                   else {
+                       Log_OC.d("Debug", "stop logging");
+                       Log_OC.stopLogging();
+                   }
+                   return true;
+               }
+           });
+       }
+       
+       pLoggingHistory = (Preference) findPreference("log_history");
+       if (pLoggingHistory != null) {
+           pLoggingHistory.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                Intent intent = new Intent(getApplicationContext(),LogHistoryActivity.class);
+                startActivity(intent);
+                return true;
+            }
+        });
+       }
+      }
+    }
+
+    @Override
+    protected void onResume() {
+        SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        boolean state = appPrefs.getBoolean("set_pincode", false);
+        pCode.setChecked(state);
+        super.onResume();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        super.onMenuItemSelected(featureId, item);
+        Intent intent;
+
+        switch (item.getItemId()) {
+        //case R.id.addSessionItem:
+        case 1:
+            intent = new Intent(this, PreferencesNewSession.class);
+            startActivityForResult(intent, mNewSession);
+            break;
+        case R.id.SessionContextEdit:
+            intent = new Intent(this, PreferencesNewSession.class);
+            intent.putExtra("sessionId", mSessions.get(mSelectedMenuItem)
+                    .getEntryId());
+            intent.putExtra("sessionName", mSessions.get(mSelectedMenuItem)
+                    .getName());
+            intent.putExtra("sessionURL", mSessions.get(mSelectedMenuItem)
+                    .getUrl());
+            startActivityForResult(intent, mEditSession);
+            break;
+        case android.R.id.home:
+            intent = new Intent(getBaseContext(), FileDisplayActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            startActivity(intent);
+            break;
+        default:
+            Log_OC.w(TAG, "Unknown menu item triggered");
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    protected void onDestroy() {
+        mDbHandler.close();
+        super.onDestroy();
+    }
+    
+    @Override
+    /**
+     * Updates various summaries after updates. Also starts and stops 
+     * the
+     */
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        // Update current account summary
+        /*if (preference.equals(mAccountList)) {
+            mAccountList.setSummary(newValue.toString());
+        }
+
+        // Update tracking interval summary
+        else*/ if (preference.equals(mTrackingUpdateInterval)) {
+            String trackingSummary = getResources().getString(
+                    R.string.prefs_trackmydevice_interval_summary);
+            trackingSummary = String.format(trackingSummary,
+                    newValue.toString());
+            mTrackingUpdateInterval.setSummary(trackingSummary);
+        }
+
+        // Start or stop tracking service
+        else if (preference.equals(mDeviceTracking)) {
+            Intent locationServiceIntent = new Intent();
+            locationServiceIntent
+                    .setAction("com.owncloud.android.location.LocationLauncher");
+            locationServiceIntent.putExtra("TRACKING_SETTING",
+                    (Boolean) newValue);
+            sendBroadcast(locationServiceIntent);
+        } 
+        return true;
+    }
+}

+ 8 - 7
src/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -44,6 +44,7 @@ import com.owncloud.android.ui.fragment.LocalFileListFragment;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 
 
 /**
 /**
@@ -78,7 +79,7 @@ public class UploadFilesActivity extends SherlockFragmentActivity implements
     
     
     @Override
     @Override
     public void onCreate(Bundle savedInstanceState) {
     public void onCreate(Bundle savedInstanceState) {
-        Log.d(TAG, "onCreate() start");
+        Log_OC.d(TAG, "onCreate() start");
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
 
 
         if(savedInstanceState != null) {
         if(savedInstanceState != null) {
@@ -125,7 +126,7 @@ public class UploadFilesActivity extends SherlockFragmentActivity implements
             mCurrentDialog = null;
             mCurrentDialog = null;
         }
         }
             
             
-        Log.d(TAG, "onCreate() end");
+        Log_OC.d(TAG, "onCreate() end");
     }
     }
 
 
 
 
@@ -181,10 +182,10 @@ public class UploadFilesActivity extends SherlockFragmentActivity implements
     @Override
     @Override
     protected void onSaveInstanceState(Bundle outState) {
     protected void onSaveInstanceState(Bundle outState) {
         // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
         // 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);
         super.onSaveInstanceState(outState);
         outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath());
         outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath());
-        Log.d(TAG, "onSaveInstanceState() end");
+        Log_OC.d(TAG, "onSaveInstanceState() end");
     }
     }
 
 
     
     
@@ -354,7 +355,7 @@ public class UploadFilesActivity extends SherlockFragmentActivity implements
 
 
     @Override
     @Override
     public void onConfirmation(String callerTag) {
     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)) {
         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
             // 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();
             Intent data = new Intent();
@@ -367,14 +368,14 @@ public class UploadFilesActivity extends SherlockFragmentActivity implements
 
 
     @Override
     @Override
     public void onNeutral(String callerTag) {
     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);
     }
     }
 
 
 
 
     @Override
     @Override
     public void onCancel(String callerTag) {
     public void onCancel(String callerTag) {
         /// nothing to do; don't finish, let the user change the selection
         /// 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);
     }    
     }    
 
 
     
     

+ 54 - 0
src/com/owncloud/android/ui/adapter/LogListAdapter.java

@@ -0,0 +1,54 @@
+package com.owncloud.android.ui.adapter;
+
+import java.io.File;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+
+
+public class LogListAdapter extends ArrayAdapter<String> {
+    private Context context = null;
+    private String[] values;
+    private Uri fileUri = null;
+   
+    
+    public LogListAdapter(Context context, String[] values) {
+        super(context, R.layout.log_item, values);
+        this.context = context;
+        this.values = values;
+    }
+
+    @Override
+    public View getView(final int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View rowView = inflater.inflate(R.layout.log_item, parent, false);
+        TextView listText = (TextView) rowView.findViewById(R.id.log_item_single);
+        listText.setText(values[position]);
+        listText.setTextSize(15);
+        fileUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+File.separator+"owncloud"+File.separator+"log"+File.separator+values[position]));
+        listText.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
+                emailIntent.setType("text/rtf");
+                emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "OwnCloud Logfile");
+                emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "This is a automatic E-mail send by owncloud/android");
+                emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, fileUri);
+                emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
+            }
+        });
+        return rowView;
+    }
+}

+ 3 - 2
src/com/owncloud/android/ui/dialog/SslValidatorDialog.java

@@ -38,6 +38,7 @@ import android.view.Window;
 import android.widget.Button;
 import android.widget.Button;
 import android.widget.TextView;
 import android.widget.TextView;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.network.CertificateCombinedException;
 import com.owncloud.android.network.CertificateCombinedException;
 import com.owncloud.android.network.OwnCloudClientUtils;
 import com.owncloud.android.network.OwnCloudClientUtils;
@@ -110,13 +111,13 @@ public class SslValidatorDialog extends Dialog {
                             if (mListener != null)
                             if (mListener != null)
                                 mListener.onSavedCertificate();
                                 mListener.onSavedCertificate();
                             else
                             else
-                                Log.d(TAG, "Nobody there to notify the certificate was saved");
+                                Log_OC.d(TAG, "Nobody there to notify the certificate was saved");
                             
                             
                         } catch (Exception e) {
                         } catch (Exception e) {
                             dismiss();
                             dismiss();
                             if (mListener != null)
                             if (mListener != null)
                                 mListener.onFailedSavingCertificate();
                                 mListener.onFailedSavingCertificate();
-                            Log.e(TAG, "Server certificate could not be saved in the known servers trust store ", e);
+                            Log_OC.e(TAG, "Server certificate could not be saved in the known servers trust store ", e);
                         }
                         }
                     }
                     }
                 });
                 });

+ 2 - 1
src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java

@@ -26,6 +26,7 @@ import android.os.Bundle;
 import android.util.Log;
 import android.util.Log;
 
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.actionbarsherlock.app.SherlockDialogFragment;
+import com.owncloud.android.Log_OC;
 
 
 public class ConfirmationDialogFragment extends SherlockDialogFragment {
 public class ConfirmationDialogFragment extends SherlockDialogFragment {
 
 
@@ -75,7 +76,7 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment {
         int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1);
         int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1);
         
         
         if (confirmationTarget == null || resourceId == -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;
             return null;
         }
         }
 
 

+ 1058 - 1037
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -1,1037 +1,1058 @@
-/* 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.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 com.actionbarsherlock.app.SherlockFragment;
-import com.owncloud.android.AccountUtils;
-import com.owncloud.android.DisplayUtils;
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-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.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,
-        FileFragment {
-
-    public static final String EXTRA_FILE = "FILE";
-    public static final String EXTRA_ACCOUNT = "ACCOUNT";
-
-    private FileFragment.ContainerActivity mContainerActivity;
-    
-    private int mLayout;
-    private View mView;
-    private OCFile mFile;
-    private Account mAccount;
-    private FileDataStorageManager mStorageManager;
-    
-    private UploadFinishReceiver mUploadFinishReceiver;
-    public ProgressListener mProgressListener;
-    
-    private Handler mHandler;
-    private RemoteOperation mLastRemoteOperation;
-    
-    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);
-            ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
-            mProgressListener = new ProgressListener(progressBar);
-        }
-        
-        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());
-        }
-    }
-        
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);
-        outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        listenForTransferProgress();
-    }
-    
-    @Override
-    public void onResume() {
-        super.onResume();
-        mUploadFinishReceiver = new UploadFinishReceiver();
-        IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
-        getActivity().registerReceiver(mUploadFinishReceiver, filter);
-
-    }
-
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        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);
-                    
-                }
-                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);
-                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);
-                confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
-                break;
-            }
-            case R.id.fdOpenBtn: {
-                openFile();
-                break;
-            }
-            default:
-                Log.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);
-            }
-        }
-    }
-    
-    @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);
-        }
-    }
-    
-    @Override
-    public void onCancel(String callerTag) {
-        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);
-    }
-
-    
-    /**
-     * {@inheritDoc}
-     */
-    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, 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, boolean refresh) {
-
-        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()) {
-                
-                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;
-    }
-    
-    
-    /**
-     * 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, 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.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.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.d("sharer", ""+ url+"/");
-                    
-                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
-                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
-                    }
-                    
-                    int status2 = wc.executeMethod(find);
-
-                    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.d("sharer", "getstatus "+status2);
-                    Log.d("sharer", "" + get.getResponseBodyAsString());
-                    
-                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
-                        Log.d("sharer", a.getName() + ":"+a.getValue());
-                    }
-
-                    status = wc.executeMethod(post);
-                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
-                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
-                    }
-                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
-                        Log.d("sharer", a.getName() + ":"+a.getValue());
-                    }
-                    String resp = post.getResponseBodyAsString();
-                    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.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.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);
-        }
-    }
-    
-    
-    /**
-     * {@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;
-        }
-
-    };
-    
-
-
-}
+/* 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.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.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.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,
+        FileFragment {
+
+    public static final String EXTRA_FILE = "FILE";
+    public static final String EXTRA_ACCOUNT = "ACCOUNT";
+
+    private FileFragment.ContainerActivity mContainerActivity;
+    
+    private int mLayout;
+    private View mView;
+    private OCFile mFile;
+    private Account mAccount;
+    private FileDataStorageManager mStorageManager;
+    
+    private UploadFinishReceiver mUploadFinishReceiver;
+    public ProgressListener mProgressListener;
+    
+    private Handler mHandler;
+    private RemoteOperation mLastRemoteOperation;
+    
+    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);
+            ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
+            mProgressListener = new ProgressListener(progressBar);
+        }
+        
+        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());
+        }
+    }
+        
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);
+        outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        listenForTransferProgress();
+    }
+    
+    @Override
+    public void onResume() {
+        super.onResume();
+        mUploadFinishReceiver = new UploadFinishReceiver();
+        IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+        getActivity().registerReceiver(mUploadFinishReceiver, filter);
+
+    }
+
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        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);
+                    
+                }
+                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);
+                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);
+                confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
+                break;
+            }
+            case R.id.fdOpenBtn: {
+                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);
+            }
+        }
+    }
+    
+    @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);
+        }
+    }
+    
+    @Override
+    public void onCancel(String callerTag) {
+        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);
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    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, 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, boolean refresh) {
+
+        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()) {
+                
+                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;
+    }
+    
+
+    /**
+     * 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, 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.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.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.d("sharer", ""+ url+"/");
+                    
+                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
+                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
+                    }
+                    
+                    int status2 = wc.executeMethod(find);
+
+                    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.d("sharer", "getstatus "+status2);
+                    Log.d("sharer", "" + get.getResponseBodyAsString());
+                    
+                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
+                        Log.d("sharer", a.getName() + ":"+a.getValue());
+                    }
+
+                    status = wc.executeMethod(post);
+                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
+                        Log.d("sharer-h", a.getName() + ":"+a.getValue());
+                    }
+                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
+                        Log.d("sharer", a.getName() + ":"+a.getValue());
+                    }
+                    String resp = post.getResponseBodyAsString();
+                    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.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.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);
+        }
+    }
+    
+    
+    /**
+     * {@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;
+        }
+
+    };
+
+}

+ 11 - 10
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -35,6 +35,7 @@ import android.widget.AdapterView;
 import android.widget.ImageView;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.ListView;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 
 
 /**
 /**
@@ -76,10 +77,10 @@ public class LocalFileListFragment extends FragmentListView {
      */
      */
     @Override
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        Log.i(TAG, "onCreateView() start");
+        Log_OC.i(TAG, "onCreateView() start");
         View v = super.onCreateView(inflater, container, savedInstanceState);
         View v = super.onCreateView(inflater, container, savedInstanceState);
         getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
         getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-        Log.i(TAG, "onCreateView() end");
+        Log_OC.i(TAG, "onCreateView() end");
         return v;
         return v;
     }    
     }    
 
 
@@ -89,30 +90,30 @@ public class LocalFileListFragment extends FragmentListView {
      */
      */
     @Override
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
     public void onActivityCreated(Bundle savedInstanceState) {
-        Log.i(TAG, "onActivityCreated() start");
+        Log_OC.i(TAG, "onActivityCreated() start");
         
         
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
         mAdapter = new LocalFileListAdapter(mContainerActivity.getInitialDirectory(), getActivity());
         mAdapter = new LocalFileListAdapter(mContainerActivity.getInitialDirectory(), getActivity());
         setListAdapter(mAdapter);
         setListAdapter(mAdapter);
         
         
         if (savedInstanceState != null) {
         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);
             int position = savedInstanceState.getInt(SAVED_LIST_POSITION);
             setReferencePosition(position);
             setReferencePosition(position);
         }
         }
         
         
-        Log.i(TAG, "onActivityCreated() stop");
+        Log_OC.i(TAG, "onActivityCreated() stop");
     }
     }
     
     
     
     
     @Override
     @Override
     public void onSaveInstanceState(Bundle savedInstanceState) {
     public void onSaveInstanceState(Bundle savedInstanceState) {
-        Log.i(TAG, "onSaveInstanceState() start");
+        Log_OC.i(TAG, "onSaveInstanceState() start");
         
         
         savedInstanceState.putInt(SAVED_LIST_POSITION, getReferencePosition());
         savedInstanceState.putInt(SAVED_LIST_POSITION, getReferencePosition());
         
         
         
         
-        Log.i(TAG, "onSaveInstanceState() stop");
+        Log_OC.i(TAG, "onSaveInstanceState() stop");
     }
     }
     
     
     
     
@@ -144,7 +145,7 @@ public class LocalFileListFragment extends FragmentListView {
             }
             }
             
             
         } else {
         } else {
-            Log.w(TAG, "Null object in ListAdapter!!");
+            Log_OC.w(TAG, "Null object in ListAdapter!!");
         }
         }
     }
     }
 
 
@@ -203,7 +204,7 @@ public class LocalFileListFragment extends FragmentListView {
         
         
         // if that's not a directory -> List its parent
         // if that's not a directory -> List its parent
         if(!directory.isDirectory()){
         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 = directory.getParentFile();
             directory = directory.getParentFile();
         }
         }
 
 
@@ -225,7 +226,7 @@ public class LocalFileListFragment extends FragmentListView {
         String [] result = null;
         String [] result = null;
         SparseBooleanArray positions = mList.getCheckedItemPositions();
         SparseBooleanArray positions = mList.getCheckedItemPositions();
         if (positions.size() > 0) {
         if (positions.size() > 0) {
-            Log.d(TAG, "Returning " + positions.size() + " selected files");
+            Log_OC.d(TAG, "Returning " + positions.size() + " selected files");
             result = new String[positions.size()];
             result = new String[positions.size()];
             for (int i=0; i<positions.size(); i++) {
             for (int i=0; i<positions.size(); i++) {
                 result[i] = ((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath();
                 result[i] = ((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath();

+ 14 - 13
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 
 
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
@@ -100,14 +101,14 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
      */
      */
     @Override
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
     public void onActivityCreated(Bundle savedInstanceState) {
-        Log.i(TAG, "onActivityCreated() start");
+        Log_OC.i(TAG, "onActivityCreated() start");
         
         
         super.onActivityCreated(savedInstanceState);
         super.onActivityCreated(savedInstanceState);
         mAdapter = new FileListListAdapter(mContainerActivity.getInitialDirectory(), mContainerActivity.getStorageManager(), getActivity(), mContainerActivity);
         mAdapter = new FileListListAdapter(mContainerActivity.getInitialDirectory(), mContainerActivity.getStorageManager(), getActivity(), mContainerActivity);
         setListAdapter(mAdapter);
         setListAdapter(mAdapter);
         
         
         if (savedInstanceState != null) {
         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);
             int position = savedInstanceState.getInt(SAVED_LIST_POSITION);
             setReferencePosition(position);
             setReferencePosition(position);
         }
         }
@@ -117,18 +118,18 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
         
         
         mHandler = new Handler();
         mHandler = new Handler();
         
         
-        Log.i(TAG, "onActivityCreated() stop");
+        Log_OC.i(TAG, "onActivityCreated() stop");
     }
     }
     
     
     
     
 
 
     @Override
     @Override
     public void onSaveInstanceState(Bundle savedInstanceState) {
     public void onSaveInstanceState(Bundle savedInstanceState) {
-        Log.i(TAG, "onSaveInstanceState() start");
+        Log_OC.i(TAG, "onSaveInstanceState() start");
         
         
         savedInstanceState.putInt(SAVED_LIST_POSITION, getReferencePosition());
         savedInstanceState.putInt(SAVED_LIST_POSITION, getReferencePosition());
         
         
-        Log.i(TAG, "onSaveInstanceState() stop");
+        Log_OC.i(TAG, "onSaveInstanceState() stop");
     }
     }
     
     
     
     
@@ -149,7 +150,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
             }
             }
             
             
         } else {
         } else {
-            Log.d(TAG, "Null object in ListAdapter!!");
+            Log_OC.d(TAG, "Null object in ListAdapter!!");
         }
         }
         
         
     }
     }
@@ -276,7 +277,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                     startActivity(i);
                     startActivity(i);
                     
                     
                 } catch (Throwable t) {
                 } 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; 
                     boolean toastIt = true; 
                     String mimeType = "";
                     String mimeType = "";
                     try {
                     try {
@@ -295,13 +296,13 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                         }
                         }
                         
                         
                     } catch (IndexOutOfBoundsException e) {
                     } 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) {
                     } 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) {
                     } catch (Throwable th) {
-                        Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+                        Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
                         
                         
                     } finally {
                     } finally {
                         if (toastIt) {
                         if (toastIt) {
@@ -404,7 +405,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
         
         
             // If that's not a directory -> List its parent
             // If that's not a directory -> List its parent
             if(!directory.isDirectory()){
             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());
                 directory = storageManager.getFileById(directory.getParentId());
             }
             }
 
 
@@ -477,7 +478,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
     public void onDismiss(EditNameDialog dialog) {
     public void onDismiss(EditNameDialog dialog) {
         if (dialog.getResult()) {
         if (dialog.getResult()) {
             String newFilename = dialog.getNewFilename();
             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, 
             RemoteOperation operation = new RenameFileOperation(mTargetFile, 
                                                                 AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
                                                                 AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
                                                                 newFilename, 
                                                                 newFilename, 
@@ -522,7 +523,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
     
     
     @Override
     @Override
     public void onCancel(String callerTag) {
     public void onCancel(String callerTag) {
-        Log.d(TAG, "REMOVAL CANCELED");
+        Log_OC.d(TAG, "REMOVAL CANCELED");
     }
     }
 
 
 
 

+ 4 - 0
src/com/owncloud/android/utils/FileStorageUtils.java

@@ -65,6 +65,10 @@ public class FileStorageUtils {
         }
         }
 
 
     }
     }
+    
+    public static final String getLogPath()  {
+        return Environment.getExternalStorageDirectory() + File.separator + "owncloud" + File.separator + "log";
+    }
 
 
     // to ensure we will not add the slash twice between filename and
     // to ensure we will not add the slash twice between filename and
     // folder-name
     // folder-name

+ 2 - 3
src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java

@@ -30,12 +30,11 @@ import java.util.Set;
 
 
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.methods.RequestEntity;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 
 
 import eu.alefzero.webdav.OnDatatransferProgressListener;
 import eu.alefzero.webdav.OnDatatransferProgressListener;
 
 
-import android.util.Log;
-
 
 
 /**
 /**
  * A RequestEntity that represents a PIECE of a file.
  * A RequestEntity that represents a PIECE of a file.
@@ -136,7 +135,7 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity, Progres
             }
             }
             
             
         } catch (IOException io) {
         } 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);   
             throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
             
             
         }
         }

+ 2 - 3
src/eu/alefzero/webdav/FileRequestEntity.java

@@ -32,12 +32,11 @@ import java.util.Set;
 
 
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.methods.RequestEntity;
 
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 
 
 import eu.alefzero.webdav.OnDatatransferProgressListener;
 import eu.alefzero.webdav.OnDatatransferProgressListener;
 
 
-import android.util.Log;
-
 
 
 /**
 /**
  * A RequestEntity that represents a File.
  * A RequestEntity that represents a File.
@@ -123,7 +122,7 @@ public class FileRequestEntity implements RequestEntity, ProgressiveDataTransfer
             }
             }
             
             
         } catch (IOException io) {
         } 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);   
             throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
             
             
         } finally {
         } finally {

+ 342 - 341
src/eu/alefzero/webdav/WebdavClient.java

@@ -1,341 +1,342 @@
-/* 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 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.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.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)":""));
-            
-        } 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.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.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.d(TAG, "Creating directory " + path);
-            status = executeMethod(mkcol);
-            Log.d(TAG, "Status returned: " + status);
-            result = mkcol.succeeded();
-            
-            Log.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.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.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.e(TAG, "HTTP violation while " + doing, e);
-
-        } else if (e instanceof IOException) {
-            Log.e(TAG, "Unrecovered transport exception while " + doing, e);
-
-        } else {
-            Log.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;
-    }
-
-}
+/* 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_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.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;
+    }
+
+}

+ 3 - 1
src/eu/alefzero/webdav/WebdavEntry.java

@@ -24,6 +24,8 @@ import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
 import org.apache.jackrabbit.webdav.property.DavPropertySet;
 
 
+import com.owncloud.android.Log_OC;
+
 import android.net.Uri;
 import android.net.Uri;
 import android.util.Log;
 import android.util.Log;
 
 
@@ -89,7 +91,7 @@ public class WebdavEntry {
             }
             }
 
 
         } else {
         } else {
-            Log.e("WebdavEntry",
+            Log_OC.e("WebdavEntry",
                     "General fuckup, no status for webdav response");
                     "General fuckup, no status for webdav response");
         }
         }
     }
     }