Browse Source

Merge branch 'develop' into file_browsing_refactoring

Conflicts:
	AndroidManifest.xml
	src/com/owncloud/android/ui/activity/FileDisplayActivity.java
	src/com/owncloud/android/ui/fragment/FileDetailFragment.java
David A. Velasco 12 years ago
parent
commit
b36914df88
74 changed files with 3339 additions and 2102 deletions
  1. 13 5
      AndroidManifest.xml
  2. 36 35
      doc/CodeStyleFormatter.xml
  3. 225 179
      res/layout-land/account_setup.xml
  4. 240 177
      res/layout/account_setup.xml
  5. 23 0
      res/values/oauth2_configuration.xml
  6. 18 4
      res/values/strings.xml
  7. 4 0
      res/values/styles.xml
  8. 8 3
      src/com/owncloud/android/AccountUtils.java
  9. 0 2
      src/com/owncloud/android/DisplayUtils.java
  10. 91 69
      src/com/owncloud/android/Uploader.java
  11. 144 111
      src/com/owncloud/android/authentication/AccountAuthenticator.java
  12. 1 1
      src/com/owncloud/android/authentication/AccountAuthenticatorService.java
  13. 1085 0
      src/com/owncloud/android/authentication/AuthenticatorActivity.java
  14. 53 0
      src/com/owncloud/android/authentication/OAuth2Constants.java
  15. 0 88
      src/com/owncloud/android/authenticator/AuthenticationRunnable.java
  16. 0 25
      src/com/owncloud/android/authenticator/OnAuthenticationResultListener.java
  17. 0 29
      src/com/owncloud/android/authenticator/OnConnectCheckListener.java
  18. 0 1
      src/com/owncloud/android/datamodel/FileDataStorageManager.java
  19. 0 1
      src/com/owncloud/android/db/DbHandler.java
  20. 0 1
      src/com/owncloud/android/extensions/ExtensionsAvailableDialog.java
  21. 0 1
      src/com/owncloud/android/extensions/ExtensionsListActivity.java
  22. 0 1
      src/com/owncloud/android/files/BootupBroadcastReceiver.java
  23. 5 4
      src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
  24. 1 5
      src/com/owncloud/android/files/OwnCloudFileObserver.java
  25. 51 25
      src/com/owncloud/android/files/services/FileDownloader.java
  26. 0 1
      src/com/owncloud/android/files/services/FileObserverService.java
  27. 0 55
      src/com/owncloud/android/files/services/FileOperation.java
  28. 67 35
      src/com/owncloud/android/files/services/FileUploader.java
  29. 0 1
      src/com/owncloud/android/location/LocationServiceLauncherReciever.java
  30. 0 1
      src/com/owncloud/android/location/LocationUpdateService.java
  31. 0 2
      src/com/owncloud/android/network/AdvancedSslSocketFactory.java
  32. 0 2
      src/com/owncloud/android/network/AdvancedX509TrustManager.java
  33. 268 0
      src/com/owncloud/android/network/BearerAuthScheme.java
  34. 97 0
      src/com/owncloud/android/network/BearerCredentials.java
  35. 52 31
      src/com/owncloud/android/network/OwnCloudClientUtils.java
  36. 0 1
      src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
  37. 94 0
      src/com/owncloud/android/operations/CreateFolderOperation.java
  38. 0 1
      src/com/owncloud/android/operations/DownloadFileOperation.java
  39. 94 0
      src/com/owncloud/android/operations/ExistenceCheckOperation.java
  40. 174 0
      src/com/owncloud/android/operations/OAuth2GetAccessToken.java
  41. 3 4
      src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java
  42. 152 5
      src/com/owncloud/android/operations/RemoteOperation.java
  43. 30 5
      src/com/owncloud/android/operations/RemoteOperationResult.java
  44. 0 2
      src/com/owncloud/android/operations/RemoveFileOperation.java
  45. 1 2
      src/com/owncloud/android/operations/RenameFileOperation.java
  46. 0 1
      src/com/owncloud/android/operations/SynchronizeFileOperation.java
  47. 0 1
      src/com/owncloud/android/operations/SynchronizeFolderOperation.java
  48. 1 2
      src/com/owncloud/android/operations/UpdateOCVersionOperation.java
  49. 0 1
      src/com/owncloud/android/providers/FileContentProvider.java
  50. 1 1
      src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
  51. 1 1
      src/com/owncloud/android/syncadapter/ContactSyncAdapter.java
  52. 31 12
      src/com/owncloud/android/syncadapter/FileSyncAdapter.java
  53. 4 5
      src/com/owncloud/android/ui/activity/AccountSelectActivity.java
  54. 0 609
      src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
  55. 0 1
      src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java
  56. 17 11
      src/com/owncloud/android/ui/activity/FailedUploadActivity.java
  57. 47 120
      src/com/owncloud/android/ui/activity/FileDisplayActivity.java
  58. 3 14
      src/com/owncloud/android/ui/activity/InstantUploadActivity.java
  59. 3 3
      src/com/owncloud/android/ui/activity/LandingActivity.java
  60. 0 1
      src/com/owncloud/android/ui/activity/UploadFilesActivity.java
  61. 0 1
      src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
  62. 0 1
      src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java
  63. 118 141
      src/com/owncloud/android/ui/fragment/FileDetailFragment.java
  64. 0 1
      src/com/owncloud/android/ui/fragment/LocalFileListFragment.java
  65. 3 9
      src/com/owncloud/android/ui/fragment/OCFileListFragment.java
  66. 4 4
      src/com/owncloud/android/ui/preview/FileDownloadFragment.java
  67. 7 10
      src/com/owncloud/android/ui/preview/PreviewImageActivity.java
  68. 11 14
      src/com/owncloud/android/ui/preview/PreviewImageFragment.java
  69. 0 8
      src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
  70. 14 18
      src/com/owncloud/android/ui/preview/PreviewMediaFragment.java
  71. 11 11
      src/com/owncloud/android/ui/preview/PreviewVideoActivity.java
  72. 0 1
      src/com/owncloud/android/utils/FileStorageUtils.java
  73. 33 184
      src/eu/alefzero/webdav/WebdavClient.java
  74. 0 1
      src/eu/alefzero/webdav/WebdavEntry.java

+ 13 - 5
AndroidManifest.xml

@@ -91,7 +91,7 @@
         <activity android:name=".ui.activity.PreferencesNewSessionewSession" >
         </activity>
         
-		<activity	android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
+        <activity	android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
 		        
         <activity	android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"
 					android:label="@string/app_name"
@@ -99,7 +99,7 @@
 		</activity>        
 
         <service
-            android:name=".authenticator.AccountAuthenticatorService"
+            android:name=".authentication.AccountAuthenticatorService"
             android:exported="true">
             <intent-filter  android:priority="100">
                 <action android:name="android.accounts.AccountAuthenticator" />
@@ -131,9 +131,16 @@
         </provider>
 
         <activity
-            android:name=".ui.activity.AuthenticatorActivity"
+            android:name=".authentication.AuthenticatorActivity"
             android:exported="true"
-            android:theme="@style/Theme.ownCloud.noActionBar" >
+            android:theme="@style/Theme.ownCloud.noActionBar" 
+            android:launchMode="singleTask">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="@string/oauth2_redirect_scheme" />
+            </intent-filter>
             <intent-filter>
                 <action android:name="com.owncloud.android.workaround.accounts.CREATE" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -170,6 +177,7 @@
             </intent-filter>
         </receiver>
         <service android:name=".files.services.FileObserverService"/>
+        
     </application>
-    
+
 </manifest>

+ 36 - 35
doc/CodeStyleFormatter.xml

@@ -1,16 +1,17 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <profiles version="12">
-<profile kind="CodeFormatterProfile" name="Owncloud" version="12">
+<profile kind="CodeFormatterProfile" name="OwnCloud-Convention" version="12">
 <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
@@ -23,11 +24,11 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="32"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
@@ -50,7 +51,7 @@
 <setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
@@ -72,8 +73,8 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="0"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
@@ -81,14 +82,14 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
 <setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
-<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
@@ -101,7 +102,7 @@
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
@@ -119,11 +120,11 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
@@ -149,21 +150,21 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
@@ -181,15 +182,15 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
@@ -204,7 +205,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
@@ -216,16 +217,16 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="false"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
@@ -233,10 +234,10 @@
 <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
@@ -246,16 +247,16 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
 <setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
 <setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
 <setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
@@ -277,7 +278,7 @@
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
 <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>

+ 225 - 179
res/layout-land/account_setup.xml

@@ -1,12 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ownCloud Android client application
 
-  Copyright (C) 2012  Bartek Przybylski
-  Copyright (C) 2012-2013 ownCloud Inc.
+  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 version 2,
+  it under the terms of the GNU General Public License version 2,
   as published by the Free Software Foundation.
 
   This program is distributed in the hope that it will be useful,
@@ -16,177 +16,223 @@
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:oc="http://schemas.android.com/apk/res/com.owncloud.android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:focusable="true"
-    android:gravity="center|fill"
-    android:orientation="vertical" >
-
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
-        android:layout_weight="1" >
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" >
-
-            <ImageView
-                android:id="@+id/imageView1"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_margin="7dp"
-                android:layout_weight="1"
-                android:src="@drawable/owncloud_logo" />
-
-            <LinearLayout
-                android:id="@+id/LinearLayout1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="1"
-                android:orientation="vertical" >
-
-                <FrameLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1" >
-
-                    <EditText
-                        android:id="@+id/host_URL"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:ems="10"
-                        android:hint="@string/auth_host_url"
-                        android:inputType="textNoSuggestions">
-                        <requestFocus />
-                    </EditText>
-
-                    <ImageView
-                        android:id="@+id/refreshButton"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="right|center_vertical"
-                        android:src="@drawable/ic_action_refresh_black"
-                        android:visibility="invisible" />
-                </FrameLayout>
-
-                <LinearLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="50dp"
-                    android:layout_weight="1" >
-
-                    <ImageView
-                        android:id="@+id/action_indicator"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp"
-                        android:src="@android:drawable/stat_notify_sync"
-                        android:visibility="invisible" />
-
-                    <TextView
-                        android:id="@+id/status_text"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="TextView"
-                        android:visibility="invisible" />
-                </LinearLayout>
-
-                <TextView
-                    android:id="@+id/textView2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="0dp"
-                    android:layout_weight="1"
-                    android:text="@string/auth_login_details"
-                    android:textAppearance="?android:attr/textAppearanceSmall" />
-
-                <EditText
-                    android:id="@+id/account_username"
-                    android:layout_width="match_parent"
-                    android:layout_height="0dp"
-                    android:layout_weight="1"
-                    android:ems="10"
-                    android:hint="@string/auth_username"
-                    android:inputType="textNoSuggestions" />
-
-                <FrameLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1" >
-
-                    <EditText
-                        android:id="@+id/account_password"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:ems="10"
-                        android:hint="@string/auth_password"
-                        android:inputType="textPassword"/>
-
-                    <ImageView
-                        android:id="@+id/viewPassword"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="right|center_vertical"
-                        android:src="@android:drawable/ic_menu_view"
-                        android:visibility="invisible" />
-                </FrameLayout>
-            </LinearLayout>
-        </LinearLayout>
-    </FrameLayout>
-
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true" >
-
-        <LinearLayout
-            android:id="@+id/buttons_layout"        
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:weightSum="1">
-
-            <Button
-                android:id="@+id/buttonCancel"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight=".5"
-                android:onClick="onCancelClick"
-                android:text="@string/common_cancel" />
-
-            <Button
-                android:id="@+id/buttonOK"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight=".5"
-                android:enabled="false"
-                android:onClick="onOkClick"
-                android:text="@string/setup_btn_connect"
-                android:textColor="@android:color/black" />
-            
-        </LinearLayout>
-        
-		<Button
-			android:id="@+id/account_register"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_below="@id/buttons_layout"
-			android:layout_centerHorizontal="true"
-			android:onClick="onRegisterClick"
-			android:paddingTop="10dp"
-			android:paddingBottom="10dp"
-			android:textColor="#0000FF"
-			android:background="@android:color/transparent" />
-			<!-- android:text="@string/app_name @string/auth_register" /-->
-        
-    </RelativeLayout>
-
-</LinearLayout>
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:oc="http://schemas.android.com/apk/res/com.owncloud.android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:focusable="true"
+    android:gravity="center|fill"
+    android:orientation="vertical" >
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginLeft="16dip"
+        android:layout_marginRight="16dip"
+        android:layout_weight="1" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" >
+
+            <ImageView
+                android:id="@+id/imageView1"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_margin="7dp"
+                android:layout_weight="1"
+                android:src="@drawable/owncloud_logo" />
+
+            <LinearLayout
+                android:id="@+id/LinearLayout1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="1"
+                android:orientation="vertical" >
+
+                <FrameLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1" >
+
+                    <EditText
+                        android:id="@+id/hostUrlInput"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ems="10"
+                        android:hint="@string/auth_host_url"
+                        android:inputType="textNoSuggestions">
+                        <requestFocus />
+                    </EditText>
+
+                    <ImageView
+                        android:id="@+id/refreshButton"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="right|center_vertical"
+                        android:src="@drawable/ic_action_refresh_black"
+                    	android:onClick="onRefreshClick"
+                        android:visibility="invisible" />
+                </FrameLayout>
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="50dp"
+                    android:layout_weight="1" >
+
+                    <ImageView
+                        android:id="@+id/action_indicator"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp"
+                        android:src="@android:drawable/stat_notify_sync"
+                        android:visibility="invisible" />
+
+                    <TextView
+                        android:id="@+id/status_text"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="TextView"
+                        android:visibility="invisible" />
+                </LinearLayout>
+
+                <CheckBox
+                    android:id="@+id/oauth_onOff_check"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:checked="false"
+                    android:onClick="onCheckClick"
+                    android:text="@string/oauth_check_onoff"
+                    android:textAppearance="?android:attr/textAppearanceSmall" />
+
+                <TextView
+                    android:id="@+id/textView2"
+                    android:layout_width="wrap_content"
+                    android:layout_height="0dp"
+                    android:layout_weight="1"
+                    android:text="@string/auth_login_details"
+                    android:textAppearance="?android:attr/textAppearanceSmall" />
+
+	            <EditText
+	                android:id="@+id/oAuthEntryPoint_1"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1"
+	                android:ems="10"
+                	android:enabled="false"
+	                android:text="@string/oauth2_url_endpoint_auth"
+	                android:singleLine="true"
+	                android:visibility="gone" >
+	
+	                <requestFocus />
+	            </EditText>            
+	
+	            <EditText
+	                android:id="@+id/oAuthEntryPoint_2"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1"
+	                android:ems="10"
+                	android:enabled="false"
+	                android:text="@string/oauth2_url_endpoint_access"
+	                android:singleLine="true"
+	                android:visibility="gone" >
+	
+	                <requestFocus />
+	            </EditText>            
+	
+                <EditText
+                    android:id="@+id/account_username"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp"
+                    android:layout_weight="1"
+                    android:ems="10"
+                    android:hint="@string/auth_username"
+                    android:inputType="textNoSuggestions" />
+
+                <FrameLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1" >
+
+                    <EditText
+                        android:id="@+id/account_password"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ems="10"
+                        android:hint="@string/auth_password"
+                        android:inputType="textPassword"/>
+
+                    <ImageView
+                        android:id="@+id/viewPasswordButton"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="right|center_vertical"
+                        android:src="@android:drawable/ic_menu_view"
+						android:onClick="onViewPasswordClick"
+                        android:visibility="invisible" />
+                </FrameLayout>
+                
+	            <TextView
+	                android:id="@+id/auth_status_text"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1" 
+	                android:text="@string/text_placeholder"
+	                android:layout_marginLeft="5dp"
+	                android:layout_marginRight="5dp"
+					android:drawableLeft="@android:drawable/stat_notify_sync"
+	    			android:drawablePadding="5dip"
+	    			android:visibility="invisible"                
+	                />
+                
+            </LinearLayout>
+            
+        </LinearLayout>
+    </FrameLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true" >
+
+        <LinearLayout
+            android:id="@+id/buttons_layout"        
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:weightSum="1">
+
+            <Button
+                android:id="@+id/buttonOK"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight=".5"
+                android:layout_marginLeft="16dip"
+		        android:layout_marginRight="16dip"
+                android:enabled="false"
+                android:onClick="onOkClick"
+                android:text="@string/setup_btn_connect"
+                android:textColor="@android:color/black" />
+            
+        </LinearLayout>
+        
+		<Button
+			android:id="@+id/account_register"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_below="@id/buttons_layout"
+			android:layout_centerHorizontal="true"
+			android:onClick="onRegisterClick"
+			android:paddingTop="10dp"
+			android:paddingBottom="10dp"
+			android:textColor="#0000FF"
+			android:background="@android:color/transparent" />
+			<!-- android:text="@string/app_name @string/auth_register" /-->
+        
+    </RelativeLayout>
+
+</LinearLayout>

+ 240 - 177
res/layout/account_setup.xml

@@ -1,12 +1,12 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ownCloud Android client application
 
-  Copyright (C) 2012  Bartek Przybylski
-  Copyright (C) 2012-2013 ownCloud Inc.
+  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 version 2,
+  it under the terms of the GNU General Public License version 2,
   as published by the Free Software Foundation.
 
   This program is distributed in the hope that it will be useful,
@@ -16,175 +16,238 @@
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:focusable="true"
-    android:gravity="center|fill"
-    android:orientation="vertical" >
-
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:layout_marginLeft="16dip"
-        android:layout_marginRight="16dip"
-        android:layout_weight="1" >
-
-        <LinearLayout
-            android:id="@+id/LinearLayout1"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:layout_weight="1"
-            android:orientation="vertical" >
-
-            <ImageView
-                android:id="@+id/imageView1"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginBottom="10dp"
-                android:layout_weight="1"
-                android:src="@drawable/owncloud_logo" />
-
-            <FrameLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1" >
-
-                <EditText
-                    android:id="@+id/host_URL"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:ems="10"
-                    android:hint="@string/auth_host_url"
-                    android:inputType="textNoSuggestions" >
-                    <requestFocus />
-                </EditText>
-
-                <ImageView
-                    android:id="@+id/refreshButton"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:src="@drawable/ic_action_refresh_black"
-                    android:layout_gravity="right|center_vertical"
-                    android:visibility="invisible" />
-
-            </FrameLayout>
-
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="50dp"
-                android:layout_weight="1" >
-
-                <ImageView
-                    android:id="@+id/action_indicator"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_marginLeft="5dp"
-                    android:layout_marginRight="5dp"
-                    android:src="@android:drawable/stat_notify_sync"
-                    android:visibility="invisible" />
-
-                <TextView
-                    android:id="@+id/status_text"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="TextView"
-                    android:visibility="invisible" />
-
-            </LinearLayout>
-
-            <TextView
-                android:id="@+id/textView2"
-                android:layout_width="wrap_content"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:text="@string/auth_login_details"
-                android:textAppearance="?android:attr/textAppearanceSmall" />
-
-            <EditText
-                android:id="@+id/account_username"
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:ems="10"
-                android:hint="@string/auth_username"
-                android:inputType="textNoSuggestions" />
-
-            <FrameLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1" >
-
-                <EditText
-                    android:id="@+id/account_password"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:ems="10"
-                    android:hint="@string/auth_password"
-                    android:inputType="textPassword"/>
-
-                <ImageView
-                    android:id="@+id/viewPassword"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="right|center_vertical"
-                    android:src="@android:drawable/ic_menu_view"
-                    android:visibility="invisible" />
-
-            </FrameLayout>
-
-            </LinearLayout>
-
-    </FrameLayout>
-
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-        <LinearLayout
-            android:id="@+id/buttons_layout"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:weightSum="1" >
-
-            <Button
-                android:id="@+id/buttonCancel"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight=".5"
-                android:onClick="onCancelClick"
-                android:text="@string/common_cancel" />
-
-            <Button
-                android:id="@+id/buttonOK"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight=".5"
-                android:enabled="false"
-                android:onClick="onOkClick"
-                android:text="@string/setup_btn_connect"
-                android:textColor="@android:color/black" />
-
-        </LinearLayout>
-        
-		<Button
-			android:id="@+id/account_register"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_below="@id/buttons_layout"
-			android:layout_centerHorizontal="true"
-			android:onClick="onRegisterClick"
-			android:paddingTop="10dp"
-			android:paddingBottom="10dp"
-			android:textColor="#0000FF"
-			android:background="@android:color/transparent" />
-			<!-- android:text="@string/app_name @string/auth_register" /-->
-        
-    </RelativeLayout>
-
-</LinearLayout>
+-->
+
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+	<LinearLayout
+	    android:layout_width="match_parent"
+	    android:layout_height="wrap_content"
+	    android:layout_gravity="center"
+	    android:focusable="true"
+	    android:gravity="center"
+	    android:orientation="vertical" >
+
+    	<FrameLayout
+			android:layout_width="match_parent"
+			android:layout_height="0dip"
+			android:layout_gravity="center"
+			android:layout_marginBottom="50dip"
+			android:layout_marginLeft="16dip"
+			android:layout_marginRight="16dip"
+			android:layout_weight="1" >
+		
+			<LinearLayout
+				android:id="@+id/LinearLayout1"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:layout_gravity="center"
+				android:orientation="vertical" >
+		
+				<ImageView
+					android:id="@+id/imageView1"
+					android:layout_width="match_parent"
+					android:layout_height="wrap_content"
+					android:layout_marginBottom="10dp"
+					android:layout_weight="1"
+					android:src="@drawable/owncloud_logo" />
+		
+	            <FrameLayout
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1" >
+	
+	                <EditText
+	                    android:id="@+id/hostUrlInput"
+	                    android:layout_width="match_parent"
+	                    android:layout_height="wrap_content"
+	                    android:ems="10"
+	                    android:hint="@string/auth_host_url"
+	                    android:inputType="textNoSuggestions" >
+	                    <requestFocus />
+	                </EditText>
+	
+	                <ImageView
+	                    android:id="@+id/refreshButton"
+	                    android:layout_width="wrap_content"
+	                    android:layout_height="wrap_content"
+	                    android:src="@drawable/ic_action_refresh_black"
+	                    android:layout_gravity="right|center_vertical"
+	                    android:visibility="invisible" />
+	
+	            </FrameLayout>
+	
+	            <LinearLayout
+	                android:layout_width="match_parent"
+	                android:layout_height="50dp"
+	                android:layout_weight="1" >
+	
+	                <ImageView
+	                    android:id="@+id/action_indicator"
+	                    android:layout_width="wrap_content"
+	                    android:layout_height="wrap_content"
+	                    android:layout_marginLeft="5dp"
+	                    android:layout_marginRight="5dp"
+	                    android:src="@android:drawable/stat_notify_sync"
+	                    android:visibility="invisible" />
+	
+	                <TextView
+	                    android:id="@+id/status_text"
+	                    android:layout_width="wrap_content"
+	                    android:layout_height="wrap_content"
+	                    android:text="TextView"
+	                    android:visibility="invisible" />
+	
+	            </LinearLayout>
+	
+	            <CheckBox
+	                android:id="@+id/oauth_onOff_check"
+	                android:layout_width="wrap_content"
+	                android:layout_height="wrap_content"
+	                android:checked="false"
+	                android:onClick="onCheckClick"
+	                android:text="@string/oauth_check_onoff"
+	                android:textAppearance="?android:attr/textAppearanceSmall" />
+	
+				<TextView
+	                android:id="@+id/textView2"
+	                android:layout_width="wrap_content"
+	                android:layout_height="0dp"
+	                android:layout_weight="1"
+	                android:text="@string/auth_login_details"
+	                android:textAppearance="?android:attr/textAppearanceSmall" />
+	
+	            <EditText
+	                android:id="@+id/oAuthEntryPoint_1"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1"
+	                android:ems="10"
+	                android:text="@string/oauth2_url_endpoint_auth"
+	                android:singleLine="true"
+	                android:visibility="gone" >
+	
+	                <requestFocus />
+	            </EditText>            
+	
+	            <EditText
+	                android:id="@+id/oAuthEntryPoint_2"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1"
+	                android:ems="10"
+		            android:text="@string/oauth2_url_endpoint_access"
+	                android:singleLine="true"
+	                android:visibility="gone" >
+	
+	                <requestFocus />
+	            </EditText>            
+	
+				<EditText
+	                android:id="@+id/account_username"
+	                android:layout_width="match_parent"
+	                android:layout_height="0dp"
+	                android:layout_weight="1"
+	                android:ems="10"
+	                android:hint="@string/auth_username"
+	                android:inputType="textNoSuggestions" />
+	
+	            <FrameLayout
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1" >
+	
+	                <EditText
+	                    android:id="@+id/account_password"
+	                    android:layout_width="match_parent"
+	                    android:layout_height="wrap_content"
+	                    android:ems="10"
+	                    android:hint="@string/auth_password"
+	                    android:inputType="textPassword"/>
+	
+	                <ImageView
+	                    android:id="@+id/viewPasswordButton"
+	                    android:layout_width="wrap_content"
+	                    android:layout_height="wrap_content"
+	                    android:layout_gravity="right|center_vertical"
+	                    android:src="@android:drawable/ic_menu_view"
+						android:onClick="onViewPasswordClick"
+	                    android:visibility="invisible" />
+	
+	            </FrameLayout>
+		
+	            <TextView
+	                android:id="@+id/auth_status_text"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+	                android:layout_weight="1" 
+	                android:text="@string/text_placeholder"
+	                android:layout_marginLeft="5dp"
+	                android:layout_marginRight="5dp"
+					android:drawableLeft="@android:drawable/stat_notify_sync"
+	    			android:drawablePadding="5dip"
+	    			android:visibility="invisible"                
+	                />
+	                    
+	           </LinearLayout>
+	
+	    </FrameLayout>
+	
+	    <RelativeLayout
+	        android:layout_width="match_parent"
+	        android:layout_height="wrap_content">
+	
+	        <LinearLayout
+	            android:id="@+id/buttons_layout"
+	            android:layout_width="match_parent"
+	            android:layout_height="wrap_content"
+	            android:weightSum="1">
+	
+	            <Button
+	                android:id="@+id/buttonOK"
+	                android:layout_width="match_parent"
+	                android:layout_height="wrap_content"
+		            android:layout_gravity="center_horizontal"
+		           	android:layout_marginLeft="16dip"
+		            android:layout_marginRight="16dip"
+	                android:enabled="false"
+	                android:onClick="onOkClick"
+	                android:text="@string/setup_btn_connect"
+	                android:textColor="@android:color/black" />
+	
+	        </LinearLayout>
+	        
+			<Button
+				android:id="@+id/account_register"
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:layout_below="@id/buttons_layout"
+				android:layout_centerHorizontal="true"
+				android:onClick="onRegisterClick"
+				android:paddingTop="10dp"
+				android:paddingBottom="10dp"
+				android:textColor="#0000FF"
+				android:background="@android:color/transparent" />
+			
+			<Button
+				android:id="@+id/account_register"
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:layout_below="@id/buttons_layout"
+				android:layout_centerHorizontal="true"
+				android:onClick="onRegisterClick"
+				android:paddingTop="10dp"
+				android:paddingBottom="10dp"
+				android:textColor="#0000FF"
+				android:background="@android:color/transparent" />
+				<!-- android:text="@string/app_name @string/auth_register" /-->
+	        
+	    </RelativeLayout>
+
+	</LinearLayout>
+			
+</ScrollView>

+ 23 - 0
res/values/oauth2_configuration.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Flag to configure OAuth availability in the app.
+    	 3 valid values now: on, off, optional	
+     -->
+    <string name="oauth2_mode">off</string>
+    
+    <!-- constants that must be respected by the authorization server; if changed, the app must be rebuild -->
+    <string name="oauth2_redirect_scheme">owncloud</string>
+    <string name="oauth2_redirect_uri">owncloud://callback</string>
+    
+    <!-- values that should be provided by ownCloud server -->
+    <string name="oauth2_url_endpoint_auth">http://oauth2.authorization.server.org/paht/to/endpoint/for/authorization</string>
+    <string name="oauth2_url_endpoint_access">http://oauth2.authorization.server.org/paht/to/endporint/for/access/token</string>
+    <string name="oauth2_scope">owncloud</string>
+    <string name="oauth2_grant_type">authorization_code</string>	<!-- the only one supported right now -->
+    <string name="oauth2_response_type">code</string>				<!-- depends on oauth2_grant_type -->
+    
+    <!-- values that should be pre-agreed between app and authorization server, but can be loaded without rebuilding the app -->
+    <string name="oauth2_client_id">com.owncloud.android</string>	<!-- preferable that client decides this -->
+    <string name="oauth2_client_secret"></string>					<!-- preferable that client decides this -->
+    
+</resources>

+ 18 - 4
res/values/strings.xml

@@ -47,7 +47,7 @@
     <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">Server address</string>
     <string name="auth_username">Username</string>
     <string name="auth_password">Password</string>
     <string name="auth_register">I am new to %1$s</string>
@@ -118,8 +118,9 @@
     <string name="sync_string_contacts">Contacts</string>
     <string name="sync_fail_ticker">Synchronization failed</string>
     <string name="sync_fail_content">Synchronization of %1$s could not be completed</string>
-    <string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>
-    <string name="sync_conflicts_in_favourites_content">%1$d kept-in-sync files could not be sync\'ed</string>
+    <string name="sync_fail_content_unauthorized">Invalid credentials for %1$s</string>
+	<string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>
+	<string name="sync_conflicts_in_favourites_content">%1$d kept-in-sync files could not be sync\'ed</string>
     <string name="sync_fail_in_favourites_ticker">Kept-in-sync files failed</string>
     <string name="sync_fail_in_favourites_content">Contents of %1$d files could not be sync\'ed (%2$d conflicts)</string>
     <string name="sync_foreign_files_forgotten_ticker">Some local files were forgotten</string>
@@ -200,9 +201,15 @@
     <string name="auth_wrong_connection_title">Couldn\'t establish connection</string>
     <string name="auth_secure_connection">Secure connection established</string>
     <string name="auth_login_details">Login details</string>
-    <string name="auth_unauthorized">Invalid login / password</string>
+    <string name="auth_unauthorized">Invalid credentials</string>
+	<string name="auth_oauth_error">Unsuccessful authorization</string>
+	<string name="auth_oauth_error_access_denied">Access denied by authorization server</string>
     <string name="auth_not_found">Wrong path given</string>
     <string name="auth_internal">Internal server error, code %1$d</string>
+    <string name="auth_wtf_reenter_URL">Unexpected state; please, enter the server URL again</string>
+    <string name="auth_expired_oauth_token_toast">Your authorization expired.\nPlease, authorize again</string>
+    <string name="auth_expired_basic_auth_toast">Your saved credentials are invalid.\nPlease, enter the current credentials</string>
+    
     <string name="crashlog_message">Application terminated unexpectedly. Would you like to submit a crash report?</string>
     <string name="crashlog_send_report">Send report</string>
     <string name="crashlog_dont_send_report">Don\'t send report</string>
@@ -229,6 +236,13 @@
     <string name="wait_a_moment">Wait a moment</string>
     <string name="filedisplay_unexpected_bad_get_content">"Unexpected problem ; please select the file from a different app"</string>
     <string name="filedisplay_no_file_selected">No file was selected</string>
+    
+    <string name="oauth_host_url">oAuth2 URL</string> 
+    <string name="oauth_check_onoff">Login with oAuth2.</string> 
+    <string name="oauth_login_connection">Connecting to oAuth2 server…</string>    
+    <string name="oauth_code_validation_message">Please, open a web browser and go to:\n%1$s.\nValidate this code there:\n%2$s</string>
+    <string name="oauth_connection_url_unavailable">Connection to this URL not available.</string> 
+        
     <string name="ssl_validator_title">Warning</string>
     <string name="ssl_validator_header">The identity of the site could not be verified</string>
     <string name="ssl_validator_reason_cert_not_trusted">- The server certificate is not trusted</string>

+ 4 - 0
res/values/styles.xml

@@ -101,6 +101,10 @@
 		<item name="android:singleLine">true</item>
   		    
     </style>
+	
+	<style name="OAuthDialog" parent="@android:style/Theme.Dialog">
+		<item name="android:windowNoTitle">false</item>	
+	</style>    
 		
 	<color name="setup_text_hint">#777777</color>
 	<color name="setup_text_typed">#000000</color>

+ 8 - 3
src/com/owncloud/android/AccountUtils.java

@@ -18,7 +18,7 @@
 
 package com.owncloud.android;
 
-import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.utils.OwnCloudVersion;
 
 import android.accounts.Account;
@@ -31,6 +31,7 @@ public class AccountUtils {
     public static final String WEBDAV_PATH_1_2 = "/webdav/owncloud.php";
     public static final String WEBDAV_PATH_2_0 = "/files/webdav.php";
     public static final String WEBDAV_PATH_4_0 = "/remote.php/webdav";
+    private static final String ODAV_PATH = "/remote.php/odav";
     public static final String CARDDAV_PATH_2_0 = "/apps/contacts/carddav.php";
     public static final String CARDDAV_PATH_4_0 = "/remote/carddav.php";
     public static final String STATUS_PATH = "/status.php";
@@ -112,8 +113,11 @@ public class AccountUtils {
      * @param version version of owncloud
      * @return webdav path for given OC version, null if OC version unknown
      */
-    public static String getWebdavPath(OwnCloudVersion version) {
+    public static String getWebdavPath(OwnCloudVersion version, boolean supportsOAuth) {
         if (version != null) {
+            if (supportsOAuth) {
+                return ODAV_PATH;
+            }
             if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)
                 return WEBDAV_PATH_4_0;
             if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0
@@ -136,8 +140,9 @@ public class AccountUtils {
             AccountManager ama = AccountManager.get(context);
             String baseurl = ama.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL);
             String strver  = ama.getUserData(account, AccountAuthenticator.KEY_OC_VERSION);
+            boolean supportsOAuth = (ama.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);
             OwnCloudVersion ver = new OwnCloudVersion(strver);
-            String webdavpath = getWebdavPath(ver);
+            String webdavpath = getWebdavPath(ver, supportsOAuth);
 
             if (webdavpath == null) return null;
             return baseurl + webdavpath;

+ 0 - 2
src/com/owncloud/android/DisplayUtils.java

@@ -24,8 +24,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Set;
 
-import android.util.Log;
-
 /**
  * A helper class for some string operations.
  * 

+ 91 - 69
src/com/owncloud/android/Uploader.java

@@ -15,6 +15,7 @@
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+
 package com.owncloud.android;
 
 import java.io.File;
@@ -25,13 +26,6 @@ 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;
@@ -48,8 +42,9 @@ 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.provider.MediaStore.Audio;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
 import android.view.View;
 import android.view.Window;
 import android.widget.AdapterView;
@@ -59,8 +54,13 @@ import android.widget.EditText;
 import android.widget.SimpleAdapter;
 import android.widget.Toast;
 
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileUploader;
+
 import com.owncloud.android.R;
-import eu.alefzero.webdav.WebdavClient;
 
 /**
  * This can be used to upload things to an ownCloud instance.
@@ -77,7 +77,6 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
     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;
 
@@ -85,7 +84,6 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
     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;
 
@@ -95,8 +93,6 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
         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);
@@ -140,8 +136,8 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
                         // 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 });
+                        Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
+                        intent.putExtra("authorities", new String[] { AccountAuthenticator.AUTHORITY });
                         startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
                     } else {
                         // since in API7 there is no direct call for
@@ -161,28 +157,6 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
                 }
             });
             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) {
@@ -283,9 +257,6 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
             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");
         }
@@ -357,45 +328,96 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
 
     public void uploadFiles() {
         try {
-            WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
+            //WebdavClient webdav = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
 
+            ArrayList<String> local = new ArrayList<String>();
+            ArrayList<String> remote = new ArrayList<String>();
+            
+            /* TODO - mCreateDir can never be true at this moment; we will replace wdc.createDirectory by CreateFolderOperation when that is fixed 
+            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();
+            */
+            
+            // this checks the mimeType 
+            for (Parcelable mStream : mStreamsToUpload) {
+                
+                Uri uri = (Uri) mStream;
+                if (uri !=null) {
+                    if (uri.getScheme().equals("content")) {
+                        
+                       String mimeType = getContentResolver().getType(uri);
+                       
+                       if (mimeType.contains("image")) {
+                           String[] CONTENT_PROJECTION = { Images.Media.DATA, Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE, Images.Media.SIZE};
+                           Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
+                           c.moveToFirst();
+                           int index = c.getColumnIndex(Images.Media.DATA);
+                           String data = c.getString(index);
+                           local.add(data);
+                           remote.add(mUploadPath + c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME)));
+                       
+                       }
+                       else if (mimeType.contains("video")) {
+                           String[] CONTENT_PROJECTION = { Video.Media.DATA, Video.Media.DISPLAY_NAME, Video.Media.MIME_TYPE, Video.Media.SIZE, Video.Media.DATE_MODIFIED };
+                           Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
+                           c.moveToFirst();
+                           int index = c.getColumnIndex(Video.Media.DATA);
+                           String data = c.getString(index);
+                           local.add(data);
+                           remote.add(mUploadPath + c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME)));
+                          
+                       }
+                       else if (mimeType.contains("audio")) {
+                           String[] CONTENT_PROJECTION = { Audio.Media.DATA, Audio.Media.DISPLAY_NAME, Audio.Media.MIME_TYPE, Audio.Media.SIZE };
+                           Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
+                           c.moveToFirst();
+                           int index = c.getColumnIndex(Audio.Media.DATA);
+                           String data = c.getString(index);
+                           local.add(data);
+                           remote.add(mUploadPath + c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME)));
+                        
+                       }
+                       else {
+                           String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "");
+                           // cut everything whats before mnt. It occured to me that sometimes apps send their name into the URI
+                           if (filePath.contains("mnt")) {
+                              String splitedFilePath[] = filePath.split("/mnt");
+                              filePath = splitedFilePath[1];
+                           }
+                           final File file = new File(filePath);
+                           local.add(file.getAbsolutePath());
+                           remote.add(mUploadPath + file.getName());
+                       }
+                        
+                    } else if (uri.getScheme().equals("file")) {
+                        String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "");
+                        if (filePath.contains("mnt")) {
+                           String splitedFilePath[] = filePath.split("/mnt");
+                           filePath = splitedFilePath[1];
+                        }
+                        final File file = new File(filePath);
+                        local.add(file.getAbsolutePath());
+                        remote.add(mUploadPath + file.getName());
+                    }
+                    else {
+                        throw new SecurityException();
+                    }
                 }
-
-            }
+                else {
+                    throw new SecurityException();
+                }
+           
             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_LOCAL_FILE, local.toArray(new String[local.size()]));
+            intent.putExtra(FileUploader.KEY_REMOTE_FILE, remote.toArray(new String[remote.size()]));
             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));

+ 144 - 111
src/com/owncloud/android/authenticator/AccountAuthenticator.java → src/com/owncloud/android/authentication/AccountAuthenticator.java

@@ -16,33 +16,46 @@
  *
  */
 
-package com.owncloud.android.authenticator;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.ui.activity.AuthenticatorActivity;
+package com.owncloud.android.authentication;
 
 import android.accounts.*;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.util.Log;
+import com.owncloud.android.Log_OC;
 
+/**
+ *  Authenticator for ownCloud accounts.
+ * 
+ *  Controller class accessed from the system AccountManager, providing integration of ownCloud accounts with the Android system.
+ * 
+ *  TODO - better separation in operations for OAuth-capable and regular ownCloud accounts.
+ *  TODO - review completeness 
+ * 
+ * @author David A. Velasco
+ */
 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 AUTHORITY = "org.owncloud";
     public static final String AUTH_TOKEN_TYPE = "org.owncloud";
+    public static final String AUTH_TOKEN_TYPE_PASSWORD = "owncloud.password";
+    public static final String AUTH_TOKEN_TYPE_ACCESS_TOKEN = "owncloud.oauth2.access_token";
+    public static final String AUTH_TOKEN_TYPE_REFRESH_TOKEN = "owncloud.oauth2.refresh_token";
 
     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.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
      * {@link com.owncloud.android.utils.OwnCloudVersion}
      * 
      * @deprecated
@@ -58,8 +71,13 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
      * http://server/path or https://owncloud.server
      */
     public static final String KEY_OC_BASE_URL = "oc_base_url";
-
-    private static final String TAG = "AccountAuthenticator";
+    /**
+     * Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
+     */
+    public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
+    
+    private static final String TAG = AccountAuthenticator.class.getSimpleName();
+    
     private Context mContext;
 
     public AccountAuthenticator(Context context) {
@@ -86,55 +104,60 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
             return e.getFailureBundle();
         }
         final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
+        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);
+        intent.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_CREATE);
 
         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;
+    }
+
     /**
      * {@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 {
+        /// validate parameters
         try {
             validateAccountType(account.type);
             validateAuthTokenType(authTokenType);
@@ -144,22 +167,31 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
             e.printStackTrace();
             return e.getFailureBundle();
         }
+        
+        /// check if required token is stored
         final AccountManager am = AccountManager.get(mContext);
-        final String password = am.getPassword(account);
-        if (password != null) {
+        String accessToken;
+        if (authTokenType.equals(AUTH_TOKEN_TYPE_PASSWORD)) {
+            accessToken = am.getPassword(account);
+        } else {
+            accessToken = am.peekAuthToken(account, authTokenType);
+        }
+        if (accessToken != 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);
+            result.putString(AccountManager.KEY_AUTHTOKEN, accessToken);
             return result;
         }
-
+        
+        /// if not stored, return Intent to access the AuthenticatorActivity and UPDATE the token for the account
         final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
-        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
-                response);
+        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);
+        intent.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, account);
+        intent.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+        
 
         final Bundle bundle = new Bundle();
         bundle.putParcelable(AccountManager.KEY_INTENT, intent);
@@ -205,8 +237,6 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
 
     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);
     }
@@ -218,65 +248,68 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
         }
     }
 
-    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;
-
-    }
-}
+    private void validateAuthTokenType(String authTokenType)
+            throws UnsupportedAuthTokenTypeException {
+        if (!authTokenType.equals(AUTH_TOKEN_TYPE) &&
+            !authTokenType.equals(AUTH_TOKEN_TYPE_PASSWORD) &&
+            !authTokenType.equals(AUTH_TOKEN_TYPE_ACCESS_TOKEN) &&
+            !authTokenType.equals(AUTH_TOKEN_TYPE_REFRESH_TOKEN) ) {
+            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;
+
+    }
+}

+ 1 - 1
src/com/owncloud/android/authenticator/AccountAuthenticatorService.java → src/com/owncloud/android/authentication/AccountAuthenticatorService.java

@@ -16,7 +16,7 @@
  *
  */
 
-package com.owncloud.android.authenticator;
+package com.owncloud.android.authentication;
 
 import android.app.Service;
 import android.content.Intent;

+ 1085 - 0
src/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -0,0 +1,1085 @@
+/* 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 version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.authentication;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.ui.dialog.SslValidatorDialog;
+import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
+import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.OwnCloudServerCheckOperation;
+import com.owncloud.android.operations.ExistenceCheckOperation;
+import com.owncloud.android.operations.OAuth2GetAccessToken;
+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 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.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.Window;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+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
+ * @author David A. Velasco
+ */
+public class AuthenticatorActivity extends AccountAuthenticatorActivity
+        implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeListener {
+
+    private static final String TAG = AuthenticatorActivity.class.getSimpleName();
+
+    public static final String EXTRA_ACCOUNT = "ACCOUNT";
+    public static final String EXTRA_USER_NAME = "USER_NAME";
+    public static final String EXTRA_HOST_NAME = "HOST_NAME";
+    public static final String EXTRA_ACTION = "ACTION";
+    
+    private static final String KEY_HOST_URL_TEXT = "HOST_URL_TEXT";
+    private static final String KEY_OC_VERSION = "OC_VERSION";
+    private static final String KEY_ACCOUNT = "ACCOUNT";
+    private static final String KEY_STATUS_TEXT = "STATUS_TEXT";
+    private static final String KEY_STATUS_ICON = "STATUS_ICON";
+    private static final String KEY_STATUS_CORRECT = "STATUS_CORRECT";
+    private static final String KEY_IS_SSL_CONN = "IS_SSL_CONN";
+    private static final String KEY_OAUTH2_STATUS_TEXT = "OAUTH2_STATUS_TEXT";
+    private static final String KEY_OAUTH2_STATUS_ICON = "OAUTH2_STATUS_ICON";
+    
+    private static final String OAUTH_MODE_ON = "on";
+    private static final String OAUTH_MODE_OFF = "off";
+    private static final String OAUTH_MODE_OPTIONAL = "optional";
+
+    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 int DIALOG_OAUTH2_LOGIN_PROGRESS = 3;
+
+    public static final byte ACTION_CREATE = 0;
+    public static final byte ACTION_UPDATE_TOKEN = 1;
+
+    
+    private String mHostBaseUrl;
+    private OwnCloudVersion mDiscoveredVersion;
+    
+    private int mStatusText, mStatusIcon;
+    private boolean mStatusCorrect, mIsSslConn;
+    private int mOAuth2StatusText, mOAuth2StatusIcon;    
+    
+    private final Handler mHandler = new Handler();
+    private Thread mOperationThread;
+    private OwnCloudServerCheckOperation mOcServerChkOperation;
+    private ExistenceCheckOperation mAuthCheckOperation;
+    private RemoteOperationResult mLastSslUntrustedServerResult;
+
+    private Uri mNewCapturedUriFromOAuth2Redirection;
+    
+    private AccountManager mAccountMgr;
+    private boolean mJustCreated;
+    private byte mAction;
+    private Account mAccount;
+    
+    private ImageView mRefreshButton;
+    private ImageView mViewPasswordButton;
+    private EditText mHostUrlInput;
+    private EditText mUsernameInput;
+    private EditText mPasswordInput;
+    private CheckBox mOAuth2Check;
+    private String mOAuthAccessToken;
+    private View mOkButton;
+    private TextView mAuthStatusLayout;
+    
+    private TextView mOAuthAuthEndpointText;
+    private TextView mOAuthTokenEndpointText;
+    
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * IMPORTANT ENTRY POINT 1: activity is shown to the user
+     */
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+        
+        /// set view and get references to view elements
+        setContentView(R.layout.account_setup);
+        mRefreshButton = (ImageView) findViewById(R.id.refreshButton);
+        mViewPasswordButton = (ImageView) findViewById(R.id.viewPasswordButton);
+        mHostUrlInput = (EditText) findViewById(R.id.hostUrlInput);
+        mUsernameInput = (EditText) findViewById(R.id.account_username);
+        mPasswordInput = (EditText) findViewById(R.id.account_password);
+        mOAuthAuthEndpointText = (TextView)findViewById(R.id.oAuthEntryPoint_1);
+        mOAuthTokenEndpointText = (TextView)findViewById(R.id.oAuthEntryPoint_2);
+        mOAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);
+        mOkButton = findViewById(R.id.buttonOK);
+        mAuthStatusLayout = (TextView) findViewById(R.id.auth_status_text); 
+        
+        /// complete label for 'register account' button
+        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)));
+        }
+
+        /// bind view elements to listeners
+        mHostUrlInput.setOnFocusChangeListener(this);
+        mPasswordInput.setOnFocusChangeListener(this);
+        
+        /// initialization
+        mAccountMgr = AccountManager.get(this);
+        mNewCapturedUriFromOAuth2Redirection = null;
+        mAction = getIntent().getByteExtra(EXTRA_ACTION, ACTION_CREATE); 
+        mAccount = null;
+
+        if (savedInstanceState == null) {
+            /// connection state and info
+            mStatusText = mStatusIcon = 0;
+            mStatusCorrect = false;
+            mIsSslConn = false;
+            
+            /// retrieve extras from intent
+            String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);
+            boolean oAuthRequired = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType) || OAUTH_MODE_ON.equals(getString(R.string.oauth2_mode));
+            
+            mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);
+            if (mAccount != null) {
+                String ocVersion = mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION);
+                if (ocVersion != null) {
+                    mDiscoveredVersion = new OwnCloudVersion(ocVersion);
+                }
+                mHostBaseUrl = mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL);
+                mHostUrlInput.setText(mHostBaseUrl);
+                String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));
+                mUsernameInput.setText(userName);
+                oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);
+            }
+            mOAuth2Check.setChecked(oAuthRequired);
+            changeViewByOAuth2Check(oAuthRequired);
+            
+
+        } else {
+            loadSavedInstanceState(savedInstanceState);
+        }
+        
+        if (!OAUTH_MODE_OPTIONAL.equals(getString(R.string.oauth2_mode))) {
+            mOAuth2Check.setVisibility(View.GONE);
+        }
+        
+        if (mAction == ACTION_UPDATE_TOKEN) {
+            /// lock things that should not change
+            mHostUrlInput.setEnabled(false);
+            mUsernameInput.setEnabled(false);
+            mOAuth2Check.setVisibility(View.GONE);
+            checkOcServer(); 
+        }
+        
+        mPasswordInput.setText("");     // clean password to avoid social hacking (disadvantage: password in removed if the device is turned aside)
+        mJustCreated = true;
+    }
+
+
+    /**
+     * Saves relevant state before {@link #onPause()}
+     * 
+     * Do NOT save {@link #mNewCapturedUriFromOAuth2Redirection}; it keeps a temporal flag, intended to defer the 
+     * processing of the redirection caught in {@link #onNewIntent(Intent)} until {@link #onResume()} 
+     * 
+     * See {@link #loadSavedInstanceState(Bundle)}
+     */
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        
+        /// connection state and info
+        outState.putInt(KEY_STATUS_TEXT, mStatusText);
+        outState.putInt(KEY_STATUS_ICON, mStatusIcon);
+        outState.putBoolean(KEY_STATUS_CORRECT, mStatusCorrect);
+        outState.putBoolean(KEY_IS_SSL_CONN, mIsSslConn);
+
+        /// server data
+        if (mDiscoveredVersion != null) 
+            outState.putString(KEY_OC_VERSION, mDiscoveredVersion.toString());
+        outState.putString(KEY_HOST_URL_TEXT, mHostBaseUrl);
+        
+        /// account data, if updating
+        if (mAccount != null)
+            outState.putParcelable(KEY_ACCOUNT, mAccount);
+        
+        // Saving the state of oAuth2 components.
+        outState.putInt(KEY_OAUTH2_STATUS_ICON, mOAuth2StatusIcon);
+        outState.putInt(KEY_OAUTH2_STATUS_TEXT, mOAuth2StatusText);
+        
+    }
+
+
+    /**
+     * Loads saved state
+     * 
+     * See {@link #onSaveInstanceState(Bundle)}.
+     * 
+     * @param savedInstanceState    Saved state, as received in {@link #onCreate(Bundle)}.
+     */
+    private void loadSavedInstanceState(Bundle savedInstanceState) {
+        /// connection state and info
+        mStatusCorrect = savedInstanceState.getBoolean(KEY_STATUS_CORRECT);
+        mIsSslConn = savedInstanceState.getBoolean(KEY_IS_SSL_CONN);
+        mStatusText = savedInstanceState.getInt(KEY_STATUS_TEXT);
+        mStatusIcon = savedInstanceState.getInt(KEY_STATUS_ICON);
+        updateConnStatus();
+        
+        /// UI settings depending upon connection
+        mOkButton.setEnabled(mStatusCorrect);   // TODO really necessary?
+        if (!mStatusCorrect)
+            mRefreshButton.setVisibility(View.VISIBLE); // seems that setting visibility is necessary
+        else
+            mRefreshButton.setVisibility(View.INVISIBLE);
+        
+        /// server data
+        String ocVersion = savedInstanceState.getString(KEY_OC_VERSION);
+        if (ocVersion != null)
+            mDiscoveredVersion = new OwnCloudVersion(ocVersion);
+        mHostBaseUrl = savedInstanceState.getString(KEY_HOST_URL_TEXT);
+        
+        // account data, if updating
+        mAccount = savedInstanceState.getParcelable(KEY_ACCOUNT);
+        
+        // state of oAuth2 components
+        mOAuth2StatusIcon = savedInstanceState.getInt(KEY_OAUTH2_STATUS_ICON);
+        mOAuth2StatusText = savedInstanceState.getInt(KEY_OAUTH2_STATUS_TEXT);
+        // END of getting the state of oAuth2 components.
+    }
+
+    
+    /**
+     * The redirection triggered by the OAuth authentication server as response to the GET AUTHORIZATION request
+     * is caught here.
+     * 
+     * To make this possible, this activity needs to be qualified with android:launchMode = "singleTask" in the
+     * AndroidManifest.xml file.
+     */
+    @Override
+    protected void onNewIntent (Intent intent) {
+        Log_OC.d(TAG, "onNewIntent()");
+        Uri data = intent.getData();
+        if (data != null && data.toString().startsWith(getString(R.string.oauth2_redirect_uri))) {
+            mNewCapturedUriFromOAuth2Redirection = data;
+        }
+    }
+
+    
+    /**
+     * The redirection triggered by the OAuth authentication server as response to the GET AUTHORIZATION, and 
+     * deferred in {@link #onNewIntent(Intent)}, is processed here.
+     */
+    @Override
+    protected void onResume() {
+        super.onResume();
+        // the state of mOAuth2Check is automatically recovered between configuration changes, but not before onCreate() finishes; so keep the next lines here
+        changeViewByOAuth2Check(mOAuth2Check.isChecked());  
+        if (mAction == ACTION_UPDATE_TOKEN && mJustCreated) {
+            if (mOAuth2Check.isChecked())
+                Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show();
+            else
+                Toast.makeText(this, R.string.auth_expired_basic_auth_toast, Toast.LENGTH_LONG).show();
+        }
+        
+        if (mNewCapturedUriFromOAuth2Redirection != null) {
+            getOAuth2AccessTokenFromCapturedRedirection();            
+        }
+        
+        mJustCreated = false;
+    }
+    
+    
+    /**
+     * Parses the redirection with the response to the GET AUTHORIZATION request to the 
+     * oAuth server and requests for the access token (GET ACCESS TOKEN)
+     */
+    private void getOAuth2AccessTokenFromCapturedRedirection() {
+        /// Parse data from OAuth redirection
+        String queryParameters = mNewCapturedUriFromOAuth2Redirection.getQuery();
+        mNewCapturedUriFromOAuth2Redirection = null;
+        
+        /// Showing the dialog with instructions for the user.
+        showDialog(DIALOG_OAUTH2_LOGIN_PROGRESS);
+
+        /// GET ACCESS TOKEN to the oAuth server 
+        RemoteOperation operation = new OAuth2GetAccessToken(   getString(R.string.oauth2_client_id), 
+                                                                getString(R.string.oauth2_redirect_uri), // TODO check - necessary here?      
+                                                                getString(R.string.oauth2_grant_type),
+                                                                queryParameters);
+        //WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());
+        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext());
+        operation.execute(client, this, mHandler);
+    }
+    
+
+    
+    /**
+     * Handles the change of focus on the text inputs for the server URL and the password
+     */
+    public void onFocusChange(View view, boolean hasFocus) {
+        if (view.getId() == R.id.hostUrlInput) {
+            onUrlInputFocusChanged((TextView) view, hasFocus);
+            
+        } else if (view.getId() == R.id.account_password) {
+            onPasswordFocusChanged((TextView) view, hasFocus);
+        }
+    }
+    
+
+    /**
+     * Handles changes in focus on the text input for the server URL.
+     * 
+     * IMPORTANT ENTRY POINT 2: When (!hasFocus), user wrote the server URL and changed to 
+     * other field. The operation to check the existence of the server in the entered URL is
+     * started. 
+     * 
+     * When hasFocus:    user 'comes back' to write again the server URL.
+     * 
+     * @param hostInput     TextView with the URL input field receiving the change of focus.
+     * @param hasFocus      'True' if focus is received, 'false' if is lost
+     */
+    private void onUrlInputFocusChanged(TextView hostInput, boolean hasFocus) {
+        if (!hasFocus) {
+            checkOcServer();
+            
+        } else {
+            // avoids that the 'connect' button can be clicked if the test was previously passed
+            mOkButton.setEnabled(false); 
+        }
+    }
+
+
+    private void checkOcServer() {
+        String uri = mHostUrlInput.getText().toString().trim();
+        if (uri.length() != 0) {
+            mStatusText = R.string.auth_testing_connection;
+            mStatusIcon = R.drawable.progress_small;
+            updateConnStatus();
+            /** TODO cancel previous connection check if the user tries to ammend a wrong URL  
+            if(mConnChkOperation != null) {
+                mConnChkOperation.cancel();
+            } */
+            mOcServerChkOperation = new  OwnCloudServerCheckOperation(uri, this);
+            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);
+            mHostBaseUrl = "";
+            mDiscoveredVersion = null;
+            mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);
+        } else {
+            mRefreshButton.setVisibility(View.INVISIBLE);
+            mStatusText = 0;
+            mStatusIcon = 0;
+            updateConnStatus();
+        }
+    }
+
+
+    /**
+     * Handles changes in focus on the text input for the password (basic authorization).
+     * 
+     * When (hasFocus), the button to toggle password visibility is shown.
+     * 
+     * When (!hasFocus), the button is made invisible and the password is hidden.
+     * 
+     * @param passwordInput    TextView with the password input field receiving the change of focus.
+     * @param hasFocus          'True' if focus is received, 'false' if is lost
+     */
+    private void onPasswordFocusChanged(TextView passwordInput, boolean hasFocus) {
+        if (hasFocus) {
+            mViewPasswordButton.setVisibility(View.VISIBLE);
+        } else {
+            int input_type = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+            passwordInput.setInputType(input_type);
+            mViewPasswordButton.setVisibility(View.INVISIBLE);
+        }
+    }
+
+
+    
+    /**
+     * Cancels the authenticator activity
+     * 
+     * IMPORTANT ENTRY POINT 3: Never underestimate the importance of cancellation
+     * 
+     * This method is bound in the layout/acceoun_setup.xml resource file.
+     * 
+     * @param view      Cancel button
+     */
+    public void onCancelClick(View view) {
+        setResult(RESULT_CANCELED);     // TODO review how is this related to AccountAuthenticator (debugging)
+        finish();
+    }
+    
+    
+    
+    /**
+     * Checks the credentials of the user in the root of the ownCloud server
+     * before creating a new local account.
+     * 
+     * For basic authorization, a check of existence of the root folder is
+     * performed.
+     * 
+     * For OAuth, starts the flow to get an access token; the credentials test 
+     * is postponed until it is available.
+     * 
+     * IMPORTANT ENTRY POINT 4
+     * 
+     * @param view      OK button
+     */
+    public void onOkClick(View view) {
+        // this check should be unnecessary
+        if (mDiscoveredVersion == null || !mDiscoveredVersion.isVersionValid()  || mHostBaseUrl == null || mHostBaseUrl.length() == 0) {
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_wtf_reenter_URL;
+            updateConnStatus();
+            mOkButton.setEnabled(false);
+            Log_OC.wtf(TAG,  "The user was allowed to click 'connect' to an unchecked server!!");
+            return;
+        }
+        
+        if (mOAuth2Check.isChecked()) {
+            startOauthorization();
+            
+        } else {
+            checkBasicAuthorization();
+        }
+    }
+    
+    
+    /**
+     * Tests the credentials entered by the user performing a check of existence on 
+     * the root folder of the ownCloud server.
+     */
+    private void checkBasicAuthorization() {
+        /// get the path to the root folder through WebDAV from the version server
+        String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, false);
+        
+        /// get basic credentials entered by user
+        String username = mUsernameInput.getText().toString();
+        String password = mPasswordInput.getText().toString();
+        
+        /// be gentle with the user
+        showDialog(DIALOG_LOGIN_PROGRESS);
+        
+        /// test credentials accessing the root folder
+        mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);
+        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this);
+        client.setBasicCredentials(username, password);
+        mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);
+    }
+
+
+    /**
+     * Starts the OAuth 'grant type' flow to get an access token, with 
+     * a GET AUTHORIZATION request to the BUILT-IN authorization server. 
+     */
+    private void startOauthorization() {
+        // be gentle with the user
+        mStatusIcon = R.drawable.progress_small;
+        mStatusText = R.string.oauth_login_connection;
+        updateAuthStatus();
+        
+        // GET AUTHORIZATION request
+        //Uri uri = Uri.parse(getString(R.string.oauth2_url_endpoint_auth));
+        Uri uri = Uri.parse(mOAuthAuthEndpointText.getText().toString().trim());
+        Uri.Builder uriBuilder = uri.buildUpon();
+        uriBuilder.appendQueryParameter(OAuth2Constants.KEY_RESPONSE_TYPE, getString(R.string.oauth2_response_type));
+        uriBuilder.appendQueryParameter(OAuth2Constants.KEY_REDIRECT_URI, getString(R.string.oauth2_redirect_uri));   
+        uriBuilder.appendQueryParameter(OAuth2Constants.KEY_CLIENT_ID, getString(R.string.oauth2_client_id));
+        uriBuilder.appendQueryParameter(OAuth2Constants.KEY_SCOPE, getString(R.string.oauth2_scope));
+        //uriBuilder.appendQueryParameter(OAuth2Constants.KEY_STATE, whateverwewant);
+        uri = uriBuilder.build();
+        Log_OC.d(TAG, "Starting browser to view " + uri.toString());
+        Intent i = new Intent(Intent.ACTION_VIEW, uri);
+        startActivity(i);
+    }
+
+    
+    /**
+     * Callback method invoked when a RemoteOperation executed by this Activity finishes.
+     * 
+     * Dispatches the operation flow to the right method.
+     */
+    @Override
+    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+
+        if (operation instanceof OwnCloudServerCheckOperation) {
+            onOcServerCheckFinish((OwnCloudServerCheckOperation) operation, result);
+            
+        } else if (operation instanceof OAuth2GetAccessToken) {
+            onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);
+                
+        } else if (operation instanceof ExistenceCheckOperation)  {
+            onAuthorizationCheckFinish((ExistenceCheckOperation)operation, result);
+                
+        }
+    }
+    
+
+    /**
+     * Processes the result of the server check performed when the user finishes the enter of the
+     * server URL.
+     * 
+     * @param operation     Server check performed.
+     * @param result        Result of the check.
+     */
+    private void onOcServerCheckFinish(OwnCloudServerCheckOperation operation, RemoteOperationResult result) {
+        /// update status icon and text
+        updateStatusIconAndText(result);
+        updateConnStatus();
+
+        /// save result state
+        mStatusCorrect = result.isSuccess();
+        mIsSslConn = (result.getCode() == ResultCode.OK_SSL);
+        
+        /// very special case (TODO: move to a common place for all the remote operations)
+        if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
+            mLastSslUntrustedServerResult = result;
+            showDialog(DIALOG_SSL_VALIDATOR); 
+        }
+        
+        /// update the visibility of the 'retry connection' button
+        if (!mStatusCorrect)
+            mRefreshButton.setVisibility(View.VISIBLE);
+        else
+            mRefreshButton.setVisibility(View.INVISIBLE);
+        
+        /// retrieve discovered version and normalize server URL
+        mDiscoveredVersion = operation.getDiscoveredVersion();
+        mHostBaseUrl = mHostUrlInput.getText().toString().trim();
+        if (!mHostBaseUrl.toLowerCase().startsWith("http://") &&
+            !mHostBaseUrl.toLowerCase().startsWith("https://")) {
+            
+            if (mIsSslConn) {
+                mHostBaseUrl = "https://" + mHostBaseUrl;
+            } else {
+                mHostBaseUrl = "http://" + mHostBaseUrl;
+            }
+            
+        }
+        if (mHostBaseUrl.endsWith("/"))
+            mHostBaseUrl = mHostBaseUrl.substring(0, mHostBaseUrl.length() - 1);
+        
+        /// allow or not the user try to access the server
+        mOkButton.setEnabled(mStatusCorrect);
+    }
+
+
+    /**
+     * Chooses the right icon and text to show to the user for the received operation result.
+     * 
+     * @param result    Result of a remote operation performed in this activity
+     */
+    private void updateStatusIconAndText(RemoteOperationResult result) {
+        mStatusText = mStatusIcon = 0;
+
+        switch (result.getCode()) {
+        case OK_SSL:
+            mStatusIcon = android.R.drawable.ic_secure;
+            mStatusText = R.string.auth_secure_connection;
+            break;
+            
+        case OK_NO_SSL:
+        case OK:
+            if (mHostUrlInput.getText().toString().trim().toLowerCase().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 SSL_RECOVERABLE_PEER_UNVERIFIED:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_ssl_unverified_server_title;
+            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_ERROR:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_ssl_general_error_title;
+            break;
+            
+        case UNAUTHORIZED:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_unauthorized;
+            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 OAUTH2_ERROR:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_oauth_error;
+            break;
+        case OAUTH2_ERROR_ACCESS_DENIED:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_oauth_error_access_denied;
+            break;
+        case UNHANDLED_HTTP_CODE:
+        case UNKNOWN_ERROR:
+            mStatusIcon = R.drawable.common_error;
+            mStatusText = R.string.auth_unknown_error_title;
+            break;
+            
+        default:
+            break;
+        }
+    }
+
+
+    /**
+     * Processes the result of the request for and access token send 
+     * to an OAuth authorization server.
+     * 
+     * @param operation     Operation performed requesting the access token.
+     * @param result        Result of the operation.
+     */
+    private void onGetOAuthAccessTokenFinish(OAuth2GetAccessToken operation, RemoteOperationResult result) {
+        try {
+            dismissDialog(DIALOG_OAUTH2_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
+        }
+
+        String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, true);
+        if (result.isSuccess() && webdav_path != null) {
+            /// be gentle with the user
+            showDialog(DIALOG_LOGIN_PROGRESS);
+            
+            /// time to test the retrieved access token on the ownCloud server
+            mOAuthAccessToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);
+            Log_OC.d(TAG, "Got ACCESS TOKEN: " + mOAuthAccessToken);
+            mAuthCheckOperation = new ExistenceCheckOperation("", this, false);
+            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this);
+            client.setBearerCredentials(mOAuthAccessToken);
+            mAuthCheckOperation.execute(client, this, mHandler);
+            
+        } else {
+            updateStatusIconAndText(result);
+            updateAuthStatus();
+            Log_OC.d(TAG, "Access failed: " + result.getLogMessage());
+        }
+    }
+
+    
+    /**
+     * Processes the result of the access check performed to try the user credentials.
+     * 
+     * Creates a new account through the AccountManager.
+     * 
+     * @param operation     Access check performed.
+     * @param result        Result of the operation.
+     */
+    private void onAuthorizationCheckFinish(ExistenceCheckOperation operation, RemoteOperationResult result) {
+        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
+        }
+        
+        if (result.isSuccess()) {
+            Log_OC.d(TAG, "Successful access - time to save the account");
+
+            if (mAction == ACTION_CREATE) {
+                createAccount();
+                
+            } else {
+                updateToken();
+            }
+            
+            finish();
+            
+        } else {
+            updateStatusIconAndText(result);
+            updateAuthStatus();
+            Log_OC.d(TAG, "Access failed: " + result.getLogMessage());
+        }
+    }
+
+    
+    /**
+     * Sets the proper response to get that the Account Authenticator that started this activity saves 
+     * a new authorization token for mAccount.
+     */
+    private void updateToken() {
+        Bundle response = new Bundle();
+        response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);
+        response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);
+        boolean isOAuth = mOAuth2Check.isChecked();
+        if (isOAuth) {
+            response.putString(AccountManager.KEY_AUTHTOKEN, mOAuthAccessToken);
+            // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention
+            mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);
+        } else {
+            response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString());
+            mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString());
+        }
+        setAccountAuthenticatorResult(response);
+    }
+
+
+    /**
+     * Creates a new account through the Account Authenticator that started this activity. 
+     * 
+     * This makes the account permanent.
+     * 
+     * TODO Decide how to name the OAuth accounts
+     */
+    private void createAccount() {
+        /// create and save new ownCloud account
+        boolean isOAuth = mOAuth2Check.isChecked();
+        
+        Uri uri = Uri.parse(mHostBaseUrl);
+        String username = mUsernameInput.getText().toString().trim();
+        if (isOAuth) {
+            username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong();
+        }            
+        String accountName = username + "@" + uri.getHost();
+        if (uri.getPort() >= 0) {
+            accountName += ":" + uri.getPort();
+        }
+        mAccount = new Account(accountName, AccountAuthenticator.ACCOUNT_TYPE);
+        if (isOAuth) {
+            mAccountMgr.addAccountExplicitly(mAccount, "", null);  // with our implementation, the password is never input in the app
+        } else {
+            mAccountMgr.addAccountExplicitly(mAccount, mPasswordInput.getText().toString(), null);
+        }
+
+        /// add the new account as default in 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();
+        }
+
+        /// prepare result to return to the Authenticator
+        //  TODO check again what the Authenticator makes with it; probably has the same effect as addAccountExplicitly, but it's not well done
+        final Intent intent = new Intent();       
+        intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE,    AccountAuthenticator.ACCOUNT_TYPE);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_NAME,    mAccount.name);
+        if (!isOAuth)
+            intent.putExtra(AccountManager.KEY_AUTHTOKEN,   AccountAuthenticator.ACCOUNT_TYPE); // TODO check this; not sure it's right; maybe
+        intent.putExtra(AccountManager.KEY_USERDATA,        username);
+        if (isOAuth) {
+            mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);
+        }
+        /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA
+        mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION,    mDiscoveredVersion.toString());
+        mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL,   mHostBaseUrl);
+        if (isOAuth)
+            mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE");  // TODO this flag should be unnecessary
+    
+        setAccountAuthenticatorResult(intent.getExtras());
+        setResult(RESULT_OK, intent);
+        
+        /// immediately request for the synchronization of the new account
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+        ContentResolver.requestSync(mAccount, AccountAuthenticator.AUTHORITY, bundle);
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * 
+     * Necessary to update the contents of the SSL Dialog
+     * 
+     * TODO move to some common place for all possible untrusted SSL failures
+     */
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
+        switch (id) {
+        case DIALOG_LOGIN_PROGRESS:
+        case DIALOG_CERT_NOT_SAVED:
+        case DIALOG_OAUTH2_LOGIN_PROGRESS:
+            break;
+        case DIALOG_SSL_VALIDATOR: {
+            ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);
+            break;
+        }
+        default:
+            Log_OC.e(TAG, "Incorrect dialog called with id = " + id);
+        }
+    }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        Dialog dialog = null;
+        switch (id) {
+        case DIALOG_LOGIN_PROGRESS: {
+            /// simple progress dialog
+            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) {
+                            /// TODO study if this is enough
+                            Log_OC.i(TAG, "Login canceled");
+                            if (mOperationThread != null) {
+                                mOperationThread.interrupt();
+                                finish();
+                            }
+                        }
+                    });
+            dialog = working_dialog;
+            break;
+        }
+        case DIALOG_OAUTH2_LOGIN_PROGRESS: {
+            ProgressDialog working_dialog = new ProgressDialog(this);
+            working_dialog.setMessage(String.format("Getting authorization")); 
+            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");
+                    finish();
+                }
+            });
+            dialog = working_dialog;
+            break;
+        }
+        case DIALOG_SSL_VALIDATOR: {
+            /// TODO start to use new dialog interface, at least for this (it is a FragmentDialog already)
+            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;
+    }
+
+    
+    /**
+     * Starts and activity to open the 'new account' page in the ownCloud web site
+     * 
+     * @param view      'Account register' button
+     */
+    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);
+    }
+
+    
+    /**
+     * Updates the content and visibility state of the icon and text associated
+     * to the last check on the ownCloud server.
+     */
+    private void updateConnStatus() {
+        ImageView iv = (ImageView) findViewById(R.id.action_indicator);
+        TextView tv = (TextView) findViewById(R.id.status_text);
+
+        if (mStatusIcon == 0 && mStatusText == 0) {
+            iv.setVisibility(View.INVISIBLE);
+            tv.setVisibility(View.INVISIBLE);
+        } else {
+            iv.setImageResource(mStatusIcon);
+            tv.setText(mStatusText);
+            iv.setVisibility(View.VISIBLE);
+            tv.setVisibility(View.VISIBLE);
+        }
+    }
+    
+    
+    /**
+     * Updates the content and visibility state of the icon and text associated
+     * to the interactions with the OAuth authorization server.
+     */
+    private void updateAuthStatus() {
+        if (mStatusIcon == 0 && mStatusText == 0) {
+            mAuthStatusLayout.setVisibility(View.INVISIBLE);
+        } else {
+            mAuthStatusLayout.setText(mStatusText);
+            mAuthStatusLayout.setCompoundDrawablesWithIntrinsicBounds(mStatusIcon, 0, 0, 0);
+            mAuthStatusLayout.setVisibility(View.VISIBLE);
+        }
+    }     
+
+    
+    /**
+     * Called when the refresh button in the input field for ownCloud host is clicked.
+     * 
+     * Performs a new check on the URL in the input field.
+     * 
+     * @param view      Refresh 'button'
+     */
+    public void onRefreshClick(View view) {
+        onFocusChange(mRefreshButton, false);
+    }
+    
+    
+    /**
+     * Called when the eye icon in the password field is clicked.
+     * 
+     * Toggles the visibility of the password in the field. 
+     * 
+     * @param view      'View password' 'button'
+     */
+    public void onViewPasswordClick(View view) {
+        int selectionStart = mPasswordInput.getSelectionStart();
+        int selectionEnd = mPasswordInput.getSelectionEnd();
+        int input_type = mPasswordInput.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;
+        }
+        mPasswordInput.setInputType(input_type);
+        mPasswordInput.setSelection(selectionStart, selectionEnd);
+    }    
+    
+    
+    /**
+     * Called when the checkbox for OAuth authorization is clicked.
+     * 
+     * Hides or shows the input fields for user & password. 
+     * 
+     * @param view      'View password' 'button'
+     */
+    public void onCheckClick(View view) {
+        CheckBox oAuth2Check = (CheckBox)view;      
+        changeViewByOAuth2Check(oAuth2Check.isChecked());
+
+    }
+    
+    /**
+     * Changes the visibility of input elements depending upon the kind of authorization
+     * chosen by the user: basic or OAuth
+     * 
+     * @param checked       'True' when OAuth is selected.
+     */
+    public void changeViewByOAuth2Check(Boolean checked) {
+        
+        if (checked) {
+            mOAuthAuthEndpointText.setVisibility(View.VISIBLE);
+            mOAuthTokenEndpointText.setVisibility(View.VISIBLE);
+            mUsernameInput.setVisibility(View.GONE);
+            mPasswordInput.setVisibility(View.GONE);
+            mViewPasswordButton.setVisibility(View.GONE);
+        } else {
+            mOAuthAuthEndpointText.setVisibility(View.GONE);
+            mOAuthTokenEndpointText.setVisibility(View.GONE);
+            mUsernameInput.setVisibility(View.VISIBLE);
+            mPasswordInput.setVisibility(View.VISIBLE);
+            mViewPasswordButton.setVisibility(View.INVISIBLE);
+        }     
+
+    }    
+    
+    /**
+     * Called from SslValidatorDialog when a new server certificate was correctly saved.
+     */
+    public void onSavedCertificate() {
+        mOperationThread = mOcServerChkOperation.retry(this, mHandler);                
+    }
+
+    /**
+     * Called from SslValidatorDialog when a new server certificate could not be saved 
+     * when the user requested it.
+     */
+    @Override
+    public void onFailedSavingCertificate() {
+        showDialog(DIALOG_CERT_NOT_SAVED);
+    }
+
+}

+ 53 - 0
src/com/owncloud/android/authentication/OAuth2Constants.java

@@ -0,0 +1,53 @@
+/* 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 version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.authentication;
+
+/** 
+ * Constant values for OAuth 2 protocol.
+ * 
+ * Includes required and optional parameter NAMES used in the 'authorization code' grant type.
+ *  
+ * @author David A. Velasco
+ */
+
+public class OAuth2Constants {
+    
+    /// Parameters to send to the Authorization Endpoint
+    public static final String KEY_RESPONSE_TYPE = "response_type";
+    public static final String KEY_REDIRECT_URI = "redirect_uri";
+    public static final String KEY_CLIENT_ID = "client_id";
+    public static final String KEY_SCOPE = "scope";
+    public static final String KEY_STATE = "state"; 
+    
+    /// Additional parameters to send to the Token Endpoint
+    public static final String KEY_GRANT_TYPE = "grant_type";
+    public static final String KEY_CODE = "code";
+    
+    /// Parameters received in an OK response from the Token Endpoint 
+    public static final String KEY_ACCESS_TOKEN = "access_token";
+    public static final String KEY_TOKEN_TYPE = "token_type";
+    public static final String KEY_EXPIRES_IN = "expires_in";
+    public static final String KEY_REFRESH_TOKEN = "refresh_token";
+    
+    /// Parameters in an ERROR response
+    public static final String KEY_ERROR = "error";
+    public static final String KEY_ERROR_DESCRIPTION = "error_description";
+    public static final String KEY_ERROR_URI = "error_uri";
+    public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
+    
+}

+ 0 - 88
src/com/owncloud/android/authenticator/AuthenticationRunnable.java

@@ -1,88 +0,0 @@
-/* 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 version 2,
- *   as published by the Free Software Foundation.
- *
- *   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 java.net.URL;
-
-import org.apache.commons.httpclient.HttpStatus;
-
-import com.owncloud.android.R;
-import com.owncloud.android.network.OwnCloudClientUtils;
-
-import eu.alefzero.webdav.WebdavClient;
-
-import android.content.Context;
-import android.net.Uri;
-import android.os.Handler;
-
-public class AuthenticationRunnable implements Runnable {
-
-    private OnAuthenticationResultListener mListener;
-    private Handler mHandler;
-    private URL mUrl;
-    private String mUsername;
-    private String mPassword;
-    private Context mContext;
-
-    public AuthenticationRunnable(URL url, String username, String password, Context context) {
-        mListener = null;
-        mUrl = url;
-        mUsername = username;
-        mPassword = password;
-        mContext = context;
-    }
-
-    public void setOnAuthenticationResultListener(
-            OnAuthenticationResultListener listener, Handler handler) {
-        mListener = listener;
-        mHandler = handler;
-    }
-
-    @Override
-    public void run() {
-        Uri uri;
-        uri = Uri.parse(mUrl.toString());
-        WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(uri, mUsername, mPassword, mContext);
-        int login_result = wdc.tryToLogin();
-        switch (login_result) {
-        case HttpStatus.SC_OK:
-            postResult(true, uri.toString());
-            break;
-        case HttpStatus.SC_UNAUTHORIZED:
-            postResult(false, mContext.getString(R.string.auth_unauthorized));
-            break;
-        case HttpStatus.SC_NOT_FOUND:
-            postResult(false, mContext.getString(R.string.auth_not_found));
-            break;
-        default:
-            postResult(false, String.format(mContext.getString(R.string.auth_internal), login_result));
-        }
-    }
-
-    private void postResult(final boolean success, final String message) {
-        if (mHandler != null && mListener != null) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mListener.onAuthenticationResult(success, message);
-                }
-            });
-        }
-    }
-}

+ 0 - 25
src/com/owncloud/android/authenticator/OnAuthenticationResultListener.java

@@ -1,25 +0,0 @@
-/* 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 version 2,
- *   as published by the Free Software Foundation.
- *
- *   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;
-
-public interface OnAuthenticationResultListener {
-
-    public void onAuthenticationResult(boolean success, String message);
-
-}

+ 0 - 29
src/com/owncloud/android/authenticator/OnConnectCheckListener.java

@@ -1,29 +0,0 @@
-/* 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 version 2,
- *   as published by the Free Software Foundation.
- *
- *   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;
-
-public interface OnConnectCheckListener {
-
-    enum ResultType {
-        OK_SSL, OK_NO_SSL, SSL_INIT_ERROR, HOST_NOT_AVAILABLE, TIMEOUT, NO_NETWORK_CONNECTION, INCORRECT_ADDRESS, INSTANCE_NOT_CONFIGURED, FILE_NOT_FOUND, UNKNOWN_ERROR, WRONG_CONNECTION,  SSL_UNVERIFIED_SERVER, BAD_OC_VERSION
-    }
-
-    public void onConnectionCheckResult(ResultType type);
-
-}

+ 0 - 1
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -40,7 +40,6 @@ import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.util.Log;
 
 public class FileDataStorageManager implements DataStorageManager {
 

+ 0 - 1
src/com/owncloud/android/db/DbHandler.java

@@ -24,7 +24,6 @@ import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
-import android.util.Log;
 
 /**
  * Custom database helper for ownCloud

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

@@ -23,7 +23,6 @@ import com.owncloud.android.R;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.app.DialogFragment;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;

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

@@ -35,7 +35,6 @@ import android.R;
 import android.app.ListActivity;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 import android.widget.SimpleAdapter;
 
 public class ExtensionsListActivity extends ListActivity {

+ 0 - 1
src/com/owncloud/android/files/BootupBroadcastReceiver.java

@@ -24,7 +24,6 @@ import com.owncloud.android.files.services.FileObserverService;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Log;
 
 public class BootupBroadcastReceiver extends BroadcastReceiver {
 

+ 5 - 4
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java

@@ -20,6 +20,11 @@ package com.owncloud.android.files;
 
 import java.io.File;
 
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.db.DbHandler;
+import com.owncloud.android.files.services.FileUploader;
+
 import android.accounts.Account;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -32,11 +37,7 @@ import android.preference.PreferenceManager;
 import android.provider.MediaStore.Images.Media;
 import android.webkit.MimeTypeMap;
 
-import com.owncloud.android.AccountUtils;
 import com.owncloud.android.Log_OC;
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.db.DbHandler;
-import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.utils.FileStorageUtils;
 
 public class InstantUploadBroadcastReceiver extends BroadcastReceiver {

+ 1 - 5
src/com/owncloud/android/files/OwnCloudFileObserver.java

@@ -23,19 +23,16 @@ import java.io.File;
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.network.OwnCloudClientUtils;
 import com.owncloud.android.operations.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
 
-import eu.alefzero.webdav.WebdavClient;
 
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 import android.os.FileObserver;
-import android.util.Log;
 
 public class OwnCloudFileObserver extends FileObserver {
 
@@ -78,7 +75,6 @@ public class OwnCloudFileObserver extends FileObserver {
                          mPath);
             return;
         }
-        WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mOCAccount, mContext);
         FileDataStorageManager storageManager = new FileDataStorageManager(mOCAccount, mContext.getContentResolver());
         OCFile file = storageManager.getFileByLocalPath(mPath);     // a fresh object is needed; many things could have occurred to the file since it was registered to observe
                                                                     // again, assuming that local files are linked to a remote file AT MOST, SOMETHING TO BE DONE; 
@@ -89,7 +85,7 @@ public class OwnCloudFileObserver extends FileObserver {
                                                                     true, 
                                                                     true, 
                                                                     mContext);
-        RemoteOperationResult result = sfo.execute(wc);
+        RemoteOperationResult result = sfo.execute(mOCAccount, mContext);
         if (result.getCode() == ResultCode.SYNC_CONFLICT) {
             // ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred
             Intent i = new Intent(mContext, ConflictsResolveActivity.class);

+ 51 - 25
src/com/owncloud/android/files/services/FileDownloader.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.files.services;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -27,6 +28,7 @@ import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import eu.alefzero.webdav.OnDatatransferProgressListener;
@@ -34,12 +36,14 @@ 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.operations.RemoteOperationResult.ResultCode;
 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.accounts.AccountsException;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -113,7 +117,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         mBinder = new FileDownloaderBinder();
     }
 
-    
     /**
      * Entry point to add one or several files to the queue of downloads.
      * 
@@ -256,7 +259,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         }
         
         
-        
         /**
          * Removes a listener interested in the progress of the download for a concrete file.
          * 
@@ -321,7 +323,6 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         }
     }
     
-    
 
     /**
      * Core download method: requests a file to download and stores it.
@@ -338,21 +339,28 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             
             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 {
+                /// 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
                 downloadResult = mCurrentDownload.execute(mDownloadClient);
                 if (downloadResult.isSuccess()) {
                     saveDownloadedFile();
                 }
             
+            } catch (AccountsException e) {
+                Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
+                downloadResult = new RemoteOperationResult(e);
+            } catch (IOException e) {
+                Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
+                downloadResult = new RemoteOperationResult(e);
+                
             } finally {
                 synchronized(mPendingDownloads) {
                     mPendingDownloads.remove(downloadKey);
@@ -455,23 +463,41 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
             Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
-            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);
+            boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED);
+            if (needsToUpdateCredentials) {
+                // let the user update credentials with one click
+                Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
+                updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, download.getAccount());
+                updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+                updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
+                finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
+                finalNotification.setLatestEventInfo(   getApplicationContext(), 
+                                                        getString(tickerId), 
+                                                        String.format(getString(contentId), new File(download.getSavePath()).getName()),
+                                                        finalNotification.contentIntent);
+                mDownloadClient = null;   // grant that future retries on the same account will get the fresh credentials
                 
             } else {
-                // TODO put something smart in showDetailsIntent
-                showDetailsIntent = new Intent();
+                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);
             }
-            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);
         }
     }

+ 0 - 1
src/com/owncloud/android/files/services/FileObserverService.java

@@ -40,7 +40,6 @@ import android.content.IntentFilter;
 import android.database.Cursor;
 import android.os.Binder;
 import android.os.IBinder;
-import android.util.Log;
 
 public class FileObserverService extends Service {
 

+ 0 - 55
src/com/owncloud/android/files/services/FileOperation.java

@@ -1,55 +0,0 @@
-/* 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 version 2,
- *   as published by the Free Software Foundation.
- *
- *   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 com.owncloud.android.AccountUtils;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.network.OwnCloudClientUtils;
-
-import android.accounts.Account;
-import android.content.Context;
-import eu.alefzero.webdav.WebdavClient;
-
-public class FileOperation {
-
-    Context mContext;
-    
-    public FileOperation(Context contex){
-        this.mContext = contex;
-    }
-    
-    /**
-     * Deletes a file from ownCloud - locally and remote.
-     * @param file The file to delete
-     * @return True on success, otherwise false
-     */
-    public boolean delete(OCFile file){
-        
-        Account account = AccountUtils.getCurrentOwnCloudAccount(mContext);
-        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(account, mContext);
-        if(client.deleteFile(file.getRemotePath())){
-            File localFile = new File(file.getStoragePath());
-            return localFile.delete();
-        }
-        
-        return false;
-    }
-    
-}

+ 67 - 35
src/com/owncloud/android/files/services/FileUploader.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.files.services;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -31,8 +32,29 @@ import org.apache.http.HttpStatus;
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.authentication.AuthenticatorActivity;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.operations.ChunkedUploadFileOperation;
+import com.owncloud.android.operations.CreateFolderOperation;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.operations.UploadFileOperation;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.ui.activity.FileDetailActivity;
+import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.utils.OwnCloudVersion;
+
+import eu.alefzero.webdav.OnDatatransferProgressListener;
+import eu.alefzero.webdav.WebdavEntry;
+import eu.alefzero.webdav.WebdavUtils;
+
+import com.owncloud.android.network.OwnCloudClientUtils;
+
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.accounts.AccountsException;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -47,32 +69,17 @@ import android.os.Message;
 import android.os.Process;
 import android.webkit.MimeTypeMap;
 import android.widget.RemoteViews;
-import android.widget.Toast;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import com.owncloud.android.authenticator.AccountAuthenticator;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.db.DbHandler;
-import com.owncloud.android.network.OwnCloudClientUtils;
-import com.owncloud.android.operations.ChunkedUploadFileOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.ui.activity.FailedUploadActivity;
-import com.owncloud.android.ui.activity.FileDetailActivity;
 import com.owncloud.android.ui.activity.InstantUploadActivity;
-import com.owncloud.android.ui.fragment.FileDetailFragment;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.OwnCloudVersion;
 
-import eu.alefzero.webdav.OnDatatransferProgressListener;
 import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavEntry;
-import eu.alefzero.webdav.WebdavUtils;
 
 public class FileUploader extends Service implements OnDatatransferProgressListener {
 
@@ -490,37 +497,48 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
 
             notifyUploadStart(mCurrentUpload);
 
-            // / prepare client object to send requests to the ownCloud server
-            if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
-                mLastAccount = mCurrentUpload.getAccount();
-                mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
-            }
-
-            // / create remote folder for instant uploads
-            if (mCurrentUpload.isRemoteFolderToBeCreated()) {
-                mUploadClient.createDirectory(FileStorageUtils.getInstantUploadFilePath(this, ""));
-                // ignoring result fail could just mean that it already exists,
-                // but local database is not synchronized the upload will be
-                // tried anyway
-            }
-
-            // / perform the upload
             RemoteOperationResult uploadResult = null;
+            
             try {
+                /// prepare client object to send requests to the ownCloud server
+                if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
+                    mLastAccount = mCurrentUpload.getAccount();
+                    mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
+                    mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
+                }
+            
+                /// create remote folder for instant uploads
+                if (mCurrentUpload.isRemoteFolderToBeCreated()) {
+                    RemoteOperation operation = new CreateFolderOperation(  FileStorageUtils.getInstantUploadFilePath(this, ""), 
+                                                                            mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR).getFileId(), // TODO generalize this : INSTANT_UPLOAD_DIR could not be a child of root
+                                                                            mStorageManager);
+                    operation.execute(mUploadClient);      // ignoring result; fail could just mean that it already exists, but local database is not synchronized; the upload will be tried anyway
+                }
+
+            
+                /// perform the upload
                 uploadResult = mCurrentUpload.execute(mUploadClient);
                 if (uploadResult.isSuccess()) {
                     saveUploadedFile();
                 }
-
+                
+            } catch (AccountsException e) {
+                Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
+                uploadResult = new RemoteOperationResult(e);
+                
+            } catch (IOException e) {
+                Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e);
+                uploadResult = new RemoteOperationResult(e);
+                
             } finally {
                 synchronized (mPendingUploads) {
                     mPendingUploads.remove(uploadKey);
                     Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
                 }
             }
-
-            // notify result
+            
+            /// notify result
+            
             notifyUploadResult(uploadResult, mCurrentUpload);
             sendFinalBroadcast(mCurrentUpload, uploadResult);
 
@@ -775,7 +793,21 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             Notification finalNotification = new Notification(R.drawable.icon,
                     getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
             finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
-
+            if (uploadResult.getCode() == ResultCode.UNAUTHORIZED) {
+                // let the user update credentials with one click
+                Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
+                updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount());
+                updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+                updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
+                finalNotification.contentIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
+                mUploadClient = null;   // grant that future retries on the same account will get the fresh credentials
+            } else {
+                // TODO put something smart in the contentIntent below
+                finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+            }
+            
             String content = null;
             if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
                     || uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {

+ 0 - 1
src/com/owncloud/android/location/LocationServiceLauncherReciever.java

@@ -26,7 +26,6 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
-import android.util.Log;
 
 public class LocationServiceLauncherReciever extends BroadcastReceiver {
 

+ 0 - 1
src/com/owncloud/android/location/LocationUpdateService.java

@@ -27,7 +27,6 @@ import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
-import android.util.Log;
 import android.widget.Toast;
 
 import com.owncloud.android.Log_OC;

+ 0 - 2
src/com/owncloud/android/network/AdvancedSslSocketFactory.java

@@ -41,8 +41,6 @@ import org.apache.http.conn.ssl.X509HostnameVerifier;
 
 import com.owncloud.android.Log_OC;
 
-import android.util.Log;
-
 /**
  * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with 
  * a custom SSLContext and an optional Hostname Verifier.

+ 0 - 2
src/com/owncloud/android/network/AdvancedX509TrustManager.java

@@ -33,8 +33,6 @@ import javax.net.ssl.X509TrustManager;
 
 import com.owncloud.android.Log_OC;
 
-import android.util.Log;
-
 /**
  * @author David A. Velasco
  */

+ 268 - 0
src/com/owncloud/android/network/BearerAuthScheme.java

@@ -0,0 +1,268 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012  ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.network;
+
+import java.util.Map;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.auth.AuthChallengeParser;
+import org.apache.commons.httpclient.auth.AuthScheme;
+import org.apache.commons.httpclient.auth.AuthenticationException;
+import org.apache.commons.httpclient.auth.InvalidCredentialsException;
+import org.apache.commons.httpclient.auth.MalformedChallengeException;
+
+import com.owncloud.android.Log_OC;
+
+/**
+ * Bearer authentication scheme as defined in RFC 6750.
+ * 
+ * @author David A. Velasco
+ */
+
+public class BearerAuthScheme implements AuthScheme /*extends RFC2617Scheme*/ {
+    
+    private static final String TAG = BearerAuthScheme.class.getSimpleName();
+
+    public static final String AUTH_POLICY = "Bearer";
+    
+    /** Whether the bearer authentication process is complete */
+    private boolean mComplete;
+    
+    /** Authentication parameter map */
+    private Map mParams = null;
+    
+    
+    /**
+     * Default constructor for the bearer authentication scheme.
+     */
+    public BearerAuthScheme() {
+        mComplete = false;
+    }
+
+    /**
+     * Constructor for the basic authentication scheme.
+     * 
+     * @param   challenge                       Authentication challenge
+     * 
+     * @throws  MalformedChallengeException     Thrown if the authentication challenge is malformed
+     * 
+     * @deprecated Use parameterless constructor and {@link AuthScheme#processChallenge(String)} method
+     */
+    public BearerAuthScheme(final String challenge) throws MalformedChallengeException {
+        processChallenge(challenge);
+        mComplete = true;
+    }
+
+    /**
+     * Returns textual designation of the bearer authentication scheme.
+     * 
+     * @return "Bearer"
+     */
+    public String getSchemeName() {
+        return "bearer";
+    }
+
+    /**
+     * Processes the Bearer challenge.
+     *  
+     * @param   challenge                   The challenge string
+     * 
+     * @throws MalformedChallengeException  Thrown if the authentication challenge is malformed
+     */
+    public void processChallenge(String challenge) throws MalformedChallengeException {
+        String s = AuthChallengeParser.extractScheme(challenge);
+        if (!s.equalsIgnoreCase(getSchemeName())) {
+            throw new MalformedChallengeException(
+              "Invalid " + getSchemeName() + " challenge: " + challenge); 
+        }
+        mParams = AuthChallengeParser.extractParams(challenge);
+        mComplete = true;
+    }
+
+    /**
+     * Tests if the Bearer authentication process has been completed.
+     * 
+     * @return 'true' if Bearer authorization has been processed, 'false' otherwise.
+     */
+    public boolean isComplete() {
+        return this.mComplete;
+    }
+
+    /**
+     * Produces bearer authorization string for the given set of 
+     * {@link Credentials}.
+     * 
+     * @param   credentials                     The set of credentials to be used for authentication
+     * @param   method                          Method name is ignored by the bearer authentication scheme
+     * @param   uri                             URI is ignored by the bearer authentication scheme
+     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable 
+     *                                          for this authentication scheme
+     * @throws  AuthenticationException         If authorization string cannot be generated due to an authentication failure
+     * @return  A bearer authorization string
+     * 
+     * @deprecated Use {@link #authenticate(Credentials, HttpMethod)}
+     */
+    public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
+        Log_OC.d(TAG, "enter BearerScheme.authenticate(Credentials, String, String)");
+
+        BearerCredentials bearer = null;
+        try {
+            bearer = (BearerCredentials) credentials;
+        } catch (ClassCastException e) {
+            throw new InvalidCredentialsException(
+             "Credentials cannot be used for bearer authentication: " 
+              + credentials.getClass().getName());
+        }
+        return BearerAuthScheme.authenticate(bearer);
+    }
+
+    
+    /**
+     * Returns 'false'. Bearer authentication scheme is request based.
+     * 
+     * @return 'false'.
+     */
+    public boolean isConnectionBased() {
+        return false;    
+    }
+
+    /**
+     * Produces bearer authorization string for the given set of {@link Credentials}.
+     * 
+     * @param   credentials                     The set of credentials to be used for authentication
+     * @param   method                          The method being authenticated
+     * @throws  InvalidCredentialsException     If authentication credentials are not valid or not applicable for this authentication 
+     *                                          scheme.
+     * @throws AuthenticationException         If authorization string cannot be generated due to an authentication failure.
+     * 
+     * @return a basic authorization string
+     */
+    public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException {
+        Log_OC.d(TAG, "enter BearerScheme.authenticate(Credentials, HttpMethod)");
+
+        if (method == null) {
+            throw new IllegalArgumentException("Method may not be null");
+        }
+        BearerCredentials bearer = null;
+        try {
+            bearer = (BearerCredentials) credentials;
+        } catch (ClassCastException e) {
+            throw new InvalidCredentialsException(
+                    "Credentials cannot be used for bearer authentication: " 
+                    + credentials.getClass().getName());
+        }
+        return BearerAuthScheme.authenticate(
+            bearer, 
+            method.getParams().getCredentialCharset());
+    }
+    
+    /**
+     * @deprecated Use {@link #authenticate(BearerCredentials, String)}
+     * 
+     * Returns a bearer Authorization header value for the given 
+     * {@link BearerCredentials}.
+     * 
+     * @param   credentials     The credentials to encode.
+     * 
+     * @return                  A bearer authorization string
+     */
+    public static String authenticate(BearerCredentials credentials) {
+        return authenticate(credentials, "ISO-8859-1");
+    }
+
+    /**
+     * Returns a bearer Authorization header value for the given 
+     * {@link BearerCredentials} and charset.
+     * 
+     * @param   credentials         The credentials to encode.
+     * @param   charset             The charset to use for encoding the credentials
+     * 
+     * @return                      A bearer authorization string
+     * 
+     * @since 3.0
+     */
+    public static String authenticate(BearerCredentials credentials, String charset) {
+        Log_OC.d(TAG, "enter BearerAuthScheme.authenticate(BearerCredentials, String)");
+
+        if (credentials == null) {
+            throw new IllegalArgumentException("Credentials may not be null"); 
+        }
+        if (charset == null || charset.length() == 0) {
+            throw new IllegalArgumentException("charset may not be null or empty");
+        }
+        StringBuffer buffer = new StringBuffer();
+        buffer.append(credentials.getAccessToken());
+        
+        //return "Bearer " + EncodingUtil.getAsciiString(EncodingUtil.getBytes(buffer.toString(), charset));
+        return "Bearer " + buffer.toString();
+    }
+
+    /**
+     * Returns a String identifying the authentication challenge.  This is
+     * used, in combination with the host and port to determine if
+     * authorization has already been attempted or not.  Schemes which
+     * require multiple requests to complete the authentication should
+     * return a different value for each stage in the request.
+     * 
+     * Additionally, the ID should take into account any changes to the
+     * authentication challenge and return a different value when appropriate.
+     * For example when the realm changes in basic authentication it should be
+     * considered a different authentication attempt and a different value should
+     * be returned.
+     * 
+     * This method simply returns the realm for the challenge.
+     * 
+     * @return String       a String identifying the authentication challenge.
+     * 
+     * @deprecated no longer used
+     */
+    @Override
+    public String getID() {
+        return getRealm();
+    }
+
+    /**
+     * Returns authentication parameter with the given name, if available.
+     * 
+     * @param   name    The name of the parameter to be returned
+     * 
+     * @return          The parameter with the given name
+     */
+    @Override
+    public String getParameter(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Parameter name may not be null"); 
+        }
+        if (mParams == null) {
+            return null;
+        }
+        return (String) mParams.get(name.toLowerCase());
+    }
+
+    /**
+     * Returns authentication realm. The realm may not be null.
+     * 
+     * @return  The authentication realm
+     */
+    @Override
+    public String getRealm() {
+        return getParameter("realm");
+    }
+    
+}

+ 97 - 0
src/com/owncloud/android/network/BearerCredentials.java

@@ -0,0 +1,97 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012  ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.network;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.util.LangUtils;
+
+/**
+ * Bearer token {@link Credentials}
+ *
+ * @author David A. Velasco
+ */
+public class BearerCredentials implements Credentials {
+
+    
+    private String mAccessToken;
+    
+    
+    /**
+     * The constructor with the bearer token
+     *
+     * @param token     The bearer token
+     */
+    public BearerCredentials(String token) {
+        /*if (token == null) {
+            throw new IllegalArgumentException("Bearer token may not be null");            
+        }*/
+        mAccessToken = (token == null) ? "" : token;
+    }
+
+
+    /**
+     * Returns the access token
+     *
+     * @return      The access token
+     */
+    public String getAccessToken() {
+        return mAccessToken;
+    }
+
+
+    /**
+     * Get this object string.
+     *
+     * @return  The access token
+     */
+    public String toString() {
+        return mAccessToken;
+    }
+
+    /**
+     * Does a hash of the access token.
+     *
+     * @return The hash code of the access token
+     */
+    public int hashCode() {
+        int hash = LangUtils.HASH_SEED;
+        hash = LangUtils.hashCode(hash, mAccessToken);
+        return hash;
+    }
+
+    /**
+     * These credentials are assumed equal if accessToken is the same.
+     *
+     * @param   o   The other object to compare with.
+     *
+     * @return      'True' if the object is equivalent.
+     */
+    public boolean equals(Object o) {
+        if (o == null) return false;
+        if (this == o) return true;
+        if (this.getClass().equals(o.getClass())) {
+            BearerCredentials that = (BearerCredentials) o;
+            if (LangUtils.equals(mAccessToken, that.mAccessToken)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
+

+ 52 - 31
src/com/owncloud/android/network/OwnCloudClientUtils.java

@@ -37,19 +37,24 @@ import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
 import org.apache.http.conn.ssl.X509HostnameVerifier;
 
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.Log_OC;
 
 import eu.alefzero.webdav.WebdavClient;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Activity;
 import android.content.Context;
 import android.net.Uri;
-import android.util.Log;
+import android.os.Bundle;
 
 public class OwnCloudClientUtils {
     
-    final private static String TAG = "OwnCloudClientFactory";
+    final private static String TAG = OwnCloudClientUtils.class.getSimpleName();
     
     /** Default timeout for waiting data from the server */
     public static final int DEFAULT_DATA_TIMEOUT = 60000;
@@ -70,46 +75,61 @@ public class OwnCloudClientUtils {
     /**
      * Creates a WebdavClient setup for an ownCloud account
      * 
-     * @param account   The ownCloud account
-     * @param context   The application context
-     * @return          A WebdavClient object ready to be used
+     * Do not call this method from the main thread.
+     * 
+     * @param account                       The ownCloud account
+     * @param appContext                    Android application context
+     * @return                              A WebdavClient object ready to be used
+     * @throws AuthenticatorException       If the authenticator failed to get the authorization token for the account.
+     * @throws OperationCanceledException   If the authenticator operation was cancelled while getting the authorization token for the account. 
+     * @throws IOException                  If there was some I/O error while getting the authorization token for the account.
      */
-    public static WebdavClient createOwnCloudClient (Account account, Context context) {
-        Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
+    public static WebdavClient createOwnCloudClient (Account account, Context appContext) throws OperationCanceledException, AuthenticatorException, IOException {
+        //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
        
-        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(context, account));
-        WebdavClient client = createOwnCloudClient(uri, context);
+        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
+        WebdavClient client = createOwnCloudClient(uri, appContext);
+        AccountManager am = AccountManager.get(appContext);
+        if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) {    // TODO avoid a call to getUserData here
+            String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
+            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
         
-        String username = account.name.substring(0, account.name.lastIndexOf('@'));
-        String password = AccountManager.get(context).getPassword(account);
-        //String password = am.blockingGetAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE, true);
-        
-        client.setCredentials(username, password);
+        } else {
+            String username = account.name.substring(0, account.name.lastIndexOf('@'));
+            //String password = am.getPassword(account);
+            String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
+            client.setBasicCredentials(username, password);
+        }
         
         return client;
     }
     
     
-    /**
-     * Creates a WebdavClient to try a new account before saving it
-     * 
-     * @param uri       URL to the ownCloud server
-     * @param username  User name
-     * @param password  User password
-     * @param context   Android context where the WebdavClient is being created.
-     * @return          A WebdavClient object ready to be used
-     */
-    public static WebdavClient createOwnCloudClient(Uri uri, String username, String password, Context context) {
-        Log_OC.d(TAG, "Creating WebdavClient for " + username + "@" + uri);
-        
-        WebdavClient client = createOwnCloudClient(uri, context);
-        
-        client.setCredentials(username, password);
+    public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException {
+        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
+        WebdavClient client = createOwnCloudClient(uri, appContext);
+        AccountManager am = AccountManager.get(appContext);
+        if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) {    // TODO avoid a call to getUserData here
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
+            //String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
+            if (accessToken == null) throw new AuthenticatorException("WTF!");
+            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
+            
+        } else {
+            String username = account.name.substring(0, account.name.lastIndexOf('@'));
+            //String password = am.getPassword(account);
+            //String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String password = result.getString(AccountManager.KEY_AUTHTOKEN);
+            client.setBasicCredentials(username, password);
+        }
         
         return client;
     }
     
-    
     /**
      * Creates a WebdavClient to access a URL and sets the desired parameters for ownCloud client connections.
      * 
@@ -118,7 +138,7 @@ public class OwnCloudClientUtils {
      * @return          A WebdavClient object ready to be used
      */
     public static WebdavClient createOwnCloudClient(Uri uri, Context context) {
-        Log_OC.d(TAG, "Creating WebdavClient for " + uri);
+        //Log_OC.d(TAG, "Creating WebdavClient for " + uri);
         
         //allowSelfsignedCertificates(true);
         try {
@@ -244,4 +264,5 @@ public class OwnCloudClientUtils {
         return mConnManager;
     }
 
+
 }

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

@@ -32,7 +32,6 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.network.ProgressiveDataTransferer;
 
 import android.accounts.Account;
-import android.util.Log;
 
 import eu.alefzero.webdav.ChunkFromFileChannelRequestEntity;
 import eu.alefzero.webdav.WebdavClient;

+ 94 - 0
src/com/owncloud/android/operations/CreateFolderOperation.java

@@ -0,0 +1,94 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.operations;
+
+import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+
+import eu.alefzero.webdav.WebdavClient;
+import eu.alefzero.webdav.WebdavUtils;
+
+/**
+ * Remote operation performing the creation of a new folder in the ownCloud server.
+ * 
+ * @author David A. Velasco 
+ */
+public class CreateFolderOperation extends RemoteOperation {
+    
+    private static final String TAG = CreateFolderOperation.class.getSimpleName();
+
+    private static final int READ_TIMEOUT = 10000;
+    private static final int CONNECTION_TIMEOUT = 5000;
+    
+    protected String mRemotePath;
+    protected long mParentDirId;
+    protected DataStorageManager mStorageManager;
+    
+    /**
+     * Constructor
+     * 
+     * @param remoetPath            Full path to the new directory to create in the remote server.
+     * @param parentDirId           Local database id for the parent folder.
+     * @param storageManager        Reference to the local database corresponding to the account where the file is contained. 
+     */
+    public CreateFolderOperation(String remotePath, long parentDirId, DataStorageManager storageManager) {
+        mRemotePath = remotePath;
+        mParentDirId = parentDirId;
+        mStorageManager = storageManager;
+    }
+    
+    
+    /**
+     * Performs the remove operation
+     * 
+     * @param   client      Client object to communicate with the remote ownCloud server.
+     */
+    @Override
+    protected RemoteOperationResult run(WebdavClient client) {
+        RemoteOperationResult result = null;
+        MkColMethod mkcol = null;
+        try {
+            mkcol = new MkColMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
+            int status =  client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
+            if (mkcol.succeeded()) {
+                // Save new directory in local database
+                OCFile newDir = new OCFile(mRemotePath);
+                newDir.setMimetype("DIR");
+                newDir.setParentId(mParentDirId);
+                mStorageManager.saveFile(newDir);
+            }
+
+            result = new RemoteOperationResult(mkcol.succeeded(), status);
+            Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
+            client.exhaustResponse(mkcol.getResponseBodyAsStream());
+                
+        } catch (Exception e) {
+            result = new RemoteOperationResult(e);
+            Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
+            
+        } finally {
+            if (mkcol != null)
+                mkcol.releaseConnection();
+        }
+        return result;
+    }
+    
+}

+ 0 - 1
src/com/owncloud/android/operations/DownloadFileOperation.java

@@ -42,7 +42,6 @@ import eu.alefzero.webdav.OnDatatransferProgressListener;
 import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavUtils;
 import android.accounts.Account;
-import android.util.Log;
 import android.webkit.MimeTypeMap;
 
 /**

+ 94 - 0
src/com/owncloud/android/operations/ExistenceCheckOperation.java

@@ -0,0 +1,94 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.operations;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.HeadMethod;
+
+import com.owncloud.android.Log_OC;
+
+import eu.alefzero.webdav.WebdavClient;
+import android.content.Context;
+import android.net.ConnectivityManager;
+
+/**
+ * Operation to check the existence or absence of a path in a remote server.
+ * 
+ * @author David A. Velasco
+ */
+public class ExistenceCheckOperation extends RemoteOperation {
+    
+    /** Maximum time to wait for a response from the server in MILLISECONDs.  */
+    public static final int TIMEOUT = 10000;
+    
+    private static final String TAG = ExistenceCheckOperation.class.getSimpleName();
+    
+    private String mPath;
+    private Context mContext;
+    private boolean mSuccessIfAbsent;
+
+    
+    /**
+     * Full constructor. Success of the operation will depend upon the value of successIfAbsent.
+     * 
+     * @param path              Path to append to the URL owned by the client instance.
+     * @param context           Android application context.
+     * @param successIfAbsent   When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404).
+     */
+    public ExistenceCheckOperation(String path, Context context, boolean successIfAbsent) {
+        mPath = (path != null) ? path : "";
+        mContext = context;
+        mSuccessIfAbsent = successIfAbsent;
+    }
+    
+
+	@Override
+	protected RemoteOperationResult run(WebdavClient client) {
+        if (!isOnline()) {
+            return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
+        }
+        RemoteOperationResult result = null;
+        HeadMethod head = null;
+        try {
+            head = new HeadMethod(client.getBaseUri() + mPath);
+            int status = client.executeMethod(head, TIMEOUT, TIMEOUT);
+            client.exhaustResponse(head.getResponseBodyAsStream());
+            boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
+            result = new RemoteOperationResult(success, status);
+            Log_OC.d(TAG, "Existence check for " + client.getBaseUri() + mPath + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":""));
+            
+        } catch (Exception e) {
+            result = new RemoteOperationResult(e);
+            Log_OC.e(TAG, "Existence check for " + client.getBaseUri() + mPath + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException());
+            
+        } finally {
+            if (head != null)
+                head.releaseConnection();
+        }
+        return result;
+	}
+
+    private boolean isOnline() {
+        ConnectivityManager cm = (ConnectivityManager) mContext
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        return cm != null && cm.getActiveNetworkInfo() != null
+                && cm.getActiveNetworkInfo().isConnectedOrConnecting();
+    }
+
+
+}

+ 174 - 0
src/com/owncloud/android/operations/OAuth2GetAccessToken.java

@@ -0,0 +1,174 @@
+package com.owncloud.android.operations;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.NameValuePair;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.authentication.OAuth2Constants;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+
+import eu.alefzero.webdav.WebdavClient;
+
+public class OAuth2GetAccessToken extends RemoteOperation {
+    
+    private static final String TAG = OAuth2GetAccessToken.class.getSimpleName();
+    
+    private String mClientId;
+    private String mRedirectUri;
+    private String mGrantType;
+    
+    private String mOAuth2AuthorizationResponse;
+    private Map<String, String> mOAuth2ParsedAuthorizationResponse;
+    private Map<String, String> mResultTokenMap;
+
+    
+    public OAuth2GetAccessToken(String clientId, String redirectUri, String grantType, String oAuth2AuthorizationResponse) {
+        mClientId = clientId;
+        mRedirectUri = redirectUri;
+        mGrantType = grantType;
+        mOAuth2AuthorizationResponse = oAuth2AuthorizationResponse;
+        mOAuth2ParsedAuthorizationResponse = new HashMap<String, String>();
+        mResultTokenMap = null;
+    }
+    
+    
+    public Map<String, String> getOauth2AutorizationResponse() {
+        return mOAuth2ParsedAuthorizationResponse;
+    }
+
+    public Map<String, String> getResultTokenMap() {
+        return mResultTokenMap;
+    }
+    
+    @Override
+    protected RemoteOperationResult run(WebdavClient client) {
+        RemoteOperationResult result = null;
+        PostMethod postMethod = null;
+        
+        try {
+            parseAuthorizationResponse();
+            if (mOAuth2ParsedAuthorizationResponse.keySet().contains(OAuth2Constants.KEY_ERROR)) {
+                if (OAuth2Constants.VALUE_ERROR_ACCESS_DENIED.equals(mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_ERROR))) {
+                    result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR_ACCESS_DENIED);
+                } else {
+                    result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
+                }
+            }
+            
+            if (result == null) { 
+                NameValuePair[] nameValuePairs = new NameValuePair[4];
+                nameValuePairs[0] = new NameValuePair(OAuth2Constants.KEY_GRANT_TYPE, mGrantType);
+                nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CODE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_CODE));            
+                nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri);       
+                nameValuePairs[3] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
+                //nameValuePairs[4] = new NameValuePair(OAuth2Constants.KEY_SCOPE, mOAuth2ParsedAuthorizationResponse.get(OAuth2Constants.KEY_SCOPE));         
+                
+                postMethod = new PostMethod(client.getBaseUri().toString());
+                postMethod.setRequestBody(nameValuePairs);
+                int status = client.executeMethod(postMethod);
+                
+                String response = postMethod.getResponseBodyAsString();
+                if (response != null && response.length() > 0) {
+                    JSONObject tokenJson = new JSONObject(response);
+                    parseAccessTokenResult(tokenJson);
+                    if (mResultTokenMap.get(OAuth2Constants.KEY_ERROR) != null || mResultTokenMap.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
+                        result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
+                    
+                    } else {
+                        result = new RemoteOperationResult(true, status);
+                    }
+                    
+                } else {
+                    client.exhaustResponse(postMethod.getResponseBodyAsStream());
+                    result = new RemoteOperationResult(false, status);
+                }
+            }
+            
+        } catch (Exception e) {
+            result = new RemoteOperationResult(e);
+            
+        } finally {
+            if (postMethod != null)
+                postMethod.releaseConnection();    // let the connection available for other methods
+            
+            if (result.isSuccess()) {
+                Log_OC.i(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage());
+            
+            } else if (result.getException() != null) {
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage(), result.getException());
+                
+            } else if (result.getCode() == ResultCode.OAUTH2_ERROR) {
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + ((mResultTokenMap != null) ? mResultTokenMap.get(OAuth2Constants.KEY_ERROR) : "NULL"));
+                    
+            } else {
+                Log_OC.e(TAG, "OAuth2 TOKEN REQUEST with auth code " + mOAuth2ParsedAuthorizationResponse.get("code") + " to " + client.getBaseUri() + ": " + result.getLogMessage());
+            }
+        }
+        
+        return result;
+    }
+    
+    
+    private void parseAuthorizationResponse() {
+        String[] pairs = mOAuth2AuthorizationResponse.split("&");
+        int i = 0;
+        String key = "";
+        String value = "";
+        StringBuilder sb = new StringBuilder();
+        while (pairs.length > i) {
+            int j = 0;
+            String[] part = pairs[i].split("=");
+            while (part.length > j) {
+                String p = part[j];
+                if (j == 0) {
+                    key = p;
+                    sb.append(key + " = ");
+                } else if (j == 1) {
+                    value = p;
+                    mOAuth2ParsedAuthorizationResponse.put(key, value);
+                    sb.append(value + "\n");
+                }
+
+                Log_OC.v(TAG, "[" + i + "," + j + "] = " + p);
+                j++;
+            }
+            i++;
+        }
+    }
+
+
+    private void parseAccessTokenResult (JSONObject tokenJson) throws JSONException {
+        mResultTokenMap = new HashMap<String, String>();
+        
+        if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.getString(OAuth2Constants.KEY_ACCESS_TOKEN));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.getString(OAuth2Constants.KEY_TOKEN_TYPE));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.getString(OAuth2Constants.KEY_EXPIRES_IN));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.getString(OAuth2Constants.KEY_REFRESH_TOKEN));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.getString(OAuth2Constants.KEY_SCOPE));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.getString(OAuth2Constants.KEY_ERROR));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
+        }
+        if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
+            mResultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.getString(OAuth2Constants.KEY_ERROR_URI));
+        }
+    }
+
+}

+ 3 - 4
src/com/owncloud/android/operations/ConnectionCheckOperation.java → src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java

@@ -30,21 +30,20 @@ import eu.alefzero.webdav.WebdavClient;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.Uri;
-import android.util.Log;
 
-public class ConnectionCheckOperation extends RemoteOperation {
+public class OwnCloudServerCheckOperation extends RemoteOperation {
     
     /** Maximum time to wait for a response from the server when the connection is being tested, in MILLISECONDs.  */
     public static final int TRY_CONNECTION_TIMEOUT = 5000;
     
-    private static final String TAG = ConnectionCheckOperation.class.getSimpleName();
+    private static final String TAG = OwnCloudServerCheckOperation.class.getSimpleName();
     
     private String mUrl;
     private RemoteOperationResult mLatestResult;
     private Context mContext;
     private OwnCloudVersion mOCVersion;
 
-    public ConnectionCheckOperation(String url, Context context) {
+    public OwnCloudServerCheckOperation(String url, Context context) {
         mUrl = url;
         mContext = context;
         mOCVersion = null;

+ 152 - 5
src/com/owncloud/android/operations/RemoteOperation.java

@@ -16,6 +16,21 @@
  */
 package com.owncloud.android.operations;
 
+import java.io.IOException;
+
+import org.apache.commons.httpclient.Credentials;
+
+import com.owncloud.android.Log_OC;
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.network.BearerCredentials;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountsException;
+import android.app.Activity;
+import android.content.Context;
 import android.os.Handler;
 
 import eu.alefzero.webdav.WebdavClient;
@@ -29,7 +44,15 @@ import eu.alefzero.webdav.WebdavClient;
  */
 public abstract class RemoteOperation implements Runnable {
 	
-	/** Object to interact with the ownCloud server */
+    private static final String TAG = RemoteOperation.class.getSimpleName();
+
+    /** ownCloud account in the remote ownCloud server to operate */
+    private Account mAccount = null;
+    
+    /** Android Application context */
+    private Context mContext = null;
+    
+	/** Object to interact with the remote server */
 	private WebdavClient mClient = null;
 	
 	/** Callback object to notify about the execution of the remote operation */
@@ -38,16 +61,49 @@ public abstract class RemoteOperation implements Runnable {
 	/** Handler to the thread where mListener methods will be called */
 	private Handler mListenerHandler = null;
 
+	/** Activity */
+    private Activity mCallerActivity;
+
 	
 	/**
 	 *  Abstract method to implement the operation in derived classes.
 	 */
 	protected abstract RemoteOperationResult run(WebdavClient client); 
 	
+
+    /**
+     * Synchronously executes the remote operation on the received ownCloud account.
+     * 
+     * Do not call this method from the main thread.
+     * 
+     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
+     * 
+     * @param account   ownCloud account in remote ownCloud server to reach during the execution of the operation.
+     * @param context   Android context for the component calling the method.
+     * @return          Result of the operation.
+     */
+    public final RemoteOperationResult execute(Account account, Context context) {
+        if (account == null)
+            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
+        if (context == null)
+            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
+        mAccount = account;
+        mContext = context.getApplicationContext();
+        try {
+            mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
+        } catch (Exception e) {
+            Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
+            return new RemoteOperationResult(e);
+        }
+        return run(mClient);
+    }
+    
 	
 	/**
 	 * Synchronously executes the remote operation
 	 * 
+     * Do not call this method from the main thread.
+     * 
 	 * @param client	Client object to reach an ownCloud server during the execution of the operation.
 	 * @return			Result of the operation.
 	 */
@@ -59,6 +115,43 @@ public abstract class RemoteOperation implements Runnable {
 	}
 
 	
+    /**
+     * Asynchronously executes the remote operation
+     * 
+     * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}. 
+     * 
+     * @param account           ownCloud account in remote ownCloud server to reach during the execution of the operation.
+     * @param context           Android context for the component calling the method.
+     * @param listener          Listener to be notified about the execution of the operation.
+     * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
+     * @return                  Thread were the remote operation is executed.
+     */
+    public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
+        if (account == null)
+            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
+        if (context == null)
+            throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
+        mAccount = account;
+        mContext = context.getApplicationContext();
+        mCallerActivity = callerActivity;
+        mClient = null;     // the client instance will be created from mAccount and mContext in the runnerThread to create below
+        
+        if (listener == null) {
+            throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
+        }
+        mListener = listener;
+        
+        if (listenerHandler == null) {
+            throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
+        }
+        mListenerHandler = listenerHandler;
+        
+        Thread runnerThread = new Thread(this);
+        runnerThread.start();
+        return runnerThread;
+    }
+
+    
 	/**
 	 * Asynchronously executes the remote operation
 	 * 
@@ -115,20 +208,74 @@ public abstract class RemoteOperation implements Runnable {
 	 * Asynchronous execution of the operation 
 	 * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}, 
 	 * and result posting.
+	 * 
+	 * TODO refactor && clean the code; now it's a mess
 	 */
     @Override
     public final void run() {
-    	final RemoteOperationResult result = execute(mClient);
+        RemoteOperationResult result = null;
+        boolean repeat = false;
+        do {
+            try{
+                if (mClient == null) {
+                    if (mAccount != null && mContext != null) {
+                        if (mCallerActivity != null) {
+                            mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext, mCallerActivity);
+                        } else {
+                            mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
+                        }
+                    } else {
+                        throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
+                    }
+                }
+            
+            } catch (IOException e) {
+                Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
+                result = new RemoteOperationResult(e);
+            
+            } catch (AccountsException e) {
+                Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
+                result = new RemoteOperationResult(e);
+            }
     	
+            if (result == null)
+                result = run(mClient);
+        
+            repeat = false;
+            if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {
+                /// fail due to lack of authorization in an operation performed in foreground
+                AccountManager am = AccountManager.get(mContext);
+                Credentials cred = mClient.getCredentials();
+                if (cred instanceof BearerCredentials) {
+                    am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());
+                } else {
+                    am.clearPassword(mAccount);
+                }
+                mClient = null;
+                repeat = true;  // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity
+                result = null;
+            }
+        } while (repeat);
+        
+        final RemoteOperationResult resultToSend = result;
         if (mListenerHandler != null && mListener != null) {
         	mListenerHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mListener.onRemoteOperationFinish(RemoteOperation.this, result);
+                    mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
                 }
             });
         }
     }
-	
-	
+
+
+    /**
+     * Returns the current client instance to access the remote server.
+     * 
+     * @return      Current client instance to access the remote server.
+     */
+    public final WebdavClient getClient() {
+        return mClient;
+    }
+
 }

+ 30 - 5
src/com/owncloud/android/operations/RemoteOperationResult.java

@@ -32,8 +32,6 @@ import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.jackrabbit.webdav.DavException;
 
-import android.util.Log;
-
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.network.CertificateCombinedException;
 
@@ -49,10 +47,37 @@ public class RemoteOperationResult implements Serializable {
 
     /** Generated - should be refreshed every time the class changes!! */
     private static final long serialVersionUID = -7805531062432602444L;
+    
     private static final String TAG = "RemoteOperationResult";
-
-    public enum ResultCode {
-        OK, OK_SSL, OK_NO_SSL, UNHANDLED_HTTP_CODE, UNAUTHORIZED, FILE_NOT_FOUND, INSTANCE_NOT_CONFIGURED, UNKNOWN_ERROR, WRONG_CONNECTION, TIMEOUT, INCORRECT_ADDRESS, HOST_NOT_AVAILABLE, NO_NETWORK_CONNECTION, SSL_ERROR, SSL_RECOVERABLE_PEER_UNVERIFIED, BAD_OC_VERSION, CANCELLED, INVALID_LOCAL_FILE_NAME, INVALID_OVERWRITE, CONFLICT, SYNC_CONFLICT, LOCAL_STORAGE_FULL, LOCAL_STORAGE_NOT_MOVED, LOCAL_STORAGE_NOT_COPIED, QUOTA_EXCEEDED
+    
+    public enum ResultCode { 
+        OK,
+        OK_SSL,
+        OK_NO_SSL,
+        UNHANDLED_HTTP_CODE,
+        UNAUTHORIZED,        
+        FILE_NOT_FOUND, 
+        INSTANCE_NOT_CONFIGURED, 
+        UNKNOWN_ERROR, 
+        WRONG_CONNECTION,  
+        TIMEOUT, 
+        INCORRECT_ADDRESS, 
+        HOST_NOT_AVAILABLE, 
+        NO_NETWORK_CONNECTION, 
+        SSL_ERROR,
+        SSL_RECOVERABLE_PEER_UNVERIFIED,
+        BAD_OC_VERSION,
+        CANCELLED, 
+        INVALID_LOCAL_FILE_NAME, 
+        INVALID_OVERWRITE,
+        CONFLICT, 
+        OAUTH2_ERROR,
+        SYNC_CONFLICT,
+        LOCAL_STORAGE_FULL, 
+        LOCAL_STORAGE_NOT_MOVED, 
+        LOCAL_STORAGE_NOT_COPIED, 
+        OAUTH2_ERROR_ACCESS_DENIED,
+        QUOTA_EXCEEDED
     }
 
     private boolean mSuccess = false;

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

@@ -20,8 +20,6 @@ package com.owncloud.android.operations;
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
 
-import android.util.Log;
-
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;

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

@@ -24,7 +24,6 @@ import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
 //import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
 
 import android.accounts.Account;
-import android.util.Log;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;
@@ -42,7 +41,7 @@ import eu.alefzero.webdav.WebdavUtils;
  */
 public class RenameFileOperation extends RemoteOperation {
     
-    private static final String TAG = RemoveFileOperation.class.getSimpleName();
+    private static final String TAG = RenameFileOperation.class.getSimpleName();
 
     private static final int RENAME_READ_TIMEOUT = 10000;
     private static final int RENAME_CONNECTION_TIMEOUT = 5000;

+ 0 - 1
src/com/owncloud/android/operations/SynchronizeFileOperation.java

@@ -25,7 +25,6 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Log;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;

+ 0 - 1
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -34,7 +34,6 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 
 import android.accounts.Account;
 import android.content.Context;
-import android.util.Log;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.DataStorageManager;

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

@@ -25,11 +25,10 @@ import org.json.JSONObject;
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.Context;
-import android.util.Log;
 
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.Log_OC;
-import com.owncloud.android.authenticator.AccountAuthenticator;
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.utils.OwnCloudVersion;
 

+ 0 - 1
src/com/owncloud/android/providers/FileContentProvider.java

@@ -37,7 +37,6 @@ 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.

+ 1 - 1
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java

@@ -142,7 +142,7 @@ public abstract class AbstractOwnCloudSyncAdapter extends
         return null;
     }
 
-    protected void initClientForCurrentAccount() throws UnknownHostException {
+    protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException {
         if (AccountUtils.constructFullURLForAccount(getContext(), account) == null) {
             throw new UnknownHostException();
         }

+ 1 - 1
src/com/owncloud/android/syncadapter/ContactSyncAdapter.java

@@ -25,7 +25,7 @@ import org.apache.http.client.methods.HttpPut;
 import org.apache.http.entity.ByteArrayEntity;
 
 import com.owncloud.android.AccountUtils;
-import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.authentication.AccountAuthenticator;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;

+ 31 - 12
src/com/owncloud/android/syncadapter/FileSyncAdapter.java

@@ -19,7 +19,6 @@
 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;
@@ -29,6 +28,7 @@ import org.apache.jackrabbit.webdav.DavException;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
+import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
@@ -38,6 +38,7 @@ 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.accounts.AccountsException;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -47,13 +48,13 @@ 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
+ * @author David A. Velasco
  */
 public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
 
@@ -103,8 +104,13 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         this.setStorageManager(new FileDataStorageManager(account, getContentProvider()));
         try {
             this.initClientForCurrentAccount();
-        } catch (UnknownHostException e) {
-            /// the account is unknown for the Synchronization Manager. unreachable for this context; don't try this again
+        } catch (IOException e) {
+            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
+            mSyncResult.tooManyRetries = true;
+            notifyFailedSynchronization();
+            return;
+        } catch (AccountsException e) {
+            /// the account is unknown for the Synchronization Manager, or unreachable for this context; don't try this again
             mSyncResult.tooManyRetries = true;
             notifyFailedSynchronization();
             return;
@@ -147,7 +153,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         }
         
     }
-
     
     /**
      * Called by system SyncManager when a synchronization is required to be cancelled.
@@ -173,7 +178,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             mLastFailedResult = result; 
         }
     }
-
     
     
     /**
@@ -292,12 +296,28 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private void notifyFailedSynchronization() {
         Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
-        // TODO put something smart in the contentIntent below
+        boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED);
+        // TODO put something smart in the contentIntent below for all the possible errors
         notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
-        notification.setLatestEventInfo(getContext().getApplicationContext(), 
-                                        getContext().getString(R.string.sync_fail_ticker), 
-                                        String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), 
-                                        notification.contentIntent);
+        if (needsToUpdateCredentials) {
+            // let the user update credentials with one click
+            Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);
+            updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());
+            updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+            updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
+            notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);
+            notification.setLatestEventInfo(getContext().getApplicationContext(), 
+                    getContext().getString(R.string.sync_fail_ticker), 
+                    String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name), 
+                    notification.contentIntent);
+        } else {
+            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);
     }
 
@@ -331,7 +351,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             ((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 

+ 4 - 5
src/com/owncloud/android/ui/activity/AccountSelectActivity.java

@@ -32,7 +32,6 @@ import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 import android.view.ContextMenu;
 import android.view.View;
 import android.view.ViewGroup;
@@ -49,8 +48,8 @@ import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.Log_OC;
-import com.owncloud.android.authenticator.AccountAuthenticator;
 
 import com.owncloud.android.R;
 
@@ -95,10 +94,10 @@ public class AccountSelectActivity extends SherlockListActivity implements
                 /// the account set as default changed since this activity was created 
             
                 // trigger synchronization
-                ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE);
+                ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY);
                 Bundle bundle = new Bundle();
                 bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
-                ContentResolver.requestSync(AccountUtils.getCurrentOwnCloudAccount(this), AccountAuthenticator.AUTH_TOKEN_TYPE, bundle);
+                ContentResolver.requestSync(AccountUtils.getCurrentOwnCloudAccount(this), AccountAuthenticator.AUTHORITY, bundle);
                 
                 // restart the main activity
                 Intent i = new Intent(this, FileDisplayActivity.class);
@@ -136,7 +135,7 @@ public class AccountSelectActivity extends SherlockListActivity implements
             Intent intent = new Intent(
                     android.provider.Settings.ACTION_ADD_ACCOUNT);
             intent.putExtra("authorities",
-                    new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
+                    new String[] { AccountAuthenticator.AUTHORITY });
             startActivity(intent);
             return true;
         }

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

@@ -1,609 +0,0 @@
-/* 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 version 2,
- *   as published by the Free Software Foundation.
- *
- *   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);
-    }
-    
-}

+ 0 - 1
src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java

@@ -28,7 +28,6 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.support.v4.app.DialogFragment;
 import android.text.method.ScrollingMovementMethod;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;

+ 17 - 11
src/com/owncloud/android/ui/activity/FailedUploadActivity.java

@@ -1,3 +1,20 @@
+/* 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 version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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.app.Activity;
@@ -14,18 +31,7 @@ import com.owncloud.android.R;
  * 
  * The entry-point for this activity is the 'Failed upload Notification"
  * 
- * 
  * @author andomaex / Matthias Baumann
- * 
- *         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 3 of the License. (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 de/
  */
 public class FailedUploadActivity extends Activity {
 

+ 47 - 120
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -23,7 +23,6 @@ import java.io.File;
 import android.accounts.Account;
 import android.app.AlertDialog;
 import android.app.ProgressDialog;
-import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -46,11 +45,9 @@ import android.preference.PreferenceManager;
 import android.provider.MediaStore;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentTransaction;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
-import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -64,7 +61,7 @@ import com.actionbarsherlock.view.Window;
 import com.owncloud.android.AccountUtils;
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
@@ -73,7 +70,7 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.CreateFolderOperation;
 import com.owncloud.android.operations.OnRemoteOperationListener;
 import com.owncloud.android.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoteOperationResult;
@@ -94,8 +91,6 @@ import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewVideoActivity;
 
-import eu.alefzero.webdav.WebdavClient;
-
 /**
  * Displays, what files the user has available in his ownCloud.
  * 
@@ -125,13 +120,10 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
     private boolean mBackFromCreatingFirstAccount;
     
     private static final int DIALOG_SETUP_ACCOUNT = 0;
-    private static final int DIALOG_CREATE_DIR = 1;
-    public static final int DIALOG_SHORT_WAIT = 3;
-    private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4;
-    private static final int DIALOG_SSL_VALIDATOR = 5;
-    private static final int DIALOG_CERT_NOT_SAVED = 6;
-    private static final String DIALOG_CHANGELOG_TAG = "DIALOG_CHANGELOG";
-
+    public static final int DIALOG_SHORT_WAIT = 1;
+    private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 2;
+    private static final int DIALOG_SSL_VALIDATOR = 3;
+    private static final int DIALOG_CERT_NOT_SAVED = 4;
     
     private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
     private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
@@ -150,6 +142,8 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         super.onCreate(savedInstanceState);
         mStarted = false;
 
+        mHandler = new Handler();
+
         /// Load of parameters from received intent
         Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
         if (account != null && AccountUtils.setCurrentOwnCloudAccount(this, account.name)) {
@@ -245,7 +239,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
      */
     private void createFirstAccount() {
         Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
-        intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
+        intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTHORITY });
         startActivity(intent);  // the new activity won't be created until this.onStart() and this.onResume() are finished;
     }
 
@@ -400,12 +394,12 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
     }
 
     private void startSynchronization() {
-        ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE);   // cancel the current synchronizations of any ownCloud account
+        ContentResolver.cancelSync(null, AccountAuthenticator.AUTHORITY);   // cancel the current synchronizations of any ownCloud account
         Bundle bundle = new Bundle();
         bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
         ContentResolver.requestSync(
                 AccountUtils.getCurrentOwnCloudAccount(this),
-                AccountAuthenticator.AUTH_TOKEN_TYPE, bundle);
+                AccountAuthenticator.AUTHORITY, bundle);
     }
 
 
@@ -560,7 +554,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
         Log_OC.d(getClass().toString(), "onSaveInstanceState() end");
     }
-
     
     @Override
     protected void onResume() {
@@ -666,53 +659,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             dialog = builder.create();
             break;
         }
-        case DIALOG_CREATE_DIR: {
-            builder = new Builder(this);
-            final EditText dirNameInput = new EditText(getBaseContext());
-            builder.setView(dirNameInput);
-            builder.setTitle(R.string.uploader_info_dirname);
-            int typed_color = getResources().getColor(R.color.setup_text_typed);
-            dirNameInput.setTextColor(typed_color);
-            builder.setPositiveButton(android.R.string.ok,
-                    new OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            String directoryName = dirNameInput.getText().toString();
-                            if (directoryName.trim().length() == 0) {
-                                dialog.cancel();
-                                return;
-                            }
-    
-                            // Figure out the path where the dir needs to be created
-                            String path;
-                            if (mCurrentDir == null) {
-                                // this is just a patch; we should ensure that mCurrentDir never is null
-                                if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
-                                    OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
-                                    mStorageManager.saveFile(file);
-                                }
-                                mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
-                            }
-                            path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
-                            
-                            // Create directory
-                            path += directoryName + OCFile.PATH_SEPARATOR;
-                            Thread thread = new Thread(new DirectoryCreator(path,  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
-                            thread.start();
-                            
-                            dialog.dismiss();
-                            
-                            showDialog(DIALOG_SHORT_WAIT);
-                        }
-                    });
-            builder.setNegativeButton(R.string.common_cancel,
-                    new OnClickListener() {
-                        public void onClick(DialogInterface dialog, int which) {
-                            dialog.cancel();
-                        }
-                    });
-            dialog = builder.create();
-            break;
-        }
         case DIALOG_SHORT_WAIT: {
             ProgressDialog working_dialog = new ProgressDialog(this);
             working_dialog.setMessage(getResources().getString(
@@ -833,57 +779,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         return !mDirectories.isEmpty();
     }
 
-    private class DirectoryCreator implements Runnable {
-        private String mTargetPath;
-        private Account mAccount;
-        private Handler mHandler; 
-    
-        public DirectoryCreator(String targetPath, Account account, Handler handler) {
-            mTargetPath = targetPath;
-            mAccount = account;
-            mHandler = handler;
-        }
-    
-        @Override
-        public void run() {
-            WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
-            boolean created = wdc.createDirectory(mTargetPath);
-            if (created) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() { 
-                        dismissDialog(DIALOG_SHORT_WAIT);
-                        
-                        // Save new directory in local database
-                        OCFile newDir = new OCFile(mTargetPath);
-                        newDir.setMimetype("DIR");
-                        newDir.setParentId(mCurrentDir.getFileId());
-                        mStorageManager.saveFile(newDir);
-    
-                        // Display the new folder right away
-                        mFileList.listDirectory();
-                    }
-                });
-                
-            } else {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        dismissDialog(DIALOG_SHORT_WAIT);
-                        try {
-                            Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG); 
-                            msg.show();
-                        
-                        } catch (NotFoundException e) {
-                            Log_OC.e(TAG, "Error while trying to show fail message ", e);
-                        }
-                    }
-                });
-            }
-        }
-    
-    }
-
     // Custom array adapter to override text colors
     private class CustomArrayAdapter<T> extends ArrayAdapter<T> {
     
@@ -1312,6 +1207,9 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
             
         } else if (operation instanceof SynchronizeFileOperation) {
             onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
+
+        } else if (operation instanceof CreateFolderOperation) {
+            onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
         }
     }
 
@@ -1351,6 +1249,30 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         }
     }
 
+    /**
+     * Updates the view associated to the activity after the finish of an operation trying create a new folder
+     * 
+     * @param operation     Creation operation performed.
+     * @param result        Result of the creation.
+     */
+    private void onCreateFolderOperationFinish(CreateFolderOperation operation, RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            dismissDialog(DIALOG_SHORT_WAIT);
+            mFileList.listDirectory();
+            
+        } else {
+            dismissDialog(DIALOG_SHORT_WAIT);
+            try {
+                Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG); 
+                msg.show();
+                    
+            } catch (NotFoundException e) {
+                Log_OC.e(TAG, "Error while trying to show fail message " , e);
+            }
+        }
+    }
+    
+    
     /**
      * Updates the view associated to the activity after the finish of an operation trying to rename a 
      * file. 
@@ -1459,7 +1381,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         //dialog.dismiss();
         if (dialog.getResult()) {
             String newDirectoryName = dialog.getNewFilename().trim();
-            Log.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
+            Log_OC.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
             if (newDirectoryName.length() > 0) {
                 String path;
                 if (mCurrentDir == null) {
@@ -1474,14 +1396,19 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
                 
                 // Create directory
                 path += newDirectoryName + OCFile.PATH_SEPARATOR;
-                Thread thread = new Thread(new DirectoryCreator(path,  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
-                thread.start();
+                RemoteOperation operation = new CreateFolderOperation(path, mCurrentDir.getFileId(), mStorageManager);
+                operation.execute(  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), 
+                                    FileDisplayActivity.this, 
+                                    FileDisplayActivity.this, 
+                                    mHandler,
+                                    FileDisplayActivity.this);
                 
                 showDialog(DIALOG_SHORT_WAIT);
             }
         }
     }
-
+    
+    
     private void requestForDownload() {
         Account account = AccountUtils.getCurrentOwnCloudAccount(this);
         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {

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

@@ -2,8 +2,8 @@
  *   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 3 of the License.
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,7 +26,6 @@ import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.os.Bundle;
-import android.util.Log;
 import android.util.SparseArray;
 import android.view.Gravity;
 import android.view.View;
@@ -59,16 +58,6 @@ import com.owncloud.android.utils.FileStorageUtils;
  * sub-menu underneath the 'Upload' menu-item
  * 
  * @author andomaex / Matthias Baumann
- * 
- *         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 3 of the License. (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 de/
  */
 public class InstantUploadActivity extends Activity {
 
@@ -363,7 +352,7 @@ public class InstantUploadActivity extends Activity {
 
             @Override
             public boolean onLongClick(View v) {
-                Log.d(LOG_TAG, message);
+                Log_OC.d(LOG_TAG, message);
                 Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
                         + message, Toast.LENGTH_LONG);
                 toast.show();

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

@@ -17,7 +17,7 @@
 package com.owncloud.android.ui.activity;
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.owncloud.android.authenticator.AccountAuthenticator;
+import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.ui.adapter.LandingScreenAdapter;
 
 import android.accounts.Account;
@@ -112,9 +112,9 @@ public class LandingActivity extends SherlockFragmentActivity implements
         dialog.dismiss();
         switch (which) {
         case DialogInterface.BUTTON_POSITIVE:
-            Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
+            Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
             intent.putExtra("authorities",
-                    new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE });
+                    new String[] { AccountAuthenticator.AUTHORITY });
             startActivity(intent);
             break;
         case DialogInterface.BUTTON_NEGATIVE:

+ 0 - 1
src/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -25,7 +25,6 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Environment;
 import android.support.v4.app.DialogFragment;
-import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;

+ 0 - 1
src/com/owncloud/android/ui/dialog/SslValidatorDialog.java

@@ -31,7 +31,6 @@ import javax.security.auth.x500.X500Principal;
 import android.app.Dialog;
 import android.content.Context;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.View;
 import android.view.Window;
 import android.widget.Button;

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

@@ -22,7 +22,6 @@ import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.util.Log;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.Log_OC;

+ 118 - 141
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -22,18 +22,6 @@ 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;
@@ -46,7 +34,6 @@ 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;
@@ -62,10 +49,8 @@ import com.actionbarsherlock.app.SherlockFragment;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
-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;
@@ -85,7 +70,6 @@ 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;
 
@@ -93,7 +77,6 @@ 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.
  * 
@@ -140,7 +123,6 @@ public class FileDetailFragment extends SherlockFragment implements
         mProgressListener = null;
     }
     
-    
     /**
      * Creates a details fragment.
      * 
@@ -390,7 +372,6 @@ public class FileDetailFragment extends SherlockFragment implements
         }
     }
     
-    
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
@@ -484,9 +465,8 @@ public class FileDetailFragment extends SherlockFragment implements
             
         } else {
             mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());
-            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-            mLastRemoteOperation.execute(wc, this, mHandler);
-        
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
+            
             // update ui 
             boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
             getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
@@ -494,7 +474,6 @@ public class FileDetailFragment extends SherlockFragment implements
         }
     }
 
-
     /**
      * Opens mFile.
      */
@@ -509,7 +488,7 @@ public class FileDetailFragment extends SherlockFragment implements
             startActivity(i);
             
         } catch (Throwable t) {
-            Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+            Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
             boolean toastIt = true; 
             String mimeType = "";
             try {
@@ -528,13 +507,13 @@ public class FileDetailFragment extends SherlockFragment implements
                 }
                 
             } catch (IndexOutOfBoundsException e) {
-                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+                Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
                 
             } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+                Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
                 
             } catch (Throwable th) {
-                Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+                Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
                 
             } finally {
                 if (toastIt) {
@@ -545,7 +524,6 @@ public class FileDetailFragment extends SherlockFragment implements
         }
     }
 
-
     @Override
     public void onConfirmation(String callerTag) {
         if (callerTag.equals(FTAG_CONFIRMATION)) {
@@ -553,8 +531,7 @@ public class FileDetailFragment extends SherlockFragment implements
                 mLastRemoteOperation = new RemoveFileOperation( mFile, 
                                                                 true, 
                                                                 mStorageManager);
-                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-                mLastRemoteOperation.execute(wc, this, mHandler);
+                mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
                 
                 boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
                 getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
@@ -575,7 +552,7 @@ public class FileDetailFragment extends SherlockFragment implements
     
     @Override
     public void onCancel(String callerTag) {
-        Log.d(TAG, "REMOVAL CANCELED");
+        Log_OC.d(TAG, "REMOVAL CANCELED");
     }
     
     
@@ -666,7 +643,6 @@ public class FileDetailFragment extends SherlockFragment implements
         getView().invalidate();
     }
     
-    
     /**
      * Checks if the fragment is ready to show details of a OCFile
      *  
@@ -846,120 +822,15 @@ public class FileDetailFragment extends SherlockFragment implements
     }
     
 
-    // 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);
+            Log_OC.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);
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
             boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
             getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
         }
@@ -1075,7 +946,7 @@ public class FileDetailFragment extends SherlockFragment implements
         }
     }
     
-    
+
     public void listenForTransferProgress() {
         if (mProgressListener != null) {
             if (mContainerActivity.getFileDownloaderBinder() != null) {
@@ -1134,4 +1005,110 @@ public class FileDetailFragment extends SherlockFragment implements
 
     };
 
-}
+    /*
+    // this is a temporary class for sharing purposes, it need to be replaced in transfer service
+    @SuppressWarnings("unused")
+    private class ShareRunnable implements Runnable {
+        private String mPath;
+
+        public ShareRunnable(String path) {
+            mPath = path;
+        }
+        
+        public void run() {
+            AccountManager am = AccountManager.get(getActivity());
+            Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
+            OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
+            String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
+
+            Log_OC.d("share", "sharing for version " + ocv.toString());
+
+            if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
+                String APPS_PATH = "/apps/files_sharing/";
+                String SHARE_PATH = "ajax/share.php";
+
+                String SHARED_PATH = "/apps/files_sharing/get.php?token=";
+                
+                final String WEBDAV_SCRIPT = "webdav.php";
+                final String WEBDAV_FILES_LOCATION = "/files/";
+                
+                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getActivity().getApplicationContext());
+                HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+                params.setMaxConnectionsPerHost(wc.getHostConfiguration(), 5);
+
+                //wc.getParams().setParameter("http.protocol.single-cookie-header", true);
+                //wc.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
+
+                PostMethod post = new PostMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + APPS_PATH + SHARE_PATH);
+
+                post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
+                post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
+                List<NameValuePair> formparams = new ArrayList<NameValuePair>();
+                Log_OC.d("share", mPath+"");
+                formparams.add(new BasicNameValuePair("sources",mPath));
+                formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
+                formparams.add(new BasicNameValuePair("permissions", "0"));
+                post.setRequestEntity(new StringRequestEntity(URLEncodedUtils.format(formparams, HTTP.UTF_8)));
+
+                int status;
+                try {
+                    PropFindMethod find = new PropFindMethod(url+"/");
+                    find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
+                    Log_OC.d("sharer", ""+ url+"/");
+                    
+                    for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
+                        Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
+                    }
+                    
+                    int status2 = wc.executeMethod(find);
+
+                    Log_OC.d("sharer", "propstatus "+status2);
+                    
+                    GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
+                    get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
+                    
+                    status2 = wc.executeMethod(get);
+
+                    Log_OC.d("sharer", "getstatus "+status2);
+                    Log_OC.d("sharer", "" + get.getResponseBodyAsString());
+                    
+                    for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
+                        Log_OC.d("sharer", a.getName() + ":"+a.getValue());
+                    }
+
+                    status = wc.executeMethod(post);
+                    for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
+                        Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
+                    }
+                    for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
+                        Log_OC.d("sharer", a.getName() + ":"+a.getValue());
+                    }
+                    String resp = post.getResponseBodyAsString();
+                    Log_OC.d("share", ""+post.getURI().toString());
+                    Log_OC.d("share", "returned status " + status);
+                    Log_OC.d("share", " " +resp);
+                    
+                    if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
+                        return;
+                     }
+
+                    JSONObject jsonObject = new JSONObject (resp);
+                    String jsonStatus = jsonObject.getString("status");
+                    if(!jsonStatus.equals("success")) throw new Exception("Error while sharing file status != success");
+                    
+                    String token = jsonObject.getString("data");
+                    String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token; 
+                    Log_OC.d("Actions:shareFile ok", "url: " + uri);   
+                    
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                
+            } else if (ocv.compareTo(new OwnCloudVersion(0x030000)) >= 0) {
+                
+            }
+        }
+    }
+    */
+    
+}

+ 0 - 1
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -25,7 +25,6 @@ import com.owncloud.android.ui.adapter.LocalFileListAdapter;
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Environment;
-import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.LayoutInflater;
 import android.view.View;

+ 3 - 9
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -28,7 +28,6 @@ import com.owncloud.android.datamodel.DataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 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.RemoveFileOperation;
@@ -42,7 +41,6 @@ import com.owncloud.android.ui.dialog.EditNameDialog;
 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
 
-import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavUtils;
 
 import android.accounts.Account;
@@ -52,7 +50,6 @@ import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 import android.view.ContextMenu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -318,8 +315,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
             case R.id.action_sync_file: {
                 Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
                 RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
-                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getSherlockActivity().getApplicationContext());
-                operation.execute(wc, mContainerActivity, mHandler);
+                operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
                 getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
                 return true;
             }
@@ -485,8 +481,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                                                                 AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
                                                                 newFilename, 
                                                                 mContainerActivity.getStorageManager());
-            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
-            operation.execute(wc, mContainerActivity, mHandler);
+            operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
             getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
         }
     }
@@ -499,8 +494,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                 RemoteOperation operation = new RemoveFileOperation( mTargetFile, 
                                                                     true, 
                                                                     mContainerActivity.getStorageManager());
-                WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
-                operation.execute(wc, mContainerActivity, mHandler);
+                operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
                 
                 getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
             }

+ 4 - 4
src/com/owncloud/android/ui/preview/FileDownloadFragment.java

@@ -3,8 +3,8 @@
  *   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 3 of the License.
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,7 +23,6 @@ import android.accounts.Account;
 import android.app.Activity;
 import android.os.Bundle;
 import android.support.v4.app.FragmentStatePagerAdapter;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -38,6 +37,7 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.ui.fragment.FileFragment;
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 
 import eu.alefzero.webdav.OnDatatransferProgressListener;
@@ -239,7 +239,7 @@ public class FileDownloadFragment extends SherlockFragment implements OnClickLis
                 break;
             }
             default:
-                Log.e(TAG, "Incorrect view clicked!");
+                Log_OC.e(TAG, "Incorrect view clicked!");
         }
     }
 

+ 7 - 10
src/com/owncloud/android/ui/preview/PreviewImageActivity.java

@@ -16,8 +16,6 @@
  */
 package com.owncloud.android.ui.preview;
 
-import org.apache.commons.httpclient.methods.PostMethod;
-
 import android.accounts.Account;
 import android.app.Dialog;
 import android.app.ProgressDialog;
@@ -29,9 +27,7 @@ import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.support.v4.app.Fragment;
 import android.support.v4.view.ViewPager;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;
@@ -52,6 +48,7 @@ import com.owncloud.android.ui.fragment.FileDetailFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
 
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 
 /**
@@ -170,12 +167,12 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
                 mDownloaderBinder = (FileDownloaderBinder) service;
                 if (mRequestWaitingForBinder) {
                     mRequestWaitingForBinder = false;
-                    Log.d(TAG, "Simulating reselection of current page after connection of download binder");
+                    Log_OC.d(TAG, "Simulating reselection of current page after connection of download binder");
                     onPageSelected(mViewPager.getCurrentItem());
                 }
                     
             } else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
-                Log.d(TAG, "Upload service connected");
+                Log_OC.d(TAG, "Upload service connected");
                 mUploaderBinder = (FileUploaderBinder) service;
             } else {
                 return;
@@ -186,10 +183,10 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
         @Override
         public void onServiceDisconnected(ComponentName component) {
             if (component.equals(new ComponentName(PreviewImageActivity.this, FileDownloader.class))) {
-                Log.d(TAG, "Download service suddenly disconnected");
+                Log_OC.d(TAG, "Download service suddenly disconnected");
                 mDownloaderBinder = null;
             } else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
-                Log.d(TAG, "Upload service suddenly disconnected");
+                Log_OC.d(TAG, "Upload service suddenly disconnected");
                 mUploaderBinder = null;
             }
         }
@@ -328,7 +325,7 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
     
     private void requestForDownload(OCFile file) {
         if (mDownloaderBinder == null) {
-            Log.d(TAG, "requestForDownload called without binder to download service");
+            Log_OC.d(TAG, "requestForDownload called without binder to download service");
             
         } else if (!mDownloaderBinder.isDownloading(mAccount, file)) {
             Intent i = new Intent(this, FileDownloader.class);
@@ -413,7 +410,7 @@ public class PreviewImageActivity extends SherlockFragmentActivity implements Fi
                     mPreviewImagePagerAdapter.notifyDataSetChanged();   // will trigger the creation of new fragments
                     
                 } else {
-                    Log.d(TAG, "Download finished, but the fragment is offscreen");
+                    Log_OC.d(TAG, "Download finished, but the fragment is offscreen");
                 }
                 
             }

+ 11 - 14
src/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -36,7 +36,6 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.v4.app.FragmentStatePagerAdapter;
-import android.util.Log;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -54,7 +53,6 @@ import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.network.OwnCloudClientUtils;
 import com.owncloud.android.operations.OnRemoteOperationListener;
 import com.owncloud.android.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoteOperationResult;
@@ -62,8 +60,8 @@ import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
 
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavUtils;
 
 
@@ -339,7 +337,7 @@ public class PreviewImageFragment extends SherlockFragment implements   FileFrag
             startActivity(i);
             
         } catch (Throwable t) {
-            Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+            Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
             boolean toastIt = true; 
             String mimeType = "";
             try {
@@ -358,13 +356,13 @@ public class PreviewImageFragment extends SherlockFragment implements   FileFrag
                 }
                 
             } catch (IndexOutOfBoundsException e) {
-                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+                Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
                 
             } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+                Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
                 
             } catch (Throwable th) {
-                Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+                Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
                 
             } finally {
                 if (toastIt) {
@@ -404,8 +402,7 @@ public class PreviewImageFragment extends SherlockFragment implements   FileFrag
             mLastRemoteOperation = new RemoveFileOperation( mFile,      // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
                                                             true, 
                                                             mStorageManager);
-            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-            mLastRemoteOperation.execute(wc, this, mHandler);
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
             
             getActivity().showDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
         }
@@ -557,24 +554,24 @@ public class PreviewImageFragment extends SherlockFragment implements   FileFrag
                 // really load the bitmap
                 options.inJustDecodeBounds = false; // the next decodeFile call will be real
                 result = BitmapFactory.decodeFile(storagePath, options);
-                //Log.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
+                //Log_OC.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
 
                 if (result == null) {
                     mErrorMessageId = R.string.preview_image_error_unknown_format;
-                    Log.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
+                    Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
                 }
                 
             } catch (OutOfMemoryError e) {
                 mErrorMessageId = R.string.preview_image_error_unknown_format;
-                Log.e(TAG, "Out of memory occured for file " + storagePath, e);
+                Log_OC.e(TAG, "Out of memory occured for file " + storagePath, e);
                     
             } catch (NoSuchFieldError e) {
                 mErrorMessageId = R.string.common_error_unknown;
-                Log.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
+                Log_OC.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
                     
             } catch (Throwable t) {
                 mErrorMessageId = R.string.common_error_unknown;
-                Log.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
+                Log_OC.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
                 
             }
             return result;

+ 0 - 8
src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java

@@ -16,7 +16,6 @@
  */
 package com.owncloud.android.ui.preview;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -24,16 +23,9 @@ import java.util.Set;
 import java.util.Vector;
 
 import android.accounts.Account;
-import android.os.Bundle;
-import android.os.Parcelable;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentStatePagerAdapter;
-import android.support.v4.app.FragmentTransaction;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.Log;
-import android.view.View;
 import android.view.ViewGroup;
 
 import com.owncloud.android.datamodel.DataStorageManager;

+ 14 - 18
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -40,7 +40,6 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.support.v4.app.FragmentTransaction;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -60,7 +59,6 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaControlView;
 import com.owncloud.android.media.MediaService;
 import com.owncloud.android.media.MediaServiceBinder;
-import com.owncloud.android.network.OwnCloudClientUtils;
 import com.owncloud.android.operations.OnRemoteOperationListener;
 import com.owncloud.android.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoteOperationResult;
@@ -73,7 +71,6 @@ import com.owncloud.android.ui.fragment.FileFragment;
 
 import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import eu.alefzero.webdav.WebdavClient;
 import eu.alefzero.webdav.WebdavUtils;
 
 /**
@@ -366,7 +363,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
          */
         @Override
         public void onPrepared(MediaPlayer vp) {
-            Log.e(TAG, "onPrepared");
+            Log_OC.e(TAG, "onPrepared");
             mVideoPreview.seekTo(mSavedPlaybackPosition);
             if (mAutoplay) { 
                 mVideoPreview.start();
@@ -386,7 +383,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
          */
         @Override
         public void onCompletion(MediaPlayer  mp) {
-            Log.e(TAG, "completed");
+            Log_OC.e(TAG, "completed");
             if (mp != null) {
                 mVideoPreview.seekTo(0);
                 // next lines are necessary to work around undesired video loops
@@ -461,7 +458,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
 
         mPrepared = false;
         if (mMediaServiceConnection != null) {
-            Log.d(TAG, "Unbinding from MediaService ...");
+            Log_OC.d(TAG, "Unbinding from MediaService ...");
             if (mMediaServiceBinder != null && mMediaController != null) {
                 mMediaServiceBinder.unregisterMediaController(mMediaController);
             }
@@ -509,7 +506,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
 
     private void playAudio() {
         if (!mMediaServiceBinder.isPlaying(mFile)) {
-            Log.d(TAG, "starting playback of " + mFile.getStoragePath());
+            Log_OC.d(TAG, "starting playback of " + mFile.getStoragePath());
             mMediaServiceBinder.start(mAccount, mFile, mAutoplay, mSavedPlaybackPosition);
             
         } else {
@@ -522,7 +519,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
 
 
     private void bindMediaService() {
-        Log.d(TAG, "Binding to MediaService...");
+        Log_OC.d(TAG, "Binding to MediaService...");
         if (mMediaServiceConnection == null) {
             mMediaServiceConnection = new MediaServiceConnection();
         }
@@ -539,16 +536,16 @@ public class PreviewMediaFragment extends SherlockFragment implements
         @Override
         public void onServiceConnected(ComponentName component, IBinder service) {
             if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
-                Log.d(TAG, "Media service connected");
+                Log_OC.d(TAG, "Media service connected");
                 mMediaServiceBinder = (MediaServiceBinder) service;
                 if (mMediaServiceBinder != null) {
                     prepareMediaController();
                     playAudio();    // do not wait for the touch of nobody to play audio
                     
-                    Log.d(TAG, "Successfully bound to MediaService, MediaController ready");
+                    Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready");
                     
                 } else {
-                    Log.e(TAG, "Unexpected response from MediaService while binding");
+                    Log_OC.e(TAG, "Unexpected response from MediaService while binding");
                 }
             }
         }
@@ -565,7 +562,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
         @Override
         public void onServiceDisconnected(ComponentName component) {
             if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
-                Log.e(TAG, "Media service suddenly disconnected");
+                Log_OC.e(TAG, "Media service suddenly disconnected");
                 if (mMediaController != null) {
                     mMediaController.setMediaPlayer(null);
                 } else {
@@ -597,7 +594,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
             startActivity(i);
             
         } catch (Throwable t) {
-            Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+            Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
             boolean toastIt = true; 
             String mimeType = "";
             try {
@@ -616,13 +613,13 @@ public class PreviewMediaFragment extends SherlockFragment implements
                 }
                 
             } catch (IndexOutOfBoundsException e) {
-                Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+                Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
                 
             } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+                Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
                 
             } catch (Throwable th) {
-                Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+                Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
                 
             } finally {
                 if (toastIt) {
@@ -662,8 +659,7 @@ public class PreviewMediaFragment extends SherlockFragment implements
             mLastRemoteOperation = new RemoveFileOperation( mFile,      // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
                                                             true, 
                                                             mStorageManager);
-            WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
-            mLastRemoteOperation.execute(wc, this, mHandler);
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
             
             boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
             getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);

+ 11 - 11
src/com/owncloud/android/ui/preview/PreviewVideoActivity.java

@@ -28,12 +28,12 @@ import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
 import android.net.Uri;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
 import com.owncloud.android.AccountUtils;
+import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaService;
@@ -84,7 +84,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log.e(TAG, "ACTIVITY\t\tonCreate");
+        Log_OC.e(TAG, "ACTIVITY\t\tonCreate");
         
         setContentView(R.layout.video_layout);
     
@@ -143,7 +143,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        Log.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
+        Log_OC.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
         outState.putParcelable(PreviewVideoActivity.EXTRA_FILE, mFile);
         outState.putParcelable(PreviewVideoActivity.EXTRA_ACCOUNT, mAccount);
         outState.putInt(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
@@ -153,7 +153,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
     
     @Override
     public void onBackPressed() {
-        Log.e(TAG, "ACTIVTIY\t\tonBackPressed");
+        Log_OC.e(TAG, "ACTIVTIY\t\tonBackPressed");
         Intent i = new Intent();
         i.putExtra(EXTRA_AUTOPLAY, mVideoPlayer.isPlaying());
         i.putExtra(EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
@@ -165,33 +165,33 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
     @Override
     public void onResume() {
         super.onResume();
-        Log.e(TAG, "ACTIVTIY\t\tonResume");
+        Log_OC.e(TAG, "ACTIVTIY\t\tonResume");
     }
 
     
     @Override
     public void onStart() {
         super.onStart();
-        Log.e(TAG, "ACTIVTIY\t\tonStart");
+        Log_OC.e(TAG, "ACTIVTIY\t\tonStart");
     }
     
     @Override
     public void onDestroy() {
         super.onDestroy();
-        Log.e(TAG, "ACTIVITY\t\tonDestroy");
+        Log_OC.e(TAG, "ACTIVITY\t\tonDestroy");
     }
     
     @Override
     public void onStop() {
         super.onStop();
-        Log.e(TAG, "ACTIVTIY\t\tonStop");
+        Log_OC.e(TAG, "ACTIVTIY\t\tonStop");
     }
     
     
     @Override
     public void onPause() {
         super.onPause();
-        Log.e(TAG, "ACTIVTIY\t\tonPause");
+        Log_OC.e(TAG, "ACTIVTIY\t\tonPause");
     }
     
     
@@ -204,7 +204,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
      */
     @Override
     public void onPrepared(MediaPlayer mp) {
-        Log.e(TAG, "ACTIVITY\t\tonPrepare");
+        Log_OC.e(TAG, "ACTIVITY\t\tonPrepare");
         mVideoPlayer.seekTo(mSavedPlaybackPosition);
         if (mAutoplay) { 
             mVideoPlayer.start();
@@ -235,7 +235,7 @@ public class PreviewVideoActivity extends Activity implements OnCompletionListen
      */
     @Override
     public boolean onError(MediaPlayer mp, int what, int extra) {
-        Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
+        Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
         
         if (mMediaController != null) {
             mMediaController.hide();

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

@@ -24,7 +24,6 @@ import android.content.Context;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.StatFs;
-import android.util.Log;
 
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;

+ 33 - 184
src/eu/alefzero/webdav/WebdavClient.java

@@ -15,6 +15,7 @@
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+
 package eu.alefzero.webdav;
 
 import java.io.BufferedInputStream;
@@ -22,14 +23,20 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HostConfiguration;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpConnectionManager;
 import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpState;
 import org.apache.commons.httpclient.HttpVersion;
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthPolicy;
 import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.HeadMethod;
@@ -39,12 +46,13 @@ 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 com.owncloud.android.network.BearerAuthScheme;
+import com.owncloud.android.network.BearerCredentials;
+
 import android.net.Uri;
-import android.util.Log;
 
 public class WebdavClient extends HttpClient {
     private Uri mUri;
@@ -65,176 +73,32 @@ public class WebdavClient extends HttpClient {
         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));
+    public void setBearerCredentials(String accessToken) {
+        AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
         
-        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;
+        List<String> authPrefs = new ArrayList<String>(1);
+        authPrefs.add(BearerAuthScheme.AUTH_POLICY);
+        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
+        
+        mCredentials = new BearerCredentials(accessToken);
+        getState().setCredentials(AuthScope.ANY, mCredentials);
     }
 
-    /**
-     * 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;
+    public void setBasicCredentials(String username, String password) {
+        List<String> authPrefs = new ArrayList<String>(1);
+        authPrefs.add(AuthPolicy.BASIC);
+        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);        
+        
+        getParams().setAuthenticationPreemptive(true);
+        mCredentials = new UsernamePasswordCredentials(username, password);
+        getState().setCredentials(AuthScope.ANY, mCredentials);
     }
     
-    
     /**
      * Check if a file exists in the OC server
      * 
+     * TODO replace with ExistenceOperation
+     * 
      * @return              'true' if the file exists; 'false' it doesn't exist
      * @throws  Exception   When the existence could not be determined
      */
@@ -250,7 +114,7 @@ public class WebdavClient extends HttpClient {
             head.releaseConnection();    // let the connection available for other methods
         }
     }
-
+    
     /**
      * Requests the received method with the received timeout (milliseconds).
      * 
@@ -299,25 +163,6 @@ public class WebdavClient extends HttpClient {
         }
     }
 
-    /**
-     * 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.
      */
@@ -338,4 +183,8 @@ public class WebdavClient extends HttpClient {
         return mUri;
     }
 
+    public final Credentials getCredentials() {
+        return mCredentials;
+    }
+
 }

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

@@ -26,7 +26,6 @@ import org.apache.jackrabbit.webdav.property.DavPropertySet;
 import com.owncloud.android.Log_OC;
 
 import android.net.Uri;
-import android.util.Log;
 
 public class WebdavEntry {
     private String mName, mPath, mUri, mContentType;