Merge branch 'develop' into refactor_remote_operation_to_create_folder
authorDavid A. Velasco <dvelasco@solidgear.es>
Mon, 18 Nov 2013 13:10:16 +0000 (14:10 +0100)
committerDavid A. Velasco <dvelasco@solidgear.es>
Mon, 18 Nov 2013 13:10:16 +0000 (14:10 +0100)
158 files changed:
.gitignore
AndroidManifest.xml
SETUP.md
oc_framework-test-project/.classpath [new file with mode: 0644]
oc_framework-test-project/.project [new file with mode: 0644]
oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
oc_framework-test-project/AndroidManifest.xml [new file with mode: 0644]
oc_framework-test-project/ic_launcher-web.png [new file with mode: 0644]
oc_framework-test-project/libs/android-support-v4.jar [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/.classpath [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/.project [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/project.properties [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/res/values/strings.xml [new file with mode: 0644]
oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java [new file with mode: 0644]
oc_framework-test-project/project.properties [new file with mode: 0644]
oc_framework-test-project/res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png [new file with mode: 0644]
oc_framework-test-project/res/layout/activity_test.xml [new file with mode: 0644]
oc_framework-test-project/res/menu/test.xml [new file with mode: 0644]
oc_framework-test-project/res/values-sw600dp/dimens.xml [new file with mode: 0644]
oc_framework-test-project/res/values-sw720dp-land/dimens.xml [new file with mode: 0644]
oc_framework-test-project/res/values-v11/styles.xml [new file with mode: 0644]
oc_framework-test-project/res/values-v14/styles.xml [new file with mode: 0644]
oc_framework-test-project/res/values/dimens.xml [new file with mode: 0644]
oc_framework-test-project/res/values/strings.xml [new file with mode: 0644]
oc_framework-test-project/res/values/styles.xml [new file with mode: 0644]
oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java [new file with mode: 0644]
oc_framework/.classpath [new file with mode: 0644]
oc_framework/.project [new file with mode: 0644]
oc_framework/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
oc_framework/AndroidManifest.xml [new file with mode: 0644]
oc_framework/build.xml [new file with mode: 0644]
oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar [new file with mode: 0644]
oc_framework/project.properties [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java [new file with mode: 0644]
oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java [new file with mode: 0644]
project.properties
res/values/strings.xml
setup_env.bat
setup_env.sh
src/com/owncloud/android/DisplayUtils.java [deleted file]
src/com/owncloud/android/Log_OC.java [deleted file]
src/com/owncloud/android/MainApp.java
src/com/owncloud/android/OwnCloudSession.java [deleted file]
src/com/owncloud/android/Uploader.java [deleted file]
src/com/owncloud/android/authentication/AccountAuthenticator.java
src/com/owncloud/android/authentication/AccountUtils.java
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/authentication/SsoWebViewClient.java
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/db/DbHandler.java
src/com/owncloud/android/files/BootupBroadcastReceiver.java
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
src/com/owncloud/android/files/OwnCloudFileObserver.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileObserverService.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/media/MediaService.java
src/com/owncloud/android/media/MediaServiceBinder.java
src/com/owncloud/android/network/AdvancedSslSocketFactory.java [deleted file]
src/com/owncloud/android/network/AdvancedX509TrustManager.java [deleted file]
src/com/owncloud/android/network/BearerAuthScheme.java [deleted file]
src/com/owncloud/android/network/BearerCredentials.java [deleted file]
src/com/owncloud/android/network/CertificateCombinedException.java [deleted file]
src/com/owncloud/android/network/OwnCloudClientUtils.java [deleted file]
src/com/owncloud/android/network/ProgressiveDataTransferer.java [deleted file]
src/com/owncloud/android/operations/ChunkedUploadFileOperation.java
src/com/owncloud/android/operations/CreateFolderOperation.java
src/com/owncloud/android/operations/DownloadFileOperation.java
src/com/owncloud/android/operations/ExistenceCheckOperation.java
src/com/owncloud/android/operations/OAuth2GetAccessToken.java
src/com/owncloud/android/operations/OnRemoteOperationListener.java [deleted file]
src/com/owncloud/android/operations/OperationCancelledException.java [deleted file]
src/com/owncloud/android/operations/OwnCloudServerCheckOperation.java
src/com/owncloud/android/operations/RemoteOperation.java [deleted file]
src/com/owncloud/android/operations/RemoteOperationResult.java [deleted file]
src/com/owncloud/android/operations/RemoveFileOperation.java
src/com/owncloud/android/operations/RenameFileOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/SynchronizeFolderOperation.java
src/com/owncloud/android/operations/UpdateOCVersionOperation.java
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/providers/FileContentProvider.java
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java
src/com/owncloud/android/syncadapter/ContactSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/syncadapter/FileSyncService.java
src/com/owncloud/android/ui/activity/AccountSelectActivity.java
src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java
src/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/InstantUploadActivity.java
src/com/owncloud/android/ui/activity/Preferences.java
src/com/owncloud/android/ui/activity/UploadFilesActivity.java
src/com/owncloud/android/ui/activity/Uploader.java [new file with mode: 0644]
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
src/com/owncloud/android/ui/dialog/EditNameDialog.java
src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java
src/com/owncloud/android/ui/dialog/SslValidatorDialog.java
src/com/owncloud/android/ui/fragment/ConfirmationDialogFragment.java
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/FileDownloadFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java
src/com/owncloud/android/ui/preview/PreviewVideoActivity.java
src/com/owncloud/android/utils/DisplayUtils.java [new file with mode: 0644]
src/com/owncloud/android/utils/FileStorageUtils.java
src/com/owncloud/android/utils/Log_OC.java [new file with mode: 0644]
src/com/owncloud/android/utils/OwnCloudSession.java [new file with mode: 0644]
src/com/owncloud/android/utils/OwnCloudVersion.java [deleted file]
src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java [deleted file]
src/eu/alefzero/webdav/FileRequestEntity.java [deleted file]
src/eu/alefzero/webdav/OnDatatransferProgressListener.java [deleted file]
src/eu/alefzero/webdav/WebdavClient.java [deleted file]
src/eu/alefzero/webdav/WebdavEntry.java [deleted file]
src/eu/alefzero/webdav/WebdavUtils.java [deleted file]
tests/.classpath
tests/ant.properties [new file with mode: 0644]
tests/build.xml [new file with mode: 0644]
tests/project.properties
tests/src/com/owncloud/android/test/AccountUtilsTest.java

index ac30011..9b9bd8e 100644 (file)
@@ -13,18 +13,22 @@ bin/
 gen/
 target/
 
-# Local configuration file (sdk path, etc)
+# Local configuration files (sdk path, etc)
 local.properties
+oc_workaround/local.properties
+oc_framework/local.properties
+oc_framework-test-project/local.properties
+tests/local.properties
 
 # Mac .DS_Store files
 .DS_Store
 
-# These files are created automatically by Eclipse:
-tests/proguard-project.txt
-tests/project.properties
-tests/ant.properties
-tests/build.xml
+# Proguard README
 proguard-project.txt
+oc_workaround/proguard-project.txt
+oc_framework/proguard-project.txt
+oc_framework-test-project/proguard-project.txt
+tests/proguard-project.txt
 
 # Should not be commited inside this repo:
 actionbarsherlock/
\ No newline at end of file
index f1900f8..bdd792b 100644 (file)
@@ -63,7 +63,7 @@
                <activity android:name=".ui.activity.InstantUploadActivity">
         </activity>
         <activity android:name=".ui.activity.FailedUploadActivity" android:theme="@android:style/Theme.Dialog" android:excludeFromRecents="true"/>
-        <activity android:name=".Uploader" >
+        <activity android:name=".ui.activity.Uploader" >
             <intent-filter>
                 <action android:name="android.intent.action.SEND" >
                 </action>
index 6e7b7f6..6470157 100644 (file)
--- a/SETUP.md
+++ b/SETUP.md
@@ -1,56 +1,73 @@
   
-  If you want to start help developing ownCloud please follow the [contribution guidlines][0] and observe these instructions:
+If you want to start help developing ownCloud please follow the [contribution guidelines][0] and observe these instructions:
   
-  1. Fork and download android/develop repository:
-
-  -  NOTE: You must have git in your enviroment path
-  -  Navigate to https://github.com/owncloud/android, click fork.
-  -  Clone your new repo: "git clone git@github.com:YOURGITHUBNAME/android.git"
-  -  "cd android"
-  -  Checkout remote develop branch: "git checkout -b develop remotes/origin/develop"
-  -  Pull changes from your develop branch: "git pull origin develop"
-  -  Make sure to get the latest changes from official android/develop branch:
-  -  Make official owncloud repo known as upstream: "git remote add upstream git@github.com:owncloud/android.git"
-  -  Pull latest changes from upstream: "git pull upstream develop"
-
-  2. Building with console/maven:
-
-  -  OPTIONAL, CONTINUE WITH STEP 3 IF NOT REQUIRED!
-  -  NOTE: You must have mvn in your enviroment path
-  -  Download/install Android plugin for Maven, then build ownCloud with mvn:
-  -  "cd .."
-  -  "git clone https://github.com/mosabua/maven-android-sdk-deployer.git"
-  -  "cd maven-android-sdk-deployer"
-  -  "mvn -pl com.simpligility.android.sdk-deployer:android-17 -am install"
-  -  "cd ../android"
-  -  Now you can create APK using "mvn package"
-
-  3. Building with Eclipse:
-
-  -  NOTE: You must have android/tools, and 'platforms-tools' in your enviroment path
-  -  Prepare building with Eclipse:
-  -  "setup_env.bat" or "./setup_env.sh"
-  -  Open Eclipse and create new "Android Project from Existing Code". As root choose android/actionbarsherlock/library
-  -  Increase Android API level until project compiles. 14 should work. 
-  -  Clean project and compile.
-  -  Make sure android/actionbarsherlock/library/bin/library.jar was created!
-  -  Import OwnCloud Android project.
-  -  Increase Android API level to 17.
-  -  Clean project and compile.
-  -  After those actions you should be good to go. HAVE FUN!
-  -  NOTE: Even though API level is set to 17, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8.
-
-  4. Create pull request:
+### 1. Fork and download android/develop repository:
+
+NOTE: You must have git in your environment path variable to perform the next operations.
+  
+* Navigate to https://github.com/owncloud/android, click fork.
+* Clone your new repo: "git clone git@github.com:YOURGITHUBNAME/android.git"
+* Move to the project folder with "cd android"
+* Checkout remote develop branch: "git checkout -b develop remotes/origin/develop"
+* Pull changes from your develop branch: "git pull origin develop"
+* Make official ownCloud repo known as upstream: "git remote add upstream git@github.com:owncloud/android.git"
+* Make sure to get the latest changes from official android/develop branch: "git pull upstream develop"
+
+At this point you can continue using different tools to build the project. Section 2, 3 and 4 describe some of the existing alternatives.  
+
+### 2. Building with Ant:
+  
+NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable.
+
+* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" .
+* Run "ant clean" .
+* Run "ant debug" to generate a debuggable version of the ownCkoud app.
+
+### 3. Building with console/maven:
+
+NOTE: You must have mvn in your environment path
+
+* Download/install Android plugin for Maven, then build ownCloud with mvn:
+* "cd .."
+* "git clone https://github.com/mosabua/maven-android-sdk-deployer.git"
+* "cd maven-android-sdk-deployer"
+* "mvn -pl com.simpligility.android.sdk-deployer:android-17 -am install"
+* "cd ../android"
+* Now you can create APK using "mvn package"
+
+### 4. Building with Eclipse:
+
+NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable.
+
+* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" .
+* Open Eclipse and create new "Android Project from Existing Code". Choose android/actionbarsherlock/library as root.
+* Clean project and compile.
+* If any error appear, check the project properties; in the 'Android' section, API Level should be greater or equal than 14.
+* Make sure android/actionbarsherlock/library/bin/library.jar was created.
+* Create a new "Android Project from Existing Code". Choose android/oc_framework/library as root.
+* Clean project and compile.
+* If any error appear, check the project properties; in the 'Android' section, API Level should be 19 or greater.
+* Make sure android/oc_framework/bin/classes.jar was created.  
+* Import ownCloud Android project.
+* Clean project and compile.
+* If any error appears, check the project properties; in the 'Android' section:
+  - API Level should be 19 or greater.
+  - Two library projects should appear referred in the bottom square: actionbarsherlock/library and oc_framework. Add them if needed. 
+* After those actions you should be good to go. HAVE FUN!
+
+NOTE: Even though API level is set to 19, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8.
+
+### 5. Create pull request:
   
-  -  NOTE: You must sign the [Contributor Agreement][1] before your changes can be accepted!
-  -  Commit your changes locally: "git commit -a"
-  -  Push your changes to your Github repo: "git push"
-  -  Browse to https://github.com/YOURGITHUBNAME/android/pulls and issue pull request
-  -  Click "Edit" and set "base:develop"
-  -  Again, click "Edit" and set "compare:develop"
-  -  Enter description and send pull request.
+NOTE: You must sign the [Contributor Agreement][1] before your changes can be accepted!
+
+* Commit your changes locally: "git commit -a"
+* Push your changes to your Github repo: "git push"
+* Browse to https://github.com/YOURGITHUBNAME/android/pulls and issue pull request
+* Click "Edit" and set "base:develop"
+* Again, click "Edit" and set "compare:develop"
+* Enter description and send pull request.
 
 
 [0]: https://github.com/owncloud/android/blob/master/CONTRIBUTING.md
 [1]: http://owncloud.org/about/contributor-agreement/
-
diff --git a/oc_framework-test-project/.classpath b/oc_framework-test-project/.classpath
new file mode 100644 (file)
index 0000000..d3d9f2d
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry exported="true" kind="lib" path="/oc_framework/bin/oc_framework.jar"/>
+       <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/oc_framework-test-project/.project b/oc_framework-test-project/.project
new file mode 100644 (file)
index 0000000..8c7df64
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>oc_framework-test-project</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs b/oc_framework-test-project/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..b080d2d
--- /dev/null
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework-test-project/AndroidManifest.xml b/oc_framework-test-project/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..c913bf0
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.owncloud.android.oc_framework_test_project"
+    android:versionCode="1"
+    android:versionName="1.0" >
+    
+    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.INTERNET"/>
+        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="com.owncloud.android.oc_framework_test_project.TestActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/oc_framework-test-project/ic_launcher-web.png b/oc_framework-test-project/ic_launcher-web.png
new file mode 100644 (file)
index 0000000..a18cbb4
Binary files /dev/null and b/oc_framework-test-project/ic_launcher-web.png differ
diff --git a/oc_framework-test-project/libs/android-support-v4.jar b/oc_framework-test-project/libs/android-support-v4.jar
new file mode 100644 (file)
index 0000000..9056828
Binary files /dev/null and b/oc_framework-test-project/libs/android-support-v4.jar differ
diff --git a/oc_framework-test-project/oc_framework-test-test/.classpath b/oc_framework-test-project/oc_framework-test-test/.classpath
new file mode 100644 (file)
index 0000000..49a8ebc
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry combineaccessrules="false" kind="src" path="/oc_framework-test-project"/>
+       <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/oc_framework-test-project/oc_framework-test-test/.project b/oc_framework-test-project/oc_framework-test-test/.project
new file mode 100644 (file)
index 0000000..c490827
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>oc_framework-test</name>
+       <comment></comment>
+       <projects>
+               <project>oc_framework-test-project</project>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs b/oc_framework-test-project/oc_framework-test-test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..b080d2d
--- /dev/null
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml b/oc_framework-test-project/oc_framework-test-test/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..294f271
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.owncloud.android.oc_framework_test_project.test"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="8" />
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:label="Tests for com.owncloud.android.oc_framework_test_project"
+        android:targetPackage="com.owncloud.android.oc_framework_test_project" />
+
+</manifest>
\ No newline at end of file
diff --git a/oc_framework-test-project/oc_framework-test-test/project.properties b/oc_framework-test-project/oc_framework-test-test/project.properties
new file mode 100644 (file)
index 0000000..4ab1256
--- /dev/null
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..96a442e
Binary files /dev/null and b/oc_framework-test-project/oc_framework-test-test/res/drawable-hdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..9923872
Binary files /dev/null and b/oc_framework-test-project/oc_framework-test-test/res/drawable-ldpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..359047d
Binary files /dev/null and b/oc_framework-test-project/oc_framework-test-test/res/drawable-mdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png b/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..71c6d76
Binary files /dev/null and b/oc_framework-test-project/oc_framework-test-test/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/oc_framework-test-test/res/values/strings.xml b/oc_framework-test-project/oc_framework-test-test/res/values/strings.xml
new file mode 100644 (file)
index 0000000..657f31d
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">Oc_framework-testTest</string>
+
+</resources>
diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java
new file mode 100644 (file)
index 0000000..0c4b8ef
--- /dev/null
@@ -0,0 +1,96 @@
+package com.owncloud.android.oc_framework_test_project.test;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework_test_project.TestActivity;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Class to test Create Folder Operation
+ * @author masensio
+ *
+ */
+public class CreateFolderTest extends ActivityInstrumentationTestCase2<TestActivity> {
+
+       private TestActivity mActivity;
+       private String mCurrentDate;
+       
+       public CreateFolderTest() {
+           super(TestActivity.class);
+          
+               SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
+               mCurrentDate = sdf.format(new Date());
+       }
+       
+       @Override
+         protected void setUp() throws Exception {
+           super.setUp();
+           setActivityInitialTouchMode(false);
+           mActivity = getActivity();
+       }
+       
+       /**
+        * Test Create Folder
+        */
+       public void testCreateFolder() {
+
+               String remotePath = "/testCreateFolder" + mCurrentDate;
+               boolean createFullPath = true;
+               
+               RemoteOperationResult result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.isSuccess() || result.getCode() == ResultCode.TIMEOUT);
+               
+               // Create Subfolder
+               remotePath = "/testCreateFolder" + mCurrentDate + "/" + "testCreateFolder" + mCurrentDate;
+               createFullPath = true;
+               
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.isSuccess() || result.getCode() == ResultCode.TIMEOUT);
+       }
+       
+       
+       /**
+        * Test to Create Folder with special characters
+        */
+       public void testCreateFolderSpecialCharacters() {               
+               boolean createFullPath = true;
+               
+               String remotePath = "/testSpecialCharacters_\\" + mCurrentDate;
+               RemoteOperationResult result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_<" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_>" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_:" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_\"" + mCurrentDate;                
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_|" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_?" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+               
+               remotePath = "/testSpecialCharacters_*" + mCurrentDate;         
+               result =  mActivity.createFolder(remotePath, createFullPath);
+               assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
+       }
+
+
+}
diff --git a/oc_framework-test-project/project.properties b/oc_framework-test-project/project.properties
new file mode 100644 (file)
index 0000000..153d36b
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
+android.library.reference.1=../oc_framework
diff --git a/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..288b665
Binary files /dev/null and b/oc_framework-test-project/res/drawable-hdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..6ae570b
Binary files /dev/null and b/oc_framework-test-project/res/drawable-mdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..d4fb7cd
Binary files /dev/null and b/oc_framework-test-project/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png b/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..85a6081
Binary files /dev/null and b/oc_framework-test-project/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/oc_framework-test-project/res/layout/activity_test.xml b/oc_framework-test-project/res/layout/activity_test.xml
new file mode 100644 (file)
index 0000000..42c4fbd
--- /dev/null
@@ -0,0 +1,16 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".TestActivity" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</RelativeLayout>
diff --git a/oc_framework-test-project/res/menu/test.xml b/oc_framework-test-project/res/menu/test.xml
new file mode 100644 (file)
index 0000000..c002028
--- /dev/null
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
diff --git a/oc_framework-test-project/res/values-sw600dp/dimens.xml b/oc_framework-test-project/res/values-sw600dp/dimens.xml
new file mode 100644 (file)
index 0000000..44f01db
--- /dev/null
@@ -0,0 +1,8 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw600dp devices (e.g. 7" tablets) here.
+    -->
+
+</resources>
diff --git a/oc_framework-test-project/res/values-sw720dp-land/dimens.xml b/oc_framework-test-project/res/values-sw720dp-land/dimens.xml
new file mode 100644 (file)
index 0000000..61e3fa8
--- /dev/null
@@ -0,0 +1,9 @@
+<resources>
+
+    <!--
+         Customize dimensions originally defined in res/values/dimens.xml (such as
+         screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
+    -->
+    <dimen name="activity_horizontal_margin">128dp</dimen>
+
+</resources>
diff --git a/oc_framework-test-project/res/values-v11/styles.xml b/oc_framework-test-project/res/values-v11/styles.xml
new file mode 100644 (file)
index 0000000..3c02242
--- /dev/null
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/oc_framework-test-project/res/values-v14/styles.xml b/oc_framework-test-project/res/values-v14/styles.xml
new file mode 100644 (file)
index 0000000..a91fd03
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/oc_framework-test-project/res/values/dimens.xml b/oc_framework-test-project/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..55c1e59
--- /dev/null
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/oc_framework-test-project/res/values/strings.xml b/oc_framework-test-project/res/values/strings.xml
new file mode 100644 (file)
index 0000000..e50b40d
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">oc_framework-test-project</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
diff --git a/oc_framework-test-project/res/values/styles.xml b/oc_framework-test-project/res/values/styles.xml
new file mode 100644 (file)
index 0000000..6ce89c7
--- /dev/null
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java b/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java
new file mode 100644 (file)
index 0000000..082557d
--- /dev/null
@@ -0,0 +1,102 @@
+package com.owncloud.android.oc_framework_test_project;
+
+import java.io.IOException;
+
+import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
+
+import android.os.Bundle;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Activity;
+import android.util.Log;
+import android.view.Menu;
+
+/**
+ * Activity to test OC framework
+ * @author masensio
+ *
+ */
+public class TestActivity extends Activity {
+       
+       private static final String TAG = "TestActivity";
+       
+       private Account mAccount = null;
+       private WebdavClient mClient;
+       
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+               setContentView(R.layout.activity_test);
+               
+               // This account must exists on the simulator / device
+               String accountHost = "beta.owncloud.com";
+               String accountUser = "testandroid";
+               String accountName = accountUser + "@"+ accountHost;
+               String accountPass = "testandroid";
+               String accountType = "owncloud";        
+
+               AccountManager am = AccountManager.get(this);
+               
+               Account[] ocAccounts = am.getAccountsByType(accountType);
+        for (Account ac : ocAccounts) {
+           if (ac.name.equals(accountName)) {
+                  mAccount = ac;
+                  break;
+            }
+        }
+
+//        if (mAccount == null) {
+//                     mAccount = new Account(accountName, accountType);       
+//                     am.addAccountExplicitly(mAccount, accountPass, null);
+//             am.setUserData(mAccount, "oc_version",    "5.0.14");
+//             am.setUserData(mAccount, "oc_base_url",   "http://beta.owncloud.com/owncloud");
+//        } else {
+            Log.d(TAG, "oc_version --->"+ am.getUserData(mAccount, "oc_version") );
+            Log.d(TAG, "oc_base_url --->"+ am.getUserData(mAccount, "oc_base_url") );
+//        }
+               
+        
+               try {
+                       mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, this.getApplicationContext());
+               } catch (OperationCanceledException e) {
+                       Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
+                       e.printStackTrace();
+               } catch (AuthenticatorException e) {
+                       Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
+                       e.printStackTrace();
+               } catch (AccountNotFoundException e) {
+                       Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
+                       e.printStackTrace();
+               } catch (IOException e) {
+                       Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
+                       e.printStackTrace();
+               }
+       }
+
+       @Override
+       public boolean onCreateOptionsMenu(Menu menu) {
+               // Inflate the menu; this adds items to the action bar if it is present.
+               getMenuInflater().inflate(R.menu.test, menu);
+               return true;
+       }
+
+       /**
+        * Access to the library method to Create a Folder
+        * @param remotePath
+        * @param createFullPath
+        * @return
+        */
+       public RemoteOperationResult createFolder(String remotePath, boolean createFullPath) {
+               
+               CreateRemoteFolderOperation createOperation = new CreateRemoteFolderOperation(remotePath, createFullPath);
+               RemoteOperationResult result =  createOperation.execute(mClient);
+               
+               return result;
+       }
+}
diff --git a/oc_framework/.classpath b/oc_framework/.classpath
new file mode 100644 (file)
index 0000000..5176974
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/oc_framework/.project b/oc_framework/.project
new file mode 100644 (file)
index 0000000..18812a0
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>oc_framework</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/oc_framework/.settings/org.eclipse.jdt.core.prefs b/oc_framework/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..b080d2d
--- /dev/null
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/oc_framework/AndroidManifest.xml b/oc_framework/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..836b4a0
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.owncloud.android.oc_framework"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="19" />
+
+</manifest>
diff --git a/oc_framework/build.xml b/oc_framework/build.xml
new file mode 100644 (file)
index 0000000..6b112f4
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="ownCloudFramework" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar b/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar
new file mode 100644 (file)
index 0000000..2dd374f
Binary files /dev/null and b/oc_framework/libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar differ
diff --git a/oc_framework/project.properties b/oc_framework/project.properties
new file mode 100644 (file)
index 0000000..91d2b02
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
+android.library=true
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountTypeUtils.java
new file mode 100644 (file)
index 0000000..2c9db68
--- /dev/null
@@ -0,0 +1,43 @@
+/* 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.oc_framework.accounts;
+
+/**
+ * @author masensio
+ * @author David A. Velasco
+ */
+public class AccountTypeUtils {
+
+    public static String getAuthTokenTypePass(String accountType) {
+        return accountType + ".password";
+    }
+    
+    public static String getAuthTokenTypeAccessToken(String accountType) {
+        return accountType  + ".oauth2.access_token";
+    }
+    
+    public static String getAuthTokenTypeRefreshToken(String accountType) {
+        return accountType  + ".oauth2.refresh_token";
+    }
+    
+    public static String getAuthTokenTypeSamlSessionCookie(String accountType) {
+        return accountType  +  ".saml.web_sso.session_cookie";
+    }
+    
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/AccountUtils.java
new file mode 100644 (file)
index 0000000..810f3eb
--- /dev/null
@@ -0,0 +1,129 @@
+/* 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.oc_framework.accounts;
+
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountsException;
+import android.content.Context;
+
+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";
+    private static final String SAML_SSO_PATH = "/remote.php/webdav";
+    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";
+
+    /**
+     * 
+     * @param version version of owncloud
+     * @return webdav path for given OC version, null if OC version unknown
+     */
+    public static String getWebdavPath(OwnCloudVersion version, boolean supportsOAuth, boolean supportsSamlSso) {
+        if (version != null) {
+            if (supportsOAuth) {
+                return ODAV_PATH;
+            }
+            if (supportsSamlSso) {
+                return SAML_SSO_PATH;
+            }
+            if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)
+                return WEBDAV_PATH_4_0;
+            if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0
+                    || version.compareTo(OwnCloudVersion.owncloud_v2) >= 0)
+                return WEBDAV_PATH_2_0;
+            if (version.compareTo(OwnCloudVersion.owncloud_v1) >= 0)
+                return WEBDAV_PATH_1_2;
+        }
+        return null;
+    }
+    
+//    /**
+//     * Returns the proper URL path to access the WebDAV interface of an ownCloud server,
+//     * according to its version and the authorization method used.
+//     * 
+//     * @param   version         Version of ownCloud server.
+//     * @param   authTokenType   Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in {@link AccountAuthenticator}. 
+//     * @return                  WebDAV path for given OC version and authorization method, null if OC version is unknown.
+//     */
+//    public static String getWebdavPath(OwnCloudVersion version, String authTokenType) {
+//        if (version != null) {
+//            if (MainApp.getAuthTokenTypeAccessToken().equals(authTokenType)) {
+//                return ODAV_PATH;
+//            }
+//            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(authTokenType)) {
+//                return SAML_SSO_PATH;
+//            }
+//            if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)
+//                return WEBDAV_PATH_4_0;
+//            if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0
+//                    || version.compareTo(OwnCloudVersion.owncloud_v2) >= 0)
+//                return WEBDAV_PATH_2_0;
+//            if (version.compareTo(OwnCloudVersion.owncloud_v1) >= 0)
+//                return WEBDAV_PATH_1_2;
+//        }
+//        return null;
+//    }
+    
+    /**
+     * Constructs full url to host and webdav resource basing on host version
+     * @param context
+     * @param account
+     * @return url or null on failure
+     * @throws AccountNotFoundException     When 'account' is unknown for the AccountManager
+     */
+    public static String constructFullURLForAccount(Context context, Account account) throws AccountNotFoundException {
+        AccountManager ama = AccountManager.get(context);
+        String baseurl = ama.getUserData(account, OwnCloudAccount.Constants.KEY_OC_BASE_URL);
+        String strver  = ama.getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION);
+        boolean supportsOAuth = (ama.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null);
+        boolean supportsSamlSso = (ama.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null);
+        OwnCloudVersion ver = new OwnCloudVersion(strver);
+        String webdavpath = getWebdavPath(ver, supportsOAuth, supportsSamlSso);
+
+        if (baseurl == null || webdavpath == null) 
+            throw new AccountNotFoundException(account, "Account not found", null);
+        
+        return baseurl + webdavpath;
+    }
+    
+    
+    public static class AccountNotFoundException extends AccountsException {
+        
+        /** Generated - should be refreshed every time the class changes!! */
+        private static final long serialVersionUID = -9013287181793186830L;
+        
+        private Account mFailedAccount; 
+                
+        public AccountNotFoundException(Account failedAccount, String message, Throwable cause) {
+            super(message, cause);
+            mFailedAccount = failedAccount;
+        }
+        
+        public Account getFailedAccount() {
+            return mFailedAccount;
+        }
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java b/oc_framework/src/com/owncloud/android/oc_framework/accounts/OwnCloudAccount.java
new file mode 100644 (file)
index 0000000..73fdb65
--- /dev/null
@@ -0,0 +1,105 @@
+/* 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.oc_framework.accounts;
+
+import android.accounts.Account;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Account with extra information specific for ownCloud accounts.
+ * 
+ * TODO integrate in the main app
+ * 
+ * @author David A. Velasco
+ */
+public class OwnCloudAccount extends Account {
+
+       public static class Constants {
+           /**
+            * 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.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
+            * {@link com.owncloud.android.oc_framework.utils.utils.OwnCloudVersion}
+            * 
+            * @deprecated
+            */
+           public static final String KEY_OC_URL = "oc_url";
+           /**
+            * Version should be 3 numbers separated by dot so it can be parsed by
+            * {@link com.owncloud.android.oc_framework.utils.utils.OwnCloudVersion}
+            */
+           public static final String KEY_OC_VERSION = "oc_version";
+           /**
+            * Base url should point to owncloud installation without trailing / ie:
+            * http://server/path or https://owncloud.server
+            */
+           public static final String KEY_OC_BASE_URL = "oc_base_url";
+           /**
+            * Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
+            */
+           public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
+           /**
+            * Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
+            */
+           public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
+       }
+       
+       private String mAuthTokenType;
+
+       public OwnCloudAccount(String name, String type, String authTokenType) {
+               super(name, type);
+               // TODO validate authTokentype as supported
+               mAuthTokenType = authTokenType;
+       }
+       
+    /**
+     * Reconstruct from parcel
+     * 
+     * @param source The source parcel
+     */
+       public OwnCloudAccount(Parcel source) {
+               super(source);
+        mAuthTokenType = source.readString();
+       }
+       
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+       super.writeToParcel(dest, flags);
+        dest.writeString(mAuthTokenType);
+    }
+       
+       
+       public String getAuthTokenType() {
+               return mAuthTokenType;
+       }
+
+       
+    public static final Parcelable.Creator<OwnCloudAccount> CREATOR = new Parcelable.Creator<OwnCloudAccount>() {
+        @Override
+        public OwnCloudAccount createFromParcel(Parcel source) {
+            return new OwnCloudAccount(source);
+        }
+
+        @Override
+        public OwnCloudAccount [] newArray(int size) {
+            return new OwnCloudAccount[size];
+        }
+    };
+       
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java b/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedSslSocketFactory.java
new file mode 100644 (file)
index 0000000..e24fa36
--- /dev/null
@@ -0,0 +1,242 @@
+/* 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.oc_framework.network;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.security.cert.X509Certificate;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+
+import android.util.Log;
+
+
+
+/**
+ * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with 
+ * a custom SSLContext and an optional Hostname Verifier.
+ * 
+ * @author David A. Velasco
+ */
+
+public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
+
+    private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
+    
+    private SSLContext mSslContext = null;
+    private AdvancedX509TrustManager mTrustManager = null;
+    private X509HostnameVerifier mHostnameVerifier = null;
+
+    public SSLContext getSslContext() {
+        return mSslContext;
+    }
+    
+    /**
+     * Constructor for AdvancedSSLProtocolSocketFactory.
+     */
+    public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) {
+        if (sslContext == null)
+            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
+        if (trustManager == null)
+            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null Trust Manager");
+        mSslContext = sslContext;
+        mTrustManager = trustManager;
+        mHostnameVerifier = hostnameVerifier;
+    }
+
+    /**
+     * @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
+     */
+    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
+        Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
+        verifyPeerIdentity(host, port, socket);
+        return socket;
+    }
+
+    
+    /**
+     * Attempts to get a new socket connection to the given host within the
+     * given time limit.
+     * 
+     * @param host the host name/IP
+     * @param port the port on the host
+     * @param clientHost the local host name/IP to bind the socket to
+     * @param clientPort the port on the local machine
+     * @param params {@link HttpConnectionParams Http connection parameters}
+     * 
+     * @return Socket a new socket
+     * 
+     * @throws IOException if an I/O error occurs while creating the socket
+     * @throws UnknownHostException if the IP address of the host cannot be
+     *             determined
+     */
+    public Socket createSocket(final String host, final int port,
+            final InetAddress localAddress, final int localPort,
+            final HttpConnectionParams params) throws IOException,
+            UnknownHostException, ConnectTimeoutException {
+        Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
+        if (params == null) {
+            throw new IllegalArgumentException("Parameters may not be null");
+        } 
+        int timeout = params.getConnectionTimeout();
+        SocketFactory socketfactory = mSslContext.getSocketFactory();
+        Log.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
+        Socket socket = socketfactory.createSocket();
+        SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
+        SocketAddress remoteaddr = new InetSocketAddress(host, port);
+        socket.setSoTimeout(params.getSoTimeout());
+        socket.bind(localaddr);
+        socket.connect(remoteaddr, timeout);
+        verifyPeerIdentity(host, port, socket);
+        return socket;
+    }
+
+    /**
+     * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
+     */
+    public Socket createSocket(String host, int port) throws IOException,
+            UnknownHostException {
+       Log.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
+        Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
+        verifyPeerIdentity(host, port, socket);
+        return socket; 
+    }
+
+    public boolean equals(Object obj) {
+        return ((obj != null) && obj.getClass().equals(
+                AdvancedSslSocketFactory.class));
+    }
+
+    public int hashCode() {
+        return AdvancedSslSocketFactory.class.hashCode();
+    }
+
+
+    public X509HostnameVerifier getHostNameVerifier() {
+        return mHostnameVerifier;
+    }
+    
+    
+    public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
+        mHostnameVerifier = hostnameVerifier;
+    }
+    
+    /**
+     * Verifies the identity of the server. 
+     * 
+     * The server certificate is verified first.
+     * 
+     * Then, the host name is compared with the content of the server certificate using the current host name verifier, if any.
+     * @param socket
+     */
+    private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
+        try {
+            CertificateCombinedException failInHandshake = null;
+            /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an instance of AdvancedX509TrustManager) 
+            try {
+                SSLSocket sock = (SSLSocket) socket;    // a new SSLSession instance is created as a "side effect" 
+                sock.startHandshake();
+                
+            } catch (RuntimeException e) {
+                
+                if (e instanceof CertificateCombinedException) {
+                    failInHandshake = (CertificateCombinedException) e;
+                } else {
+                    Throwable cause = e.getCause();
+                    Throwable previousCause = null;
+                    while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
+                        previousCause = cause;
+                        cause = cause.getCause();
+                    }
+                    if (cause != null && cause instanceof CertificateCombinedException) {
+                        failInHandshake = (CertificateCombinedException)cause;
+                    }
+                }
+                if (failInHandshake == null) {
+                    throw e;
+                }
+                failInHandshake.setHostInUrl(host);
+                
+            }
+            
+            /// 2. VERIFY HOSTNAME
+            SSLSession newSession = null;
+            boolean verifiedHostname = true;
+            if (mHostnameVerifier != null) {
+                if (failInHandshake != null) {
+                    /// 2.1 : a new SSLSession instance was NOT created in the handshake
+                    X509Certificate serverCert = failInHandshake.getServerCertificate();
+                    try {
+                        mHostnameVerifier.verify(host, serverCert);
+                    } catch (SSLException e) {
+                        verifiedHostname = false;
+                    }
+                
+                } else {
+                    /// 2.2 : a new SSLSession instance was created in the handshake
+                    newSession = ((SSLSocket)socket).getSession();
+                    if (!mTrustManager.isKnownServer((X509Certificate)(newSession.getPeerCertificates()[0]))) {
+                        verifiedHostname = mHostnameVerifier.verify(host, newSession); 
+                    }
+                }
+            }
+
+            /// 3. Combine the exceptions to throw, if any
+            if (!verifiedHostname) {
+                SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException("Names in the server certificate do not match to " + host + " in the URL");
+                if (failInHandshake == null) {
+                    failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]);
+                    failInHandshake.setHostInUrl(host);
+                }
+                failInHandshake.setSslPeerUnverifiedException(pue);
+                pue.initCause(failInHandshake);
+                throw pue;
+                
+            } else if (failInHandshake != null) {
+                SSLHandshakeException hse = new SSLHandshakeException("Server certificate could not be verified");
+                hse.initCause(failInHandshake);
+                throw hse;
+            }
+            
+        } catch (IOException io) {        
+            try {
+                socket.close();
+            } catch (Exception x) {
+                // NOTHING - irrelevant exception for the caller 
+            }
+            throw io;
+        }
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java b/oc_framework/src/com/owncloud/android/oc_framework/network/AdvancedX509TrustManager.java
new file mode 100644 (file)
index 0000000..4bad3ef
--- /dev/null
@@ -0,0 +1,148 @@
+/* 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.oc_framework.network;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertStoreException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import android.util.Log;
+
+
+
+/**
+ * @author David A. Velasco
+ */
+public class AdvancedX509TrustManager implements X509TrustManager {
+    
+    private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
+
+    private X509TrustManager mStandardTrustManager = null;
+    private KeyStore mKnownServersKeyStore;
+
+    /**
+     * Constructor for AdvancedX509TrustManager
+     * 
+     * @param  knownServersCertStore    Local certificates store with server certificates explicitly trusted by the user.
+     * @throws CertStoreException       When no default X509TrustManager instance was found in the system.
+     */
+    public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
+            throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
+        super();
+        TrustManagerFactory factory = TrustManagerFactory
+                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        factory.init((KeyStore)null);
+        mStandardTrustManager = findX509TrustManager(factory);
+
+        mKnownServersKeyStore = knownServersKeyStore;
+    }
+    
+    
+    /**
+     * Locates the first X509TrustManager provided by a given TrustManagerFactory
+     * @param factory               TrustManagerFactory to inspect in the search for a X509TrustManager
+     * @return                      The first X509TrustManager found in factory.
+     * @throws CertStoreException   When no X509TrustManager instance was found in factory
+     */
+    private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
+        TrustManager tms[] = factory.getTrustManagers();
+        for (int i = 0; i < tms.length; i++) {
+            if (tms[i] instanceof X509TrustManager) {
+                return (X509TrustManager) tms[i];
+            }
+        }
+        return null;
+    }
+    
+
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
+     *      String authType)
+     */
+    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        mStandardTrustManager.checkClientTrusted(certificates, authType);
+    }
+
+    
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
+     *      String authType)
+     */
+    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        if (!isKnownServer(certificates[0])) {
+               CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
+               try {
+                       certificates[0].checkValidity();
+               } catch (CertificateExpiredException c) {
+                       result.setCertificateExpiredException(c);
+                       
+               } catch (CertificateNotYetValidException c) {
+                result.setCertificateNotYetException(c);
+               }
+               
+               try {
+                   mStandardTrustManager.checkServerTrusted(certificates, authType);
+               } catch (CertificateException c) {
+                Throwable cause = c.getCause();
+                Throwable previousCause = null;
+                while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) {     // getCause() is not funny
+                    previousCause = cause;
+                    cause = cause.getCause();
+                }
+                if (cause != null && cause instanceof CertPathValidatorException) {
+                       result.setCertPathValidatorException((CertPathValidatorException)cause);
+                } else {
+                       result.setOtherCertificateException(c);
+                }
+               }
+               
+               if (result.isException())
+                       throw result;
+
+        }
+    }
+    
+    
+    /**
+     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+     */
+    public X509Certificate[] getAcceptedIssuers() {
+        return mStandardTrustManager.getAcceptedIssuers();
+    }
+
+    
+    public boolean isKnownServer(X509Certificate cert) {
+        try {
+            return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
+        } catch (KeyStoreException e) {
+            Log.d(TAG, "Fail while checking certificate in the known-servers store");
+            return false;
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java b/oc_framework/src/com/owncloud/android/oc_framework/network/BearerAuthScheme.java
new file mode 100644 (file)
index 0000000..37698d6
--- /dev/null
@@ -0,0 +1,272 @@
+package com.owncloud.android.oc_framework.network;
+/* 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/>.
+ *
+ */
+
+
+
+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 android.util.Log;
+
+
+
+/**
+ * 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 */
+    @SuppressWarnings("rawtypes")
+       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.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.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.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");
+    }
+    
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java b/oc_framework/src/com/owncloud/android/oc_framework/network/BearerCredentials.java
new file mode 100644 (file)
index 0000000..5b18e62
--- /dev/null
@@ -0,0 +1,98 @@
+package com.owncloud.android.oc_framework.network;
+/* 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/>.
+ *
+ */
+
+
+
+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;
+    }
+
+}
+
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java b/oc_framework/src/com/owncloud/android/oc_framework/network/CertificateCombinedException.java
new file mode 100644 (file)
index 0000000..1b262bc
--- /dev/null
@@ -0,0 +1,131 @@
+package com.owncloud.android.oc_framework.network;
+/* 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/>.
+ *
+ */
+
+
+
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+/**
+ * Exception joining all the problems that {@link AdvancedX509TrustManager} can find in
+ * a certificate chain for a server.
+ * 
+ * This was initially created as an extension of CertificateException, but some
+ * implementations of the SSL socket layer in existing devices are REPLACING the CertificateException
+ * instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)}
+ * with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it. 
+ * 
+ * Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException 
+ * instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}.
+ * 
+ * BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it
+ * in client methods. Be sure to use it only when you know exactly where it will go.
+ * 
+ * @author David A. Velasco
+ */
+public class CertificateCombinedException extends RuntimeException {
+
+    /** Generated - to refresh every time the class changes */
+    private static final long serialVersionUID = -8875782030758554999L;
+    
+    private X509Certificate mServerCert = null;
+    private String mHostInUrl;
+
+    private CertificateExpiredException mCertificateExpiredException = null;
+    private CertificateNotYetValidException mCertificateNotYetValidException = null;
+    private CertPathValidatorException mCertPathValidatorException = null;
+    private CertificateException mOtherCertificateException = null;
+    private SSLPeerUnverifiedException mSslPeerUnverifiedException = null;
+    
+    public CertificateCombinedException(X509Certificate x509Certificate) {
+        mServerCert = x509Certificate;
+    }
+
+    public X509Certificate getServerCertificate() {
+        return mServerCert;
+    }
+
+    public String getHostInUrl() {
+        return mHostInUrl;
+    }
+
+    public void setHostInUrl(String host) {
+        mHostInUrl = host;
+    }
+
+    public CertificateExpiredException getCertificateExpiredException() {
+        return mCertificateExpiredException;
+    }
+
+    public void setCertificateExpiredException(CertificateExpiredException c) {
+        mCertificateExpiredException  = c;
+    }
+
+    public CertificateNotYetValidException getCertificateNotYetValidException() {
+        return mCertificateNotYetValidException;
+    }
+
+    public void setCertificateNotYetException(CertificateNotYetValidException c) {
+        mCertificateNotYetValidException = c;
+    }
+
+    public CertPathValidatorException getCertPathValidatorException() {
+        return mCertPathValidatorException;
+    }
+
+    public void setCertPathValidatorException(CertPathValidatorException c) {
+        mCertPathValidatorException = c;
+    }
+
+    public CertificateException getOtherCertificateException() {
+        return mOtherCertificateException;
+    }
+
+    public void setOtherCertificateException(CertificateException c) {
+        mOtherCertificateException = c;
+    }
+
+    public SSLPeerUnverifiedException getSslPeerUnverifiedException() {
+        return mSslPeerUnverifiedException ; 
+    }
+
+    public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) {
+        mSslPeerUnverifiedException = s;
+    }
+
+    public boolean isException() {
+        return (mCertificateExpiredException != null ||
+                mCertificateNotYetValidException != null ||
+                mCertPathValidatorException != null ||
+                mOtherCertificateException != null ||
+                mSslPeerUnverifiedException != null);
+    }
+
+    public boolean isRecoverable() {
+        return (mCertificateExpiredException != null ||
+                mCertificateNotYetValidException != null ||
+                mCertPathValidatorException != null ||
+                mSslPeerUnverifiedException != null);
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/network/NetworkUtils.java
new file mode 100644 (file)
index 0000000..ac2e015
--- /dev/null
@@ -0,0 +1,168 @@
+/* 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.oc_framework.network;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+
+import android.content.Context;
+import android.util.Log;
+
+public class NetworkUtils {
+    
+    final private static String TAG = NetworkUtils.class.getSimpleName();
+    
+    /** Default timeout for waiting data from the server */
+    public static final int DEFAULT_DATA_TIMEOUT = 60000;
+    
+    /** Default timeout for establishing a connection */
+    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
+
+    /** Connection manager for all the WebdavClients */
+    private static MultiThreadedHttpConnectionManager mConnManager = null;
+    
+    private static Protocol mDefaultHttpsProtocol = null;
+
+    private static AdvancedSslSocketFactory mAdvancedSslSocketFactory = null;
+
+    private static X509HostnameVerifier mHostnameVerifier = null;
+    
+    
+    /**
+     * Registers or unregisters the proper components for advanced SSL handling.
+     * @throws IOException 
+     */
+    public static void registerAdvancedSslContext(boolean register, Context context) throws GeneralSecurityException, IOException {
+        Protocol pr = null;
+        try {
+            pr = Protocol.getProtocol("https");
+            if (pr != null && mDefaultHttpsProtocol == null) {
+                mDefaultHttpsProtocol = pr;
+            }
+        } catch (IllegalStateException e) {
+            // nothing to do here; really
+        }
+        boolean isRegistered = (pr != null && pr.getSocketFactory() instanceof AdvancedSslSocketFactory);
+        if (register && !isRegistered) {
+            Protocol.registerProtocol("https", new Protocol("https", getAdvancedSslSocketFactory(context), 443));
+            
+        } else if (!register && isRegistered) {
+            if (mDefaultHttpsProtocol != null) {
+                Protocol.registerProtocol("https", mDefaultHttpsProtocol);
+            }
+        }
+    }
+    
+    public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
+        if (mAdvancedSslSocketFactory  == null) {
+            KeyStore trustStore = getKnownServersStore(context);
+            AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
+            TrustManager[] tms = new TrustManager[] { trustMgr };
+                
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, tms, null);
+                    
+            mHostnameVerifier = new BrowserCompatHostnameVerifier();
+            mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
+        }
+        return mAdvancedSslSocketFactory;
+    }
+
+
+    private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
+    
+    private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
+
+    private static KeyStore mKnownServersStore = null;
+    
+    /**
+     * Returns the local store of reliable server certificates, explicitly accepted by the user.
+     * 
+     * Returns a KeyStore instance with empty content if the local store was never created.
+     * 
+     * Loads the store from the storage environment if needed.
+     * 
+     * @param context                       Android context where the operation is being performed.
+     * @return                              KeyStore instance with explicitly-accepted server certificates. 
+     * @throws KeyStoreException            When the KeyStore instance could not be created.
+     * @throws IOException                  When an existing local trust store could not be loaded.
+     * @throws NoSuchAlgorithmException     When the existing local trust store was saved with an unsupported algorithm.
+     * @throws CertificateException         When an exception occurred while loading the certificates from the local trust store.
+     */
+    private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
+        if (mKnownServersStore == null) {
+            //mKnownServersStore = KeyStore.getInstance("BKS");
+            mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
+            Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
+            if (localTrustStoreFile.exists()) {
+                InputStream in = new FileInputStream(localTrustStoreFile);
+                try {
+                    mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
+                } finally {
+                    in.close();
+                }
+            } else {
+                mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
+            }
+        }
+        return mKnownServersStore;
+    }
+    
+    
+    public static void addCertToKnownServersStore(Certificate cert, Context context) throws  KeyStoreException, NoSuchAlgorithmException, 
+                                                                                            CertificateException, IOException {
+        KeyStore knownServers = getKnownServersStore(context);
+        knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
+        FileOutputStream fos = null;
+        try {
+            fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
+            knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
+        } finally {
+            fos.close();
+        }
+    }
+    
+    
+    static public MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
+        if (mConnManager == null) {
+            mConnManager = new MultiThreadedHttpConnectionManager();
+            mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
+            mConnManager.getParams().setMaxTotalConnections(5);
+        }
+        return mConnManager;
+    }
+
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java b/oc_framework/src/com/owncloud/android/oc_framework/network/ProgressiveDataTransferer.java
new file mode 100644 (file)
index 0000000..3a21d5f
--- /dev/null
@@ -0,0 +1,34 @@
+package com.owncloud.android.oc_framework.network;
+/* 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/>.
+ *
+ */
+
+
+
+import java.util.Collection;
+
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+
+
+public interface ProgressiveDataTransferer {
+
+    public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
+    
+    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
+
+    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/ChunkFromFileChannelRequestEntity.java
new file mode 100644 (file)
index 0000000..6a4200d
--- /dev/null
@@ -0,0 +1,145 @@
+/* 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.oc_framework.network.webdav;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.RequestEntity;
+
+import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
+
+import android.util.Log;
+
+
+/**
+ * A RequestEntity that represents a PIECE of a file.
+ * 
+ * @author David A. Velasco
+ */
+public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
+
+    private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
+    
+    //private final File mFile;
+    private final FileChannel mChannel;
+    private final String mContentType;
+    private final long mChunkSize;
+    private final File mFile;
+    private long mOffset;
+    private long mTransferred;
+    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
+    private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
+
+    public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
+        super();
+        if (channel == null) {
+            throw new IllegalArgumentException("File may not be null");
+        }
+        if (chunkSize <= 0) {
+            throw new IllegalArgumentException("Chunk size must be greater than zero");
+        }
+        mChannel = channel;
+        mContentType = contentType;
+        mChunkSize = chunkSize;
+        mFile = file;
+        mOffset = 0;
+        mTransferred = 0;
+    }
+    
+    public void setOffset(long offset) {
+        mOffset = offset;
+    }
+    
+    public long getContentLength() {
+        try {
+            return Math.min(mChunkSize, mChannel.size() - mChannel.position());
+        } catch (IOException e) {
+            return mChunkSize;
+        }
+    }
+
+    public String getContentType() {
+        return mContentType;
+    }
+
+    public boolean isRepeatable() {
+        return true;
+    }
+    
+    @Override
+    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.add(listener);
+        }
+    }
+    
+    @Override
+    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.addAll(listeners);
+        }
+    }
+    
+    @Override
+    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.remove(listener);
+        }
+    }
+    
+    
+    public void writeRequest(final OutputStream out) throws IOException {
+        int readCount = 0;
+        Iterator<OnDatatransferProgressListener> it = null;
+        
+       try {
+            mChannel.position(mOffset);
+            long size = mFile.length();
+            if (size == 0) size = -1;
+            long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
+            while (mChannel.position() < maxCount) {
+                readCount = mChannel.read(mBuffer);
+                out.write(mBuffer.array(), 0, readCount);
+                mBuffer.clear();
+                if (mTransferred < maxCount) {  // condition to avoid accumulate progress for repeated chunks
+                    mTransferred += readCount;
+                }
+                synchronized (mDataTransferListeners) {
+                    it = mDataTransferListeners.iterator();
+                    while (it.hasNext()) {
+                        it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+                    }
+                }
+            }
+            
+        } catch (IOException io) {
+            Log.e(TAG, io.getMessage());
+            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
+            
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/FileRequestEntity.java
new file mode 100644 (file)
index 0000000..3f066f9
--- /dev/null
@@ -0,0 +1,132 @@
+/* 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.oc_framework.network.webdav;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.RequestEntity;
+
+import android.util.Log;
+
+import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
+
+
+/**
+ * A RequestEntity that represents a File.
+ * 
+ */
+public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
+
+    final File mFile;
+    final String mContentType;
+    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
+
+    public FileRequestEntity(final File file, final String contentType) {
+        super();
+        this.mFile = file;
+        this.mContentType = contentType;
+        if (file == null) {
+            throw new IllegalArgumentException("File may not be null");
+        }
+    }
+    
+    @Override
+    public long getContentLength() {
+        return mFile.length();
+    }
+
+    @Override
+    public String getContentType() {
+        return mContentType;
+    }
+
+    @Override
+    public boolean isRepeatable() {
+        return true;
+    }
+
+    @Override
+    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.add(listener);
+        }
+    }
+    
+    @Override
+    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.addAll(listeners);
+        }
+    }
+    
+    @Override
+    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+        synchronized (mDataTransferListeners) {
+            mDataTransferListeners.remove(listener);
+        }
+    }
+    
+    
+    @Override
+    public void writeRequest(final OutputStream out) throws IOException {
+        //byte[] tmp = new byte[4096];
+        ByteBuffer tmp = ByteBuffer.allocate(4096);
+        int readResult = 0;
+        
+        // TODO(bprzybylski): each mem allocation can throw OutOfMemoryError we need to handle it
+        //                    globally in some fashionable manner
+        RandomAccessFile raf = new RandomAccessFile(mFile, "r");
+        FileChannel channel = raf.getChannel();
+        Iterator<OnDatatransferProgressListener> it = null;
+        long transferred = 0;
+        long size = mFile.length();
+        if (size == 0) size = -1;
+        try {
+            while ((readResult = channel.read(tmp)) >= 0) {
+                out.write(tmp.array(), 0, readResult);
+                tmp.clear();
+                transferred += readResult;
+                synchronized (mDataTransferListeners) {
+                    it = mDataTransferListeners.iterator();
+                    while (it.hasNext()) {
+                        it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+                    }
+                }
+            }
+            
+        } catch (IOException io) {
+            Log.e("FileRequestException", io.getMessage());
+            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
+            
+        } finally {
+            channel.close();
+            raf.close();
+        }
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OnDatatransferProgressListener.java
new file mode 100644 (file)
index 0000000..06f32b5
--- /dev/null
@@ -0,0 +1,24 @@
+/* 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.oc_framework.network.webdav;
+
+public interface OnDatatransferProgressListener {
+    public void onTransferProgress(long progressRate);
+    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName);
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/OwnCloudClientFactory.java
new file mode 100644 (file)
index 0000000..0c0c207
--- /dev/null
@@ -0,0 +1,151 @@
+/* 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.oc_framework.network.webdav;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
+import com.owncloud.android.oc_framework.accounts.AccountUtils;
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
+import com.owncloud.android.oc_framework.network.NetworkUtils;
+
+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.os.Bundle;
+import android.util.Log;
+
+public class OwnCloudClientFactory {
+    
+    final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
+    
+    /** Default timeout for waiting data from the server */
+    public static final int DEFAULT_DATA_TIMEOUT = 60000;
+    
+    /** Default timeout for establishing a connection */
+    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
+
+    
+    /**
+     * Creates a WebdavClient setup for an ownCloud account
+     * 
+     * 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.
+     * @throws AccountNotFoundException     If 'account' is unknown for the AccountManager
+     */
+    public static WebdavClient createOwnCloudClient (Account account, Context appContext) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
+        //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
+       
+        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
+        AccountManager am = AccountManager.get(appContext);
+        boolean isOauth2 = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
+        boolean isSamlSso = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null;
+        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
+        if (isOauth2) {    
+            String accessToken = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), false);
+            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
+        
+        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
+            String accessToken = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), false);
+            client.setSsoSessionCookie(accessToken);
+            
+        } else {
+            String username = account.name.substring(0, account.name.lastIndexOf('@'));
+            String password = am.getPassword(account);
+            //String password = am.blockingGetAuthToken(account, AccountTypeUtils.getAuthTokenTypePass(account.type), false);
+            client.setBasicCredentials(username, password);
+        }
+        
+        return client;
+    }
+    
+    
+    public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
+        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
+        AccountManager am = AccountManager.get(appContext);
+        boolean isOauth2 = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
+        boolean isSamlSso = am.getUserData(account, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null;
+        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
+        
+        if (isOauth2) {    // TODO avoid a call to getUserData here
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account,  AccountTypeUtils.getAuthTokenTypeAccessToken(account.type), null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
+            if (accessToken == null) throw new AuthenticatorException("WTF!");
+            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
+
+        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type), null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
+            if (accessToken == null) throw new AuthenticatorException("WTF!");
+            client.setSsoSessionCookie(accessToken);
+
+        } else {
+            String username = account.name.substring(0, account.name.lastIndexOf('@'));
+            //String password = am.getPassword(account);
+            //String password = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypePass(), false);
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account,  AccountTypeUtils.getAuthTokenTypePass(account.type), 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.
+     * 
+     * @param uri       URL to the ownCloud server
+     * @param context   Android context where the WebdavClient is being created.
+     * @return          A WebdavClient object ready to be used
+     */
+    public static WebdavClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
+        try {
+            NetworkUtils.registerAdvancedSslContext(true, context);
+        }  catch (GeneralSecurityException e) {
+            Log.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
+            
+        } catch (IOException e) {
+            Log.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
+        }
+        
+        WebdavClient client = new WebdavClient(NetworkUtils.getMultiThreadedConnManager());
+        
+        client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
+        client.setBaseUri(uri);
+        client.setFollowRedirects(followRedirects);
+        
+        return client;
+    }
+    
+    
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavClient.java
new file mode 100644 (file)
index 0000000..543374c
--- /dev/null
@@ -0,0 +1,245 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2011  Bartek Przybylski
+ *   Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License 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.oc_framework.network.webdav;
+
+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.Header;
+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.HttpVersion;
+import org.apache.commons.httpclient.URI;
+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.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.http.HttpStatus;
+import org.apache.http.params.CoreProtocolPNames;
+
+import com.owncloud.android.oc_framework.network.BearerAuthScheme;
+import com.owncloud.android.oc_framework.network.BearerCredentials;
+
+import android.net.Uri;
+import android.util.Log;
+
+public class WebdavClient extends HttpClient {
+    private static final int MAX_REDIRECTIONS_COUNT = 3;
+    
+    private Uri mUri;
+    private Credentials mCredentials;
+    private boolean mFollowRedirects;
+    private String mSsoSessionCookie;
+    final private static String TAG = WebdavClient.class.getSimpleName();
+    public static final String USER_AGENT = "Android-ownCloud";
+    
+    static private byte[] sExhaustBuffer = new byte[1024];
+    
+    /**
+     * Constructor
+     */
+    public WebdavClient(HttpConnectionManager connectionMgr) {
+        super(connectionMgr);
+        Log.d(TAG, "Creating WebdavClient");
+        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
+        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
+        mFollowRedirects = true;
+        mSsoSessionCookie = null;
+    }
+
+    public void setBearerCredentials(String accessToken) {
+        AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
+        
+        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);
+        mSsoSessionCookie = null;
+    }
+
+    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);
+        mSsoSessionCookie = null;
+    }
+    
+    public void setSsoSessionCookie(String accessToken) {
+        getParams().setAuthenticationPreemptive(false);
+        getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
+        mSsoSessionCookie = accessToken;
+        mCredentials = null;
+    }
+    
+    
+    /**
+     * 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
+     */
+    public boolean existsFile(String path) throws IOException, HttpException {
+        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
+        try {
+            int status = executeMethod(head);
+            Log.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
+            exhaustResponse(head.getResponseBodyAsStream());
+            return (status == HttpStatus.SC_OK);
+            
+        } finally {
+            head.releaseConnection();    // let the connection available for other methods
+        }
+    }
+    
+    /**
+     * Requests the received method with the received timeout (milliseconds).
+     * 
+     * Executes the method through the inherited HttpClient.executedMethod(method).
+     * 
+     * Sets the socket and connection timeouts only for the method received.
+     * 
+     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
+     * 
+     * @param method            HTTP method request.
+     * @param readTimeout       Timeout to set for data reception
+     * @param conntionTimout    Timeout to set for connection establishment
+     */
+    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
+        int oldSoTimeout = getParams().getSoTimeout();
+        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
+        try {
+            if (readTimeout >= 0) { 
+                method.getParams().setSoTimeout(readTimeout);   // this should be enough...
+                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS
+            }
+            if (connectionTimeout >= 0) {
+                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
+            }
+            return executeMethod(method);
+        } finally {
+            getParams().setSoTimeout(oldSoTimeout);
+            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
+        }
+    }
+    
+    
+    @Override
+    public int executeMethod(HttpMethod method) throws IOException, HttpException {
+        boolean customRedirectionNeeded = false;
+        try {
+            method.setFollowRedirects(mFollowRedirects);
+        } catch (Exception e) {
+            //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
+            customRedirectionNeeded = mFollowRedirects;
+        }
+        if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
+            method.setRequestHeader("Cookie", mSsoSessionCookie);
+        }
+        int status = super.executeMethod(method);
+        int redirectionsCount = 0;
+        while (customRedirectionNeeded &&
+                redirectionsCount < MAX_REDIRECTIONS_COUNT &&
+                (   status == HttpStatus.SC_MOVED_PERMANENTLY || 
+                    status == HttpStatus.SC_MOVED_TEMPORARILY ||
+                    status == HttpStatus.SC_TEMPORARY_REDIRECT)
+                ) {
+            
+            Header location = method.getResponseHeader("Location");
+            if (location != null) {
+                Log.d(TAG,  "Location to redirect: " + location.getValue());
+                method.setURI(new URI(location.getValue(), true));
+                status = super.executeMethod(method);
+                redirectionsCount++;
+                
+            } else {
+                Log.d(TAG,  "No location to redirect!");
+                status = HttpStatus.SC_NOT_FOUND;
+            }
+        }
+        
+        return status;
+    }
+
+
+    /**
+     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
+     * 
+     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.
+     */
+    public void exhaustResponse(InputStream responseBodyAsStream) {
+        if (responseBodyAsStream != null) {
+            try {
+                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
+                responseBodyAsStream.close();
+            
+            } catch (IOException io) {
+                Log.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
+            }
+        }
+    }
+
+    /**
+     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
+     */
+    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
+            getParams().setSoTimeout(defaultDataTimeout);
+            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
+    }
+
+    /**
+     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
+     * @param uri
+     */
+    public void setBaseUri(Uri uri) {
+        mUri = uri;
+    }
+
+    public Uri getBaseUri() {
+        return mUri;
+    }
+
+    public final Credentials getCredentials() {
+        return mCredentials;
+    }
+    
+    public final String getSsoSessionCookie() {
+        return mSsoSessionCookie;
+    }
+
+    public void setFollowRedirects(boolean followRedirects) {
+        mFollowRedirects = followRedirects;
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavEntry.java
new file mode 100644 (file)
index 0000000..3bcfa36
--- /dev/null
@@ -0,0 +1,150 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012  ownCloud
+ *
+ *   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.oc_framework.network.webdav;
+
+import java.util.Date;
+
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+
+
+
+import android.net.Uri;
+import android.util.Log;
+
+public class WebdavEntry {
+    private String mName, mPath, mUri, mContentType, mEtag;
+    private long mContentLength, mCreateTimestamp, mModifiedTimestamp;
+
+    public WebdavEntry(MultiStatusResponse ms, String splitElement) {
+        resetData();
+        if (ms.getStatus().length != 0) {
+            mUri = ms.getHref();
+
+            mPath = mUri.split(splitElement, 2)[1];
+
+            int status = ms.getStatus()[0].getStatusCode();
+            DavPropertySet propSet = ms.getProperties(status);
+            @SuppressWarnings("rawtypes")
+            DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
+            if (prop != null) {
+                mName = (String) prop.getName().toString();
+                mName = mName.substring(1, mName.length()-1);
+            }
+            else {
+                String[] tmp = mPath.split("/");
+                if (tmp.length > 0)
+                    mName = tmp[tmp.length - 1];
+            }
+
+            // use unknown mimetype as default behavior
+            mContentType = "application/octet-stream";
+            prop = propSet.get(DavPropertyName.GETCONTENTTYPE);
+            if (prop != null) {
+                mContentType = (String) prop.getValue();
+                // dvelasco: some builds of ownCloud server 4.0.x added a trailing ';' to the MIME type ; if looks fixed, but let's be cautious
+                if (mContentType.indexOf(";") >= 0) {
+                    mContentType = mContentType.substring(0, mContentType.indexOf(";"));
+                }
+            }
+            
+            // check if it's a folder in the standard way: see RFC2518 12.2 . RFC4918 14.3 
+            prop = propSet.get(DavPropertyName.RESOURCETYPE);
+            if (prop!= null) {
+                Object value = prop.getValue();
+                if (value != null) {
+                    mContentType = "DIR";   // a specific attribute would be better, but this is enough; unless while we have no reason to distinguish MIME types for folders
+                }
+            }
+
+            prop = propSet.get(DavPropertyName.GETCONTENTLENGTH);
+            if (prop != null)
+                mContentLength = Long.parseLong((String) prop.getValue());
+
+            prop = propSet.get(DavPropertyName.GETLASTMODIFIED);
+            if (prop != null) {
+                Date d = WebdavUtils
+                        .parseResponseDate((String) prop.getValue());
+                mModifiedTimestamp = (d != null) ? d.getTime() : 0;
+            }
+
+            prop = propSet.get(DavPropertyName.CREATIONDATE);
+            if (prop != null) {
+                Date d = WebdavUtils
+                        .parseResponseDate((String) prop.getValue());
+                mCreateTimestamp = (d != null) ? d.getTime() : 0;
+            }
+            
+            prop = propSet.get(DavPropertyName.GETETAG);
+            if (prop != null) {
+                mEtag = (String) prop.getValue();
+                mEtag = mEtag.substring(1, mEtag.length()-1);
+            }
+
+        } else {
+            Log.e("WebdavEntry",
+                    "General fuckup, no status for webdav response");
+        }
+    }
+
+    public String path() {
+        return mPath;
+    }
+    
+    public String decodedPath() {
+        return Uri.decode(mPath);
+    }
+
+    public String name() {
+        return mName;
+    }
+
+    public boolean isDirectory() {
+        return mContentType.equals("DIR");
+    }
+
+    public String contentType() {
+        return mContentType;
+    }
+
+    public String uri() {
+        return mUri;
+    }
+
+    public long contentLength() {
+        return mContentLength;
+    }
+
+    public long createTimestamp() {
+        return mCreateTimestamp;
+    }
+
+    public long modifiedTimestamp() {
+        return mModifiedTimestamp;
+    }
+    
+    public String etag() {
+        return mEtag;
+    }
+
+    private void resetData() {
+        mName = mUri = mContentType = null;
+        mContentLength = mCreateTimestamp = mModifiedTimestamp = 0;
+    }
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/network/webdav/WebdavUtils.java
new file mode 100644 (file)
index 0000000..f5681de
--- /dev/null
@@ -0,0 +1,76 @@
+/* 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.oc_framework.network.webdav;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import android.net.Uri;
+
+public class WebdavUtils {
+    public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
+            "dd.MM.yyyy hh:mm");
+    private static final SimpleDateFormat DATETIME_FORMATS[] = {
+            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
+            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
+            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US),
+            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
+            new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US),
+            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
+            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
+
+    public static String prepareXmlForPropFind() {
+        String ret = "<?xml version=\"1.0\" ?><D:propfind xmlns:D=\"DAV:\"><D:allprop/></D:propfind>";
+        return ret;
+    }
+
+    public static String prepareXmlForPatch() {
+        return "<?xml version=\"1.0\" ?><D:propertyupdate xmlns:D=\"DAV:\"></D:propertyupdate>";
+    }
+
+    public static Date parseResponseDate(String date) {
+        Date returnDate = null;
+        for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
+            try {
+                returnDate = DATETIME_FORMATS[i].parse(date);
+                return returnDate;
+            } catch (ParseException e) {
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Encodes a path according to URI RFC 2396. 
+     * 
+     * If the received path doesn't start with "/", the method adds it.
+     * 
+     * @param remoteFilePath    Path
+     * @return                  Encoded path according to RFC 2396, always starting with "/"
+     */
+    public static String encodePath(String remoteFilePath) {
+        String encodedPath = Uri.encode(remoteFilePath, "/");
+        if (!encodedPath.startsWith("/"))
+            encodedPath = "/" + encodedPath;
+        return encodedPath;
+    }
+    
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/OnRemoteOperationListener.java
new file mode 100644 (file)
index 0000000..a81d401
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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.oc_framework.operations;
+
+public interface OnRemoteOperationListener {
+
+       void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
+       
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/OperationCancelledException.java
new file mode 100644 (file)
index 0000000..d5fd378
--- /dev/null
@@ -0,0 +1,28 @@
+/* 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.oc_framework.operations;
+
+public class OperationCancelledException extends Exception {
+
+    /**
+     * Generated serial version - to avoid Java warning
+     */
+    private static final long serialVersionUID = -6350981497740424983L;
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperation.java
new file mode 100644 (file)
index 0000000..e18ae53
--- /dev/null
@@ -0,0 +1,287 @@
+/* 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.oc_framework.operations;
+
+import java.io.IOException;
+
+import org.apache.commons.httpclient.Credentials;
+
+import com.owncloud.android.oc_framework.network.BearerCredentials;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
+import com.owncloud.android.oc_framework.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 android.util.Log;
+
+
+/**
+ * Operation which execution involves one or several interactions with an ownCloud server.
+ * 
+ * Provides methods to execute the operation both synchronously or asynchronously.
+ * 
+ * @author David A. Velasco 
+ */
+public abstract class RemoteOperation implements Runnable {
+       
+    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 */
+       private OnRemoteOperationListener mListener = null;
+       
+       /** 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 = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
+        } catch (Exception e) {
+            Log.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.
+        */
+       public final RemoteOperationResult execute(WebdavClient client) {
+               if (client == null)
+                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
+               mClient = client;
+               return run(client);
+       }
+
+       
+    /**
+     * 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
+        
+        mListener = listener;
+        
+        mListenerHandler = listenerHandler;
+        
+        Thread runnerThread = new Thread(this);
+        runnerThread.start();
+        return runnerThread;
+    }
+
+    
+       /**
+        * Asynchronously executes the remote operation
+        * 
+        * @param client                        Client object to reach an ownCloud server during the execution of the operation.
+        * @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(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
+               if (client == null) {
+                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
+               }
+               mClient = client;
+               
+               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;
+       }
+       
+    /**
+     * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
+     * 
+     * @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 RemoteOperationResult retry() {
+        return execute(mClient);
+    }
+    
+    /**
+     * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
+     * 
+     * @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 retry(OnRemoteOperationListener listener, Handler listenerHandler) {
+        return execute(mClient, listener, listenerHandler);
+    }
+       
+       
+       /**
+        * 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() {
+        RemoteOperationResult result = null;
+        boolean repeat = false;
+        do {
+            try{
+                if (mClient == null) {
+                    if (mAccount != null && mContext != null) {
+                        if (mCallerActivity != null) {
+                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext, mCallerActivity);
+                        } else {
+                            mClient = OwnCloudClientFactory.createOwnCloudClient(mAccount, mContext);
+                        }
+                    } else {
+                        throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
+                    }
+                }
+            
+            } catch (IOException e) {
+                Log.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.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 || (result.isTemporalRedirection() && result.isIdPRedirection()))) {
+                    (result.getCode() == ResultCode.UNAUTHORIZED || result.isIdPRedirection())) {
+                /// possible fail due to lack of authorization in an operation performed in foreground
+                Credentials cred = mClient.getCredentials();
+                String ssoSessionCookie = mClient.getSsoSessionCookie();
+                if (cred != null || ssoSessionCookie != null) {
+                    /// confirmed : unauthorized operation
+                    AccountManager am = AccountManager.get(mContext);
+                    boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
+                    boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
+                    if (bearerAuthorization) {
+                        am.invalidateAuthToken(mAccount.type, ((BearerCredentials)cred).getAccessToken());
+                    } else if (samlBasedSsoAuthorization ) {
+                        am.invalidateAuthToken(mAccount.type, ssoSessionCookie);
+                    } 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, 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;
+    }
+
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java
new file mode 100644 (file)
index 0000000..f26988c
--- /dev/null
@@ -0,0 +1,341 @@
+/* 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.oc_framework.operations;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+import javax.net.ssl.SSLException;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.jackrabbit.webdav.DavException;
+
+import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
+import com.owncloud.android.oc_framework.network.CertificateCombinedException;
+
+import android.accounts.Account;
+import android.accounts.AccountsException;
+import android.util.Log;
+
+
+/**
+ * The result of a remote operation required to an ownCloud server.
+ * 
+ * Provides a common classification of remote operation results for all the
+ * application.
+ * 
+ * @author David A. Velasco
+ */
+public class RemoteOperationResult implements Serializable {
+
+    /** Generated - should be refreshed every time the class changes!! */
+    private static final long serialVersionUID = -4415103901492836870L;
+    
+
+    
+    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, 
+        OAUTH2_ERROR,
+        SYNC_CONFLICT,
+        LOCAL_STORAGE_FULL, 
+        LOCAL_STORAGE_NOT_MOVED, 
+        LOCAL_STORAGE_NOT_COPIED, 
+        OAUTH2_ERROR_ACCESS_DENIED,
+        QUOTA_EXCEEDED, 
+        ACCOUNT_NOT_FOUND, 
+        ACCOUNT_EXCEPTION, 
+        ACCOUNT_NOT_NEW, 
+        ACCOUNT_NOT_THE_SAME,
+        INVALID_CHARACTER_IN_NAME
+    }
+
+    private boolean mSuccess = false;
+    private int mHttpCode = -1;
+    private Exception mException = null;
+    private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
+    private String mRedirectedLocation;
+
+    public RemoteOperationResult(ResultCode code) {
+        mCode = code;
+        mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
+    }
+
+    private RemoteOperationResult(boolean success, int httpCode) {
+        mSuccess = success;
+        mHttpCode = httpCode;
+
+        if (success) {
+            mCode = ResultCode.OK;
+
+        } else if (httpCode > 0) {
+            switch (httpCode) {
+            case HttpStatus.SC_UNAUTHORIZED:
+                mCode = ResultCode.UNAUTHORIZED;
+                break;
+            case HttpStatus.SC_NOT_FOUND:
+                mCode = ResultCode.FILE_NOT_FOUND;
+                break;
+            case HttpStatus.SC_INTERNAL_SERVER_ERROR:
+                mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
+                break;
+            case HttpStatus.SC_CONFLICT:
+                mCode = ResultCode.CONFLICT;
+                break;
+            case HttpStatus.SC_INSUFFICIENT_STORAGE:
+                mCode = ResultCode.QUOTA_EXCEEDED;
+                break;
+            default:
+                mCode = ResultCode.UNHANDLED_HTTP_CODE;
+                Log.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
+            }
+        }
+    }
+    
+    public RemoteOperationResult(boolean success, int httpCode, Header[] headers) {
+        this(success, httpCode);
+        if (headers != null) {
+            Header current;
+            for (int i=0; i<headers.length; i++) {
+                current = headers[i];
+                if ("Location".equals(current.getName())) {
+                    mRedirectedLocation = current.getValue();
+                    break;
+                }
+            }
+        }
+    }    
+
+    public RemoteOperationResult(Exception e) {
+        mException = e;
+
+        if (e instanceof OperationCancelledException) {
+            mCode = ResultCode.CANCELLED;
+
+        } else if (e instanceof SocketException) {
+            mCode = ResultCode.WRONG_CONNECTION;
+
+        } else if (e instanceof SocketTimeoutException) {
+            mCode = ResultCode.TIMEOUT;
+
+        } else if (e instanceof ConnectTimeoutException) {
+            mCode = ResultCode.TIMEOUT;
+
+        } else if (e instanceof MalformedURLException) {
+            mCode = ResultCode.INCORRECT_ADDRESS;
+
+        } else if (e instanceof UnknownHostException) {
+            mCode = ResultCode.HOST_NOT_AVAILABLE;
+
+        } else if (e instanceof AccountNotFoundException) {
+            mCode = ResultCode.ACCOUNT_NOT_FOUND;
+            
+        } else if (e instanceof AccountsException) {
+            mCode = ResultCode.ACCOUNT_EXCEPTION;
+            
+        } else if (e instanceof SSLException || e instanceof RuntimeException) {
+            CertificateCombinedException se = getCertificateCombinedException(e);
+            if (se != null) {
+                mException = se;
+                if (se.isRecoverable()) {
+                    mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
+                }
+            } else if (e instanceof RuntimeException) {
+                mCode = ResultCode.HOST_NOT_AVAILABLE;
+
+            } else {
+                mCode = ResultCode.SSL_ERROR;
+            }
+
+        } else {
+            mCode = ResultCode.UNKNOWN_ERROR;
+        }
+
+    }
+
+    public boolean isSuccess() {
+        return mSuccess;
+    }
+
+    public boolean isCancelled() {
+        return mCode == ResultCode.CANCELLED;
+    }
+
+    public int getHttpCode() {
+        return mHttpCode;
+    }
+
+    public ResultCode getCode() {
+        return mCode;
+    }
+
+    public Exception getException() {
+        return mException;
+    }
+
+    public boolean isSslRecoverableException() {
+        return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
+    }
+
+    private CertificateCombinedException getCertificateCombinedException(Exception e) {
+        CertificateCombinedException result = null;
+        if (e instanceof CertificateCombinedException) {
+            return (CertificateCombinedException) e;
+        }
+        Throwable cause = mException.getCause();
+        Throwable previousCause = null;
+        while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
+            previousCause = cause;
+            cause = cause.getCause();
+        }
+        if (cause != null && cause instanceof CertificateCombinedException) {
+            result = (CertificateCombinedException) cause;
+        }
+        return result;
+    }
+
+    public String getLogMessage() {
+
+        if (mException != null) {
+            if (mException instanceof OperationCancelledException) {
+                return "Operation cancelled by the caller";
+
+            } else if (mException instanceof SocketException) {
+                return "Socket exception";
+
+            } else if (mException instanceof SocketTimeoutException) {
+                return "Socket timeout exception";
+
+            } else if (mException instanceof ConnectTimeoutException) {
+                return "Connect timeout exception";
+
+            } else if (mException instanceof MalformedURLException) {
+                return "Malformed URL exception";
+
+            } else if (mException instanceof UnknownHostException) {
+                return "Unknown host exception";
+
+            } else if (mException instanceof CertificateCombinedException) {
+                if (((CertificateCombinedException) mException).isRecoverable())
+                    return "SSL recoverable exception";
+                else
+                    return "SSL exception";
+
+            } else if (mException instanceof SSLException) {
+                return "SSL exception";
+
+            } else if (mException instanceof DavException) {
+                return "Unexpected WebDAV exception";
+
+            } else if (mException instanceof HttpException) {
+                return "HTTP violation";
+
+            } else if (mException instanceof IOException) {
+                return "Unrecovered transport exception";
+
+            } else if (mException instanceof AccountNotFoundException) {
+                Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
+                return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
+                
+            } else if (mException instanceof AccountsException) {
+                return "Exception while using account";
+                
+            } else {
+                return "Unexpected exception";
+            }
+        }
+
+        if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
+            return "The ownCloud server is not configured!";
+
+        } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
+            return "No network connection";
+
+        } else if (mCode == ResultCode.BAD_OC_VERSION) {
+            return "No valid ownCloud version was found at the server";
+
+        } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
+            return "Local storage full";
+
+        } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
+            return "Error while moving file to final directory";
+
+        } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
+            return "Account already existing when creating a new one";
+
+        } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
+            return "Authenticated with a different account than the one updating";
+        } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
+               return "The file name contains an forbidden character";
+        }
+
+        return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
+
+    }
+
+    public boolean isServerFail() {
+        return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
+    }
+
+    public boolean isException() {
+        return (mException != null);
+    }
+
+    public boolean isTemporalRedirection() {
+        return (mHttpCode == 302 || mHttpCode == 307);
+    }
+
+    public String getRedirectedLocation() {
+        return mRedirectedLocation;
+    }
+    
+    public boolean isIdPRedirection() {
+        return (mRedirectedLocation != null &&
+                (mRedirectedLocation.toUpperCase().contains("SAML") || 
+                mRedirectedLocation.toLowerCase().contains("wayf")));
+    }
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/CreateRemoteFolderOperation.java
new file mode 100644 (file)
index 0000000..0974d08
--- /dev/null
@@ -0,0 +1,94 @@
+package com.owncloud.android.oc_framework.operations.remote;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
+
+import android.util.Log;
+
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.utils.FileUtils;
+
+
+
+/**
+ * Remote operation performing the creation of a new folder in the ownCloud server.
+ * 
+ * @author David A. Velasco 
+ * @author masensio
+ *
+ */
+public class CreateRemoteFolderOperation extends RemoteOperation {
+    
+    private static final String TAG = CreateRemoteFolderOperation.class.getSimpleName();
+
+    private static final int READ_TIMEOUT = 10000;
+    private static final int CONNECTION_TIMEOUT = 5000;
+    
+
+    protected String mRemotePath;
+    protected boolean mCreateFullPath;
+    
+    /**
+     * Constructor
+     * 
+     * @param remotePath            Full path to the new directory to create in the remote server.
+     * @param createFullPath        'True' means that all the ancestor folders should be created if don't exist yet.
+     */
+    public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
+        mRemotePath = remotePath;
+        mCreateFullPath = createFullPath;
+    }
+
+    /**
+     * Performs the operation
+     * 
+     * @param   client      Client object to communicate with the remote ownCloud server.
+     */
+    @Override
+    protected RemoteOperationResult run(WebdavClient client) {
+        RemoteOperationResult result = null;
+        MkColMethod mkcol = null;
+        
+        boolean noInvalidChars = FileUtils.isValidPath(mRemotePath);
+        if (noInvalidChars) {
+               try {
+                       mkcol = new MkColMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
+                       int status =  client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
+                       if (!mkcol.succeeded() && mkcol.getStatusCode() == HttpStatus.SC_CONFLICT && mCreateFullPath) {
+                               result = createParentFolder(FileUtils.getParentPath(mRemotePath), client);
+                               status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);    // second (and last) try
+                       }
+
+                       result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders());
+                       Log.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
+                       client.exhaustResponse(mkcol.getResponseBodyAsStream());
+
+               } catch (Exception e) {
+                       result = new RemoteOperationResult(e);
+                       Log.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
+
+               } finally {
+                       if (mkcol != null)
+                               mkcol.releaseConnection();
+               }
+        } else {
+               result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
+        }
+        
+        return result;
+    }
+
+    
+    private RemoteOperationResult createParentFolder(String parentPath, WebdavClient client) {
+        RemoteOperation operation = new CreateRemoteFolderOperation(parentPath,
+                                                                mCreateFullPath);
+        return operation.execute(client);
+    }
+    
+   
+
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java
new file mode 100644 (file)
index 0000000..8fb01dc
--- /dev/null
@@ -0,0 +1,52 @@
+package com.owncloud.android.oc_framework.utils;
+
+import java.io.File;
+
+import android.util.Log;
+
+public class FileUtils {
+
+       public static final String PATH_SEPARATOR = "/";
+
+
+       public static String getParentPath(String remotePath) {
+               String parentPath = new File(remotePath).getParent();
+               parentPath = parentPath.endsWith(PATH_SEPARATOR) ? parentPath : parentPath + PATH_SEPARATOR;
+               return parentPath;
+       }
+       
+       /**
+        * Validate the fileName to detect if contains any forbidden character: / , \ , < , > , : , " , | , ? , *
+        * @param fileName
+        * @return
+        */
+       public static boolean isValidName(String fileName) {
+               boolean result = true;
+               
+               Log.d("FileUtils", "fileName =======" + fileName);
+               if (fileName.contains(PATH_SEPARATOR) ||
+                               fileName.contains("\\") || fileName.contains("<") || fileName.contains(">") ||
+                               fileName.contains(":") || fileName.contains("\"") || fileName.contains("|") || 
+                               fileName.contains("?") || fileName.contains("*")) {
+                       result = false;
+               }
+               return result;
+       }
+       
+       /**
+        * Validate the path to detect if contains any forbidden character: \ , < , > , : , " , | , ? , *
+        * @param path
+        * @return
+        */
+       public static boolean isValidPath(String path) {
+               boolean result = true;
+               
+               Log.d("FileUtils", "path ....... " + path);
+               if (path.contains("\\") || path.contains("<") || path.contains(">") ||
+                               path.contains(":") || path.contains("\"") || path.contains("|") || 
+                               path.contains("?") || path.contains("*")) {
+                       result = false;
+               }
+               return result;
+       }
+}
diff --git a/oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java b/oc_framework/src/com/owncloud/android/oc_framework/utils/OwnCloudVersion.java
new file mode 100644 (file)
index 0000000..5a9df4d
--- /dev/null
@@ -0,0 +1,85 @@
+/* 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.oc_framework.utils;
+
+public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
+    public static final OwnCloudVersion owncloud_v1 = new OwnCloudVersion(
+            0x010000);
+    public static final OwnCloudVersion owncloud_v2 = new OwnCloudVersion(
+            0x020000);
+    public static final OwnCloudVersion owncloud_v3 = new OwnCloudVersion(
+            0x030000);
+    public static final OwnCloudVersion owncloud_v4 = new OwnCloudVersion(
+            0x040000);
+    public static final OwnCloudVersion owncloud_v4_5 = new OwnCloudVersion(
+            0x040500);
+
+    // format is in version
+    // 0xAABBCC
+    // for version AA.BB.CC
+    // ie version 2.0.3 will be stored as 0x030003
+    private int mVersion;
+    private boolean mIsValid;
+
+    public OwnCloudVersion(int version) {
+        mVersion = version;
+        mIsValid = true;
+    }
+
+    public OwnCloudVersion(String version) {
+        mVersion = 0;
+        mIsValid = false;
+        parseVersionString(version);
+    }
+
+    public String toString() {
+        return ((mVersion >> 16) % 256) + "." + ((mVersion >> 8) % 256) + "."
+                + ((mVersion) % 256);
+    }
+
+    public boolean isVersionValid() {
+        return mIsValid;
+    }
+
+    @Override
+    public int compareTo(OwnCloudVersion another) {
+        return another.mVersion == mVersion ? 0
+                : another.mVersion < mVersion ? 1 : -1;
+    }
+
+    private void parseVersionString(String version) {
+        try {
+            String[] nums = version.split("\\.");
+            if (nums.length > 0) {
+                mVersion += Integer.parseInt(nums[0]);
+            }
+            mVersion = mVersion << 8;
+            if (nums.length > 1) {
+                mVersion += Integer.parseInt(nums[1]);
+            }
+            mVersion = mVersion << 8;
+            if (nums.length > 2) {
+                mVersion += Integer.parseInt(nums[2]);
+            }
+            mIsValid = true;
+        } catch (Exception e) {
+            mIsValid = false;
+        }
+    }
+}
index c9e5840..8435261 100644 (file)
@@ -9,4 +9,5 @@
 
 # Project target.
 target=android-19
-android.library.reference.1=actionbarsherlock/library
+android.library.reference.1=actionbarsherlock\\library
+android.library.reference.2=oc_framework
index c8cea0b..05c7ecf 100644 (file)
     <string name="sync_file_fail_msg">Remote file could not be checked</string>
     <string name="sync_file_nothing_to_do_msg">File contents already synchronized</string>
     <string name="create_dir_fail_msg">Directory could not be created</string>
+    <string name="filename_forbidden_characters">Forbidden characters: / \\ &lt; &gt; : " | ? *</string>
     <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>
index 265ff59..d5b78c9 100644 (file)
@@ -1,6 +1,7 @@
 call git submodule init
 call git submodule update
 call android.bat update project -p actionbarsherlock\library -n ActionBarSherlock
+call android.bat update project -p oc_framework -n ownCloudFramework
 call android.bat update project -p .
 call android.bat update project -p oc_jb_workaround
 copy /Y third_party\android-support-library\android-support-v4.jar actionbarsherlock\library\libs\android-support-v4.jar
index d18ce22..b13fe81 100755 (executable)
@@ -3,6 +3,7 @@
 git submodule init
 git submodule update
 android update project -p actionbarsherlock/library -n ActionBarSherlock
+android update project -p oc_framework -n ownCloudFramework
 android update project -p .
 android update project -p oc_jb_workaround
 cp third_party/android-support-library/android-support-v4.jar actionbarsherlock/library/libs/android-support-v4.jar 
diff --git a/src/com/owncloud/android/DisplayUtils.java b/src/com/owncloud/android/DisplayUtils.java
deleted file mode 100644 (file)
index 1ee898b..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/* ownCloud Android client application\r
- *   Copyright (C) 2011  Bartek Przybylski\r
- *   Copyright (C) 2012-2013 ownCloud Inc.\r
- *\r
- *   This program is free software: you can redistribute it and/or modify\r
- *   it under the terms of the GNU General Public License version 2,\r
- *   as published by the Free Software Foundation.\r
- *\r
- *   This program is distributed in the hope that it will be useful,\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *   GNU General Public License for more details.\r
- *\r
- *   You should have received a copy of the GNU General Public License\r
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
- *\r
- */\r
-\r
-package com.owncloud.android;\r
-\r
-import java.util.Arrays;\r
-import java.util.Date;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
-/**\r
- * A helper class for some string operations.\r
- * \r
- * @author Bartek Przybylski\r
- * @author David A. Velasco\r
- */\r
-public class DisplayUtils {\r
-    \r
-    //private static String TAG = DisplayUtils.class.getSimpleName(); \r
-    \r
-    private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };\r
-\r
-    private static HashMap<String, String> mimeType2HUmanReadable;\r
-    static {\r
-        mimeType2HUmanReadable = new HashMap<String, String>();\r
-        // images\r
-        mimeType2HUmanReadable.put("image/jpeg", "JPEG image");\r
-        mimeType2HUmanReadable.put("image/jpg", "JPEG image");\r
-        mimeType2HUmanReadable.put("image/png", "PNG image");\r
-        mimeType2HUmanReadable.put("image/bmp", "Bitmap image");\r
-        mimeType2HUmanReadable.put("image/gif", "GIF image");\r
-        mimeType2HUmanReadable.put("image/svg+xml", "JPEG image");\r
-        mimeType2HUmanReadable.put("image/tiff", "TIFF image");\r
-        // music\r
-        mimeType2HUmanReadable.put("audio/mpeg", "MP3 music file");\r
-        mimeType2HUmanReadable.put("application/ogg", "OGG music file");\r
-\r
-    }\r
-\r
-    private static final String TYPE_APPLICATION = "application";\r
-    private static final String TYPE_AUDIO = "audio";\r
-    private static final String TYPE_IMAGE = "image";\r
-    private static final String TYPE_TXT = "text";\r
-    private static final String TYPE_VIDEO = "video";\r
-    \r
-    private static final String SUBTYPE_PDF = "pdf";\r
-    private static final String[] SUBTYPES_DOCUMENT = { "msword", "mspowerpoint", "msexcel", \r
-                                                        "vnd.oasis.opendocument.presentation",\r
-                                                        "vnd.oasis.opendocument.spreadsheet",\r
-                                                        "vnd.oasis.opendocument.text"\r
-                                                        };\r
-    private static Set<String> SUBTYPES_DOCUMENT_SET = new HashSet<String>(Arrays.asList(SUBTYPES_DOCUMENT));\r
-    private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"};\r
-    private static final Set<String> SUBTYPES_COMPRESSED_SET = new HashSet<String>(Arrays.asList(SUBTYPES_COMPRESSED));\r
-    \r
-    /**\r
-     * Converts the file size in bytes to human readable output.\r
-     * \r
-     * @param bytes Input file size\r
-     * @return Like something readable like "12 MB"\r
-     */\r
-    public static String bytesToHumanReadable(long bytes) {\r
-        double result = bytes;\r
-        int attachedsuff = 0;\r
-        while (result > 1024 && attachedsuff < sizeSuffixes.length) {\r
-            result /= 1024.;\r
-            attachedsuff++;\r
-        }\r
-        result = ((int) (result * 100)) / 100.;\r
-        return result + " " + sizeSuffixes[attachedsuff];\r
-    }\r
-\r
-    /**\r
-     * Removes special HTML entities from a string\r
-     * \r
-     * @param s Input string\r
-     * @return A cleaned version of the string\r
-     */\r
-    public static String HtmlDecode(String s) {\r
-        /*\r
-         * TODO: Perhaps we should use something more proven like:\r
-         * http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#unescapeHtml%28java.lang.String%29\r
-         */\r
-\r
-        String ret = "";\r
-        for (int i = 0; i < s.length(); ++i) {\r
-            if (s.charAt(i) == '%') {\r
-                ret += (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);\r
-                i += 2;\r
-            } else {\r
-                ret += s.charAt(i);\r
-            }\r
-        }\r
-        return ret;\r
-    }\r
-\r
-    /**\r
-     * Converts MIME types like "image/jpg" to more end user friendly output\r
-     * like "JPG image".\r
-     * \r
-     * @param mimetype MIME type to convert\r
-     * @return A human friendly version of the MIME type\r
-     */\r
-    public static String convertMIMEtoPrettyPrint(String mimetype) {\r
-        if (mimeType2HUmanReadable.containsKey(mimetype)) {\r
-            return mimeType2HUmanReadable.get(mimetype);\r
-        }\r
-        if (mimetype.split("/").length >= 2)\r
-            return mimetype.split("/")[1].toUpperCase() + " file";\r
-        return "Unknown type";\r
-    }\r
-    \r
-    \r
-    /**\r
-     * Returns the resource identifier of an image resource to use as icon associated to a \r
-     * known MIME type.\r
-     * \r
-     * @param mimetype      MIME type string.\r
-     * @return              Resource identifier of an image resource.\r
-     */\r
-    public static int getResourceId(String mimetype) {\r
-\r
-        if (mimetype == null || "DIR".equals(mimetype)) {\r
-            return R.drawable.ic_menu_archive;\r
-            \r
-        } else {\r
-            String [] parts = mimetype.split("/");\r
-            String type = parts[0];\r
-            String subtype = (parts.length > 1) ? parts[1] : "";\r
-            \r
-            if(TYPE_TXT.equals(type)) {\r
-                return R.drawable.file_doc;\r
-    \r
-            } else if(TYPE_IMAGE.equals(type)) {\r
-                return R.drawable.file_image;\r
-                \r
-            } else if(TYPE_VIDEO.equals(type)) {\r
-                return R.drawable.file_movie;\r
-                \r
-            } else if(TYPE_AUDIO.equals(type)) {  \r
-                return R.drawable.file_sound;\r
-                \r
-            } else if(TYPE_APPLICATION.equals(type)) {\r
-                \r
-                if (SUBTYPE_PDF.equals(subtype)) {\r
-                    return R.drawable.file_pdf;\r
-                    \r
-                } else if (SUBTYPES_DOCUMENT_SET.contains(subtype)) {\r
-                    return R.drawable.file_doc;\r
-\r
-                } else if (SUBTYPES_COMPRESSED_SET.contains(subtype)) {\r
-                    return R.drawable.file_zip;\r
-                }\r
-    \r
-            }\r
-            // problems: RAR, RTF, 3GP are send as application/octet-stream from the server ; extension in the filename should be explicitly reviewed\r
-        }\r
-\r
-        // default icon\r
-        return R.drawable.file;\r
-    }\r
-\r
-    \r
-\r
-    /**\r
-     * Converts Unix time to human readable format\r
-     * @param miliseconds that have passed since 01/01/1970\r
-     * @return The human readable time for the users locale\r
-     */\r
-    public static String unixTimeToHumanReadable(long milliseconds) {\r
-        Date date = new Date(milliseconds);\r
-        return date.toLocaleString();\r
-    }\r
-}\r
diff --git a/src/com/owncloud/android/Log_OC.java b/src/com/owncloud/android/Log_OC.java
deleted file mode 100644 (file)
index 5a1be29..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.owncloud.android;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import android.util.Log;
-
-
-
-public class Log_OC {
-    
-
-    private static boolean isEnabled = false;
-    private static File logFile;
-    private static File folder;
-    private static BufferedWriter buf;  
-    
-    public static void i(String TAG, String message){
-        // Printing the message to LogCat console
-        Log.i(TAG, message);
-        // Write the log message to the file
-        appendLog(TAG+" : "+message);
-    }
-
-    public static void d(String TAG, String message){
-        Log.d(TAG, message);
-        appendLog(TAG + " : " + message);
-    }
-    public static void d(String TAG, String message, Exception e) {
-        Log.d(TAG, message, e);
-        appendLog(TAG + " : " + message + " Exception : "+ e.getStackTrace());
-    }
-    public static void e(String TAG, String message){
-        Log.e(TAG, message);
-        appendLog(TAG + " : " + message);
-    }
-    
-    public static void e(String TAG, String message, Throwable e) {
-        Log.e(TAG, message, e);
-        appendLog(TAG+" : " + message +" Exception : " + e.getStackTrace());
-    }
-    
-    public static void v(String TAG, String message){
-        Log.v(TAG, message);
-        appendLog(TAG+" : "+ message);
-    }
-    
-    public static void w(String TAG, String message) {
-        Log.w(TAG,message); 
-        appendLog(TAG+" : "+ message);
-    }
-    
-    public static void wtf(String TAG, String message) {
-        Log.wtf(TAG,message); 
-        appendLog(TAG+" : "+ message);
-    }
-    
-    public static void startLogging(String logPath) {
-        folder = new File(logPath);
-        logFile = new File(folder + File.separator + "log.txt");
-        
-        if (!folder.exists()) {
-            folder.mkdirs();
-        }
-        if (logFile.exists()) {
-            logFile.delete();
-        }
-        try { 
-            logFile.createNewFile();
-            buf = new BufferedWriter(new FileWriter(logFile, true));
-            isEnabled = true;
-            appendPhoneInfo();
-        }catch (IOException e){ 
-            e.printStackTrace(); 
-        } 
-    }
-    
-    public static void stopLogging() {
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
-        String currentDateandTime = sdf.format(new Date());
-        if (logFile != null) {
-            logFile.renameTo(new File(folder + File.separator + MainApp.getLogName() + currentDateandTime+".log"));
-          
-            isEnabled = false;
-            try {
-                buf.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            } 
-        
-        }
-        
-    }
-    
-    private static void appendPhoneInfo() {
-        appendLog("Model : " + android.os.Build.MODEL);
-        appendLog("Brand : " + android.os.Build.BRAND);
-        appendLog("Product : " + android.os.Build.PRODUCT);
-        appendLog("Device : " + android.os.Build.DEVICE);
-        appendLog("Version-Codename : " + android.os.Build.VERSION.CODENAME);
-        appendLog("Version-Release : " + android.os.Build.VERSION.RELEASE);
-    }
-    
-    private static void appendLog(String text) { 
-        if (isEnabled) {
-           try { 
-               buf.append(text); 
-               buf.newLine(); 
-           } catch (IOException e) { 
-               e.printStackTrace(); 
-        } 
-    }
-}
-
-    
-   
-
-  
-
-   
-   
-}
index 6cd88fe..85718ff 100644 (file)
@@ -57,30 +57,6 @@ public class MainApp extends Application {
         return getAppContext().getResources().getString(R.string.authority);
     }
     
-    //  From AccountAuthenticator
-    //  public static final String AUTH_TOKEN_TYPE_PASSWORD = "owncloud.password";
-    public static String getAuthTokenTypePass() {
-        return getAppContext().getResources().getString(R.string.account_type) + ".password";
-    }
-    
-    //  From AccountAuthenticator
-    //  public static final String AUTH_TOKEN_TYPE_ACCESS_TOKEN = "owncloud.oauth2.access_token";
-    public static String getAuthTokenTypeAccessToken() {
-        return getAppContext().getResources().getString(R.string.account_type) + ".oauth2.access_token";
-    }
-    
-    //  From AccountAuthenticator
-    //  public static final String AUTH_TOKEN_TYPE_REFRESH_TOKEN = "owncloud.oauth2.refresh_token";
-    public static String getAuthTokenTypeRefreshToken() {
-        return getAppContext().getResources().getString(R.string.account_type) + ".oauth2.refresh_token";
-    }
-    
-    //  From AccountAuthenticator
-    //  public static final String AUTH_TOKEN_TYPE_SAML_WEB_SSO_SESSION_COOKIE = "owncloud.saml.web_sso.session_cookie";
-    public static String getAuthTokenTypeSamlSessionCookie() {
-        return getAppContext().getResources().getString(R.string.account_type) +  ".saml.web_sso.session_cookie";
-    }
-    
     //  From ProviderMeta 
     //  public static final String DB_FILE = "owncloud.db";
     public static String getDBFile() {
diff --git a/src/com/owncloud/android/OwnCloudSession.java b/src/com/owncloud/android/OwnCloudSession.java
deleted file mode 100644 (file)
index d7bb609..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* ownCloud Android client application\r
- *   Copyright (C) 2011  Bartek Przybylski\r
- *   Copyright (C) 2012-2013 ownCloud Inc.\r
- *\r
- *   This program is free software: you can redistribute it and/or modify\r
- *   it under the terms of the GNU General Public License version 2,\r
- *   as published by the Free Software Foundation.\r
- *\r
- *   This program is distributed in the hope that it will be useful,\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *   GNU General Public License for more details.\r
- *\r
- *   You should have received a copy of the GNU General Public License\r
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
- *\r
- */\r
-package com.owncloud.android;\r
-\r
-/**\r
- * Represents a session to an ownCloud instance\r
- * \r
- * @author Bartek Przybylski\r
- * \r
- */\r
-public class OwnCloudSession {\r
-    private String mSessionName;\r
-    private String mSessionUrl;\r
-    private int mEntryId;\r
-\r
-    public OwnCloudSession(String name, String url, int entryId) {\r
-        mSessionName = name;\r
-        mSessionUrl = url;\r
-        mEntryId = entryId;\r
-    }\r
-\r
-    public void setName(String name) {\r
-        mSessionName = name;\r
-    }\r
-\r
-    public String getName() {\r
-        return mSessionName;\r
-    }\r
-\r
-    public void setUrl(String url) {\r
-        mSessionUrl = url;\r
-    }\r
-\r
-    public String getUrl() {\r
-        return mSessionUrl;\r
-    }\r
-\r
-    public int getEntryId() {\r
-        return mEntryId;\r
-    }\r
-}\r
diff --git a/src/com/owncloud/android/Uploader.java b/src/com/owncloud/android/Uploader.java
deleted file mode 100644 (file)
index 29a4d6a..0000000
+++ /dev/null
@@ -1,427 +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;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Stack;
-import java.util.Vector;
-
-import com.owncloud.android.R;
-import com.owncloud.android.authentication.AccountAuthenticator;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileUploader;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
-import android.app.Dialog;
-import android.app.ListActivity;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.provider.MediaStore.Audio;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Video;
-import android.view.View;
-import android.view.Window;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.SimpleAdapter;
-import android.widget.Toast;
-
-
-/**
- * This can be used to upload things to an ownCloud instance.
- * 
- * @author Bartek Przybylski
- * 
- */
-public class Uploader extends ListActivity implements OnItemClickListener, android.view.View.OnClickListener {
-    private static final String TAG = "ownCloudUploader";
-
-    private Account mAccount;
-    private AccountManager mAccountManager;
-    private Stack<String> mParents;
-    private ArrayList<Parcelable> mStreamsToUpload;
-    private boolean mCreateDir;
-    private String mUploadPath;
-    private FileDataStorageManager mStorageManager;
-    private OCFile mFile;
-
-    private final static int DIALOG_NO_ACCOUNT = 0;
-    private final static int DIALOG_WAITING = 1;
-    private final static int DIALOG_NO_STREAM = 2;
-    private final static int DIALOG_MULTIPLE_ACCOUNT = 3;
-
-    private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
-        mParents = new Stack<String>();
-        mParents.add("");
-        if (prepareStreamsToUpload()) {
-            mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
-            Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
-            if (accounts.length == 0) {
-                Log_OC.i(TAG, "No ownCloud account is available");
-                showDialog(DIALOG_NO_ACCOUNT);
-            } else if (accounts.length > 1) {
-                Log_OC.i(TAG, "More then one ownCloud is available");
-                showDialog(DIALOG_MULTIPLE_ACCOUNT);
-            } else {
-                mAccount = accounts[0];
-                mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                populateDirectoryList();
-            }
-        } else {
-            showDialog(DIALOG_NO_STREAM);
-        }
-    }
-    
-    @Override
-    protected Dialog onCreateDialog(final int id) {
-        final AlertDialog.Builder builder = new Builder(this);
-        switch (id) {
-        case DIALOG_WAITING:
-            ProgressDialog pDialog = new ProgressDialog(this);
-            pDialog.setIndeterminate(false);
-            pDialog.setCancelable(false);
-            pDialog.setMessage(getResources().getString(R.string.uploader_info_uploading));
-            return pDialog;
-        case DIALOG_NO_ACCOUNT:
-            builder.setIcon(android.R.drawable.ic_dialog_alert);
-            builder.setTitle(R.string.uploader_wrn_no_account_title);
-            builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
-            builder.setCancelable(false);
-            builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) {
-                        // using string value since in API7 this
-                        // constatn is not defined
-                        // in API7 < this constatant is defined in
-                        // Settings.ADD_ACCOUNT_SETTINGS
-                        // and Settings.EXTRA_AUTHORITIES
-                        Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
-                        intent.putExtra("authorities", new String[] { MainApp.getAuthTokenType() });
-                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
-                    } else {
-                        // since in API7 there is no direct call for
-                        // account setup, so we need to
-                        // show our own AccountSetupAcricity, get
-                        // desired results and setup
-                        // everything for ourself
-                        Intent intent = new Intent(getBaseContext(), AccountAuthenticator.class);
-                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
-                    }
-                }
-            });
-            builder.setNegativeButton(R.string.uploader_wrn_no_account_quit_btn_text, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            return builder.create();
-        case DIALOG_MULTIPLE_ACCOUNT:
-            CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
-            for (int i = 0; i < ac.length; ++i) {
-                ac[i] = mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name;
-            }
-            builder.setTitle(R.string.common_choose_account);
-            builder.setItems(ac, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
-                    mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                    populateDirectoryList();
-                }
-            });
-            builder.setCancelable(true);
-            builder.setOnCancelListener(new OnCancelListener() {
-                @Override
-                public void onCancel(DialogInterface dialog) {
-                    dialog.cancel();
-                    finish();
-                }
-            });
-            return builder.create();
-        case DIALOG_NO_STREAM:
-            builder.setIcon(android.R.drawable.ic_dialog_alert);
-            builder.setTitle(R.string.uploader_wrn_no_content_title);
-            builder.setMessage(R.string.uploader_wrn_no_content_text);
-            builder.setCancelable(false);
-            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            return builder.create();
-        default:
-            throw new IllegalArgumentException("Unknown dialog id: " + id);
-        }
-    }
-
-    class a implements OnClickListener {
-        String mPath;
-        EditText mDirname;
-
-        public a(String path, EditText dirname) {
-            mPath = path; 
-            mDirname = dirname;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            Uploader.this.mUploadPath = mPath + mDirname.getText().toString();
-            Uploader.this.mCreateDir = true;
-            uploadFiles();
-        }
-    }
-
-    @Override
-    public void onBackPressed() {
-
-        if (mParents.size() <= 1) {
-            super.onBackPressed();
-            return;
-        } else {
-            mParents.pop();
-            populateDirectoryList();
-        }
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        // click on folder in the list
-        Log_OC.d(TAG, "on item click");
-        Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
-        if (tmpfiles.size() <= 0) return;
-        // filter on dirtype
-        Vector<OCFile> files = new Vector<OCFile>();
-        for (OCFile f : tmpfiles)
-            if (f.isFolder())
-                files.add(f);
-        if (files.size() < position) {
-            throw new IndexOutOfBoundsException("Incorrect item selected");
-        }
-        mParents.push(files.get(position).getFileName());
-        populateDirectoryList();
-    }
-
-    @Override
-    public void onClick(View v) {
-        // click on button
-        switch (v.getId()) {
-        case R.id.uploader_choose_folder:
-            mUploadPath = "";   // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
-            for (String p : mParents)
-                mUploadPath += p + OCFile.PATH_SEPARATOR;
-            Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
-
-            uploadFiles();
-
-            break;
-        default:
-            throw new IllegalArgumentException("Wrong element clicked");
-        }
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        Log_OC.i(TAG, "result received. req: " + requestCode + " res: " + resultCode);
-        if (requestCode == REQUEST_CODE_SETUP_ACCOUNT) {
-            dismissDialog(DIALOG_NO_ACCOUNT);
-            if (resultCode == RESULT_CANCELED) {
-                finish();
-            }
-            Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAuthTokenType());
-            if (accounts.length == 0) {
-                showDialog(DIALOG_NO_ACCOUNT);
-            } else {
-                // there is no need for checking for is there more then one
-                // account at this point
-                // since account setup can set only one account at time
-                mAccount = accounts[0];
-                populateDirectoryList();
-            }
-        }
-    }
-
-    private void populateDirectoryList() {
-        setContentView(R.layout.uploader_layout);
-
-        String full_path = "";
-        for (String a : mParents)
-            full_path += a + "/";
-        
-        Log_OC.d(TAG, "Populating view with content of : " + full_path);
-        
-        mFile = mStorageManager.getFileByPath(full_path);
-        if (mFile != null) {
-            Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
-            List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
-            for (OCFile f : files) {
-                HashMap<String, Object> h = new HashMap<String, Object>();
-                if (f.isFolder()) {
-                    h.put("dirname", f.getFileName());
-                    data.add(h);
-                }
-            }
-            SimpleAdapter sa = new SimpleAdapter(this,
-                                                data,
-                                                R.layout.uploader_list_item_layout,
-                                                new String[] {"dirname"},
-                                                new int[] {R.id.textView1});
-            setListAdapter(sa);
-            Button btn = (Button) findViewById(R.id.uploader_choose_folder);
-            btn.setOnClickListener(this);
-            getListView().setOnItemClickListener(this);
-        }
-    }
-
-    private boolean prepareStreamsToUpload() {
-        if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
-            mStreamsToUpload = new ArrayList<Parcelable>();
-            mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
-        } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
-            mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
-        }
-        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
-    }
-
-    public void uploadFiles() {
-        try {
-            //WebdavClient 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);
-            }
-            */
-            
-            // 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.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));
-            Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
-        }
-    }
-
-}
index ff0782d..78a8575 100644 (file)
@@ -18,7 +18,6 @@
 
 package com.owncloud.android.authentication;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 
@@ -29,7 +28,8 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.widget.Toast;
 
-
+import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
@@ -53,34 +53,6 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
     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.authentication.AuthenticatorActivity.KEY_OC_BASE_URL} and
-     * {@link com.owncloud.android.utils.OwnCloudVersion}
-     * 
-     * @deprecated
-     */
-    public static final String KEY_OC_URL = "oc_url";
-    /**
-     * Version should be 3 numbers separated by dot so it can be parsed by
-     * {@link com.owncloud.android.utils.OwnCloudVersion}
-     */
-    public static final String KEY_OC_VERSION = "oc_version";
-    /**
-     * Base url should point to owncloud installation without trailing / ie:
-     * http://server/path or https://owncloud.server
-     */
-    public static final String KEY_OC_BASE_URL = "oc_base_url";
-    /**
-     * Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
-     */
-    public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
-    /**
-     * Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
-     */
-    public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
-    
     private static final String TAG = AccountAuthenticator.class.getSimpleName();
     
     private Context mContext;
@@ -204,7 +176,7 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
         /// check if required token is stored
         final AccountManager am = AccountManager.get(mContext);
         String accessToken;
-        if (authTokenType.equals(MainApp.getAuthTokenTypePass())) {
+        if (authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType()))) {
             accessToken = am.getPassword(account);
         } else {
             accessToken = am.peekAuthToken(account, authTokenType);
@@ -285,10 +257,10 @@ public class AccountAuthenticator extends AbstractAccountAuthenticator {
     private void validateAuthTokenType(String authTokenType)\r
             throws UnsupportedAuthTokenTypeException {\r
         if (!authTokenType.equals(MainApp.getAuthTokenType()) &&\r
-            !authTokenType.equals(MainApp.getAuthTokenTypePass()) &&\r
-            !authTokenType.equals(MainApp.getAuthTokenTypeAccessToken()) &&\r
-            !authTokenType.equals(MainApp.getAuthTokenTypeRefreshToken()) &&
-            !authTokenType.equals(MainApp.getAuthTokenTypeSamlSessionCookie())) {\r
+            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType())) &&\r
+            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType())) &&\r
+            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeRefreshToken(MainApp.getAccountType())) &&
+            !authTokenType.equals(AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()))) {\r
             throw new UnsupportedAuthTokenTypeException();\r
         }\r
     }\r
index 3b79c39..33c7e6a 100644 (file)
 package com.owncloud.android.authentication;\r
 \r
 import com.owncloud.android.MainApp;\r
-import com.owncloud.android.utils.OwnCloudVersion;\r
+import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;\r
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;\r
 \r
 import android.accounts.Account;\r
 import android.accounts.AccountManager;\r
-import android.accounts.AccountsException;\r
 import android.content.Context;\r
 import android.content.SharedPreferences;\r
 import android.preference.PreferenceManager;\r
@@ -127,30 +127,6 @@ public class AccountUtils {
     }\r
 \r
     /**\r
-     * \r
-     * @param version version of owncloud\r
-     * @return webdav path for given OC version, null if OC version unknown\r
-     */\r
-    public static String getWebdavPath(OwnCloudVersion version, boolean supportsOAuth, boolean supportsSamlSso) {\r
-        if (version != null) {\r
-            if (supportsOAuth) {\r
-                return ODAV_PATH;\r
-            }\r
-            if (supportsSamlSso) {\r
-                return SAML_SSO_PATH;\r
-            }\r
-            if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)\r
-                return WEBDAV_PATH_4_0;\r
-            if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0\r
-                    || version.compareTo(OwnCloudVersion.owncloud_v2) >= 0)\r
-                return WEBDAV_PATH_2_0;\r
-            if (version.compareTo(OwnCloudVersion.owncloud_v1) >= 0)\r
-                return WEBDAV_PATH_1_2;\r
-        }\r
-        return null;\r
-    }\r
-    \r
-    /**\r
      * Returns the proper URL path to access the WebDAV interface of an ownCloud server,\r
      * according to its version and the authorization method used.\r
      * \r
@@ -160,10 +136,10 @@ public class AccountUtils {
      */\r
     public static String getWebdavPath(OwnCloudVersion version, String authTokenType) {\r
         if (version != null) {\r
-            if (MainApp.getAuthTokenTypeAccessToken().equals(authTokenType)) {\r
+            if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(authTokenType)) {\r
                 return ODAV_PATH;\r
             }\r
-            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(authTokenType)) {\r
+            if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(authTokenType)) {\r
                 return SAML_SSO_PATH;\r
             }\r
             if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0)\r
@@ -177,44 +153,4 @@ public class AccountUtils {
         return null;\r
     }\r
     \r
-    /**\r
-     * Constructs full url to host and webdav resource basing on host version\r
-     * @param context\r
-     * @param account\r
-     * @return url or null on failure\r
-     * @throws AccountNotFoundException     When 'account' is unknown for the AccountManager\r
-     */\r
-    public static String constructFullURLForAccount(Context context, Account account) throws AccountNotFoundException {\r
-        AccountManager ama = AccountManager.get(context);\r
-        String baseurl = ama.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL);\r
-        String strver  = ama.getUserData(account, AccountAuthenticator.KEY_OC_VERSION);\r
-        boolean supportsOAuth = (ama.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);\r
-        boolean supportsSamlSso = (ama.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null);\r
-        OwnCloudVersion ver = new OwnCloudVersion(strver);\r
-        String webdavpath = getWebdavPath(ver, supportsOAuth, supportsSamlSso);\r
-\r
-        if (baseurl == null || webdavpath == null) \r
-            throw new AccountNotFoundException(account, "Account not found", null);\r
-        \r
-        return baseurl + webdavpath;\r
-    }\r
-    \r
-    \r
-    public static class AccountNotFoundException extends AccountsException {\r
-        \r
-        /** Generated - should be refreshed every time the class changes!! */\r
-        private static final long serialVersionUID = -9013287181793186830L;\r
-        \r
-        private Account mFailedAccount; \r
-                \r
-        public AccountNotFoundException(Account failedAccount, String message, Throwable cause) {\r
-            super(message, cause);\r
-            mFailedAccount = failedAccount;\r
-        }\r
-        \r
-        public Account getFailedAccount() {\r
-            return mFailedAccount;\r
-        }\r
-    }\r
-\r
 }\r
index faeffd5..6928d41 100644 (file)
@@ -51,25 +51,25 @@ import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;\r
 \r
 import com.actionbarsherlock.app.SherlockDialogFragment;\r
-import com.owncloud.android.Log_OC;\r
 import com.owncloud.android.MainApp;\r
 import com.owncloud.android.R;\r
 import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;\r
-import com.owncloud.android.network.OwnCloudClientUtils;\r
+import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;\r
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;\r
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
 import com.owncloud.android.operations.ExistenceCheckOperation;\r
 import com.owncloud.android.operations.OAuth2GetAccessToken;\r
-import com.owncloud.android.operations.OnRemoteOperationListener;\r
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;\r
 import com.owncloud.android.operations.OwnCloudServerCheckOperation;\r
-import com.owncloud.android.operations.RemoteOperation;\r
-import com.owncloud.android.operations.RemoteOperationResult;\r
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;\r
+import com.owncloud.android.oc_framework.operations.RemoteOperation;\r
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;\r
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;\r
 import com.owncloud.android.ui.dialog.SamlWebViewDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;\r
-import com.owncloud.android.utils.OwnCloudVersion;\r
-\r
-\r
-import eu.alefzero.webdav.WebdavClient;\r
+import com.owncloud.android.utils.Log_OC;\r
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;\r
 \r
 /**\r
  * This Activity is used to add an ownCloud account to the App\r
@@ -236,11 +236,11 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             /// retrieve extras from intent\r
             mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);\r
             if (mAccount != null) {\r
-                String ocVersion = mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION);\r
+                String ocVersion = mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION);\r
                 if (ocVersion != null) {\r
                     mDiscoveredVersion = new OwnCloudVersion(ocVersion);\r
                 }\r
-                mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL));\r
+                mHostBaseUrl = normalizeUrl(mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL));\r
                 mHostUrlInput.setText(mHostBaseUrl);\r
                 String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));\r
                 mUsernameInput.setText(userName);\r
@@ -279,7 +279,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mAccount = savedInstanceState.getParcelable(KEY_ACCOUNT);\r
             mAuthTokenType = savedInstanceState.getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
             if (mAuthTokenType == null) {\r
-                mAuthTokenType =  MainApp.getAuthTokenTypePass();\r
+                mAuthTokenType =  AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
                 \r
             }\r
 \r
@@ -317,7 +317,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         if (mServerIsChecked && !mServerIsValid && refreshButtonEnabled) showRefreshButton();\r
         mOkButton.setEnabled(mServerIsValid); // state not automatically recovered in configuration changes\r
 \r
-        if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) || \r
+        if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) || \r
                 !AUTH_OPTIONAL.equals(getString(R.string.auth_method_oauth2))) {\r
             mOAuth2Check.setVisibility(View.GONE);\r
         }\r
@@ -369,7 +369,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             @Override\r
             public boolean onTouch(View view, MotionEvent event) {\r
                 if (event.getAction() == MotionEvent.ACTION_DOWN) {\r
-                    if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) &&\r
+                    if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&\r
                             mHostUrlInput.hasFocus()) {\r
                         checkOcServer();\r
                     }\r
@@ -393,8 +393,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         if (mAuthTokenType == null) {    \r
             if (mAccount != null) {\r
                 /// same authentication method than the one used to create the account to update\r
-                oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);\r
-                samlWebSsoRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null);\r
+                oAuthRequired = (mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2) != null);\r
+                samlWebSsoRequired = (mAccountMgr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null);\r
             \r
             } else {\r
                 /// use the one set in setup.xml\r
@@ -402,11 +402,11 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 samlWebSsoRequired = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));            \r
             }\r
             if (oAuthRequired) {\r
-                mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();\r
+                mAuthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
             } else if (samlWebSsoRequired) {\r
-                mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();\r
+                mAuthTokenType = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());\r
             } else {\r
-                mAuthTokenType = MainApp.getAuthTokenTypePass();\r
+                mAuthTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
             }\r
         }\r
     \r
@@ -415,7 +415,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mUsernameInput.setText(userName);\r
         }\r
         \r
-        mOAuth2Check.setChecked(MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType));\r
+        mOAuth2Check.setChecked(AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType));\r
         \r
     }\r
 \r
@@ -488,10 +488,10 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     protected void onResume() {\r
         super.onResume();\r
         if (mAction == ACTION_UPDATE_TOKEN && mJustCreated && getIntent().getBooleanExtra(EXTRA_ENFORCED_UPDATE, false)) {\r
-            if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
+            if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 //Toast.makeText(this, R.string.auth_expired_oauth_token_toast, Toast.LENGTH_LONG).show();\r
                 showAuthMessage(getString(R.string.auth_expired_oauth_token_toast));\r
-            } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
+            } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 //Toast.makeText(this, R.string.auth_expired_saml_sso_token_toast, Toast.LENGTH_LONG).show();\r
                 showAuthMessage(getString(R.string.auth_expired_saml_sso_token_toast));\r
             } else {\r
@@ -527,7 +527,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 getString(R.string.oauth2_grant_type),\r
                 queryParameters);\r
         //WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
-        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
+        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
         operation.execute(client, this, mHandler);\r
     }\r
 \r
@@ -591,7 +591,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mServerStatusIcon = R.drawable.progress_small;\r
             showServerStatus();\r
             mOcServerChkOperation = new  OwnCloudServerCheckOperation(uri, this);\r
-            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this, true);\r
+            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);\r
             mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);\r
         } else {\r
             mServerStatusText = 0;\r
@@ -691,9 +691,9 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             return;\r
         }\r
 \r
-        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
+        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
             startOauthorization();\r
-        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) { \r
+        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) { \r
             startSamlBasedFederatedSingleSignOnAuthorization();\r
         } else {\r
             checkBasicAuthorization();\r
@@ -718,7 +718,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         /// test credentials accessing the root folder\r
         mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
-        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
+        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
         client.setBasicCredentials(username, password);\r
         mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
     }\r
@@ -767,7 +767,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
         /// test credentials accessing the root folder\r
         mAuthCheckOperation = new  ExistenceCheckOperation("", this, false);\r
-        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
+        WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);\r
         mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);\r
       \r
     }\r
@@ -787,7 +787,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);\r
 \r
         } else if (operation instanceof ExistenceCheckOperation)  {\r
-            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
+            if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 onSamlBasedFederatedSingleSignOnAuthorizationStart(operation, result);\r
                 \r
             } else {\r
@@ -1086,7 +1086,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
             Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);\r
             mAuthCheckOperation = new ExistenceCheckOperation("", this, false);\r
-            WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
+            WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);\r
             client.setBearerCredentials(mAuthToken);\r
             mAuthCheckOperation.execute(client, this, mHandler);\r
 \r
@@ -1172,12 +1172,12 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
         response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);\r
         response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);\r
         \r
-        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) { \r
+        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) { \r
             response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);\r
             // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention\r
             mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
             \r
-        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
+        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
             String username = getUserNameForSamlSso();\r
             if (!mUsernameInput.getText().toString().equals(username)) {\r
                 // fail - not a new account, but an existing one; disallow\r
@@ -1212,8 +1212,8 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
      */\r
     private boolean createAccount() {\r
         /// create and save new ownCloud account\r
-        boolean isOAuth = MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType);\r
-        boolean isSaml =  MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType);\r
+        boolean isOAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType);\r
+        boolean isSaml =  AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType);\r
 \r
         Uri uri = Uri.parse(mHostBaseUrl);\r
         String username = mUsernameInput.getText().toString().trim();\r
@@ -1265,12 +1265,12 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
                 mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
             }\r
             /// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA\r
-            mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION,    mDiscoveredVersion.toString());\r
-            mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL,   mHostBaseUrl);\r
+            mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION,    mDiscoveredVersion.toString());\r
+            mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL,   mHostBaseUrl);\r
             if (isSaml) {\r
-                mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
+                mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
             } else if (isOAuth) {\r
-                mAccountMgr.setUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE");  \r
+                mAccountMgr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_SUPPORTS_OAUTH2, "TRUE");  \r
             }\r
     \r
             setAccountAuthenticatorResult(intent.getExtras());\r
@@ -1482,9 +1482,9 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
     public void onCheckClick(View view) {\r
         CheckBox oAuth2Check = (CheckBox)view;\r
         if (oAuth2Check.isChecked()) {\r
-            mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();\r
+            mAuthTokenType = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
         } else {\r
-            mAuthTokenType = MainApp.getAuthTokenTypePass();\r
+            mAuthTokenType = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
         }\r
         adaptViewAccordingToAuthenticationMethod();\r
     }\r
@@ -1495,14 +1495,14 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
      * the current authorization method.\r
      */\r
     private void adaptViewAccordingToAuthenticationMethod () {\r
-        if (MainApp.getAuthTokenTypeAccessToken().equals(mAuthTokenType)) {\r
+        if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
             // OAuth 2 authorization\r
             mOAuthAuthEndpointText.setVisibility(View.VISIBLE);\r
             mOAuthTokenEndpointText.setVisibility(View.VISIBLE);\r
             mUsernameInput.setVisibility(View.GONE);\r
             mPasswordInput.setVisibility(View.GONE);\r
             \r
-        } else if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
+        } else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
             // SAML-based web Single Sign On\r
             mOAuthAuthEndpointText.setVisibility(View.GONE);\r
             mOAuthTokenEndpointText.setVisibility(View.GONE);\r
@@ -1548,7 +1548,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
             }\r
             \r
         } else if (actionId == EditorInfo.IME_ACTION_NEXT && inputField != null && inputField.equals(mHostUrlInput)) {\r
-            if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType)) {\r
+            if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 checkOcServer();\r
             }\r
         }\r
@@ -1647,7 +1647,7 @@ implements  OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
 \r
     @Override\r
     public boolean onTouchEvent(MotionEvent event) {\r
-        if (MainApp.getAuthTokenTypeSamlSessionCookie().equals(mAuthTokenType) &&\r
+        if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&\r
                 mHostUrlInput.hasFocus() && event.getAction() == MotionEvent.ACTION_DOWN) {\r
             checkOcServer();\r
         }\r
index 5c97931..8d80e9b 100644 (file)
@@ -19,7 +19,7 @@ package com.owncloud.android.authentication;
 
 import java.lang.ref.WeakReference;
 
-import com.owncloud.android.Log_OC;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.graphics.Bitmap;
index 0ad985e..fb55e93 100644 (file)
@@ -25,10 +25,10 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.Vector;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
index 67de500..a6e6a54 100644 (file)
@@ -20,7 +20,7 @@ package com.owncloud.android.datamodel;
 
 import java.io.File;
 
-import com.owncloud.android.Log_OC;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.os.Parcel;
index 0ba7b0c..89864fe 100644 (file)
@@ -17,8 +17,8 @@
  */
 package com.owncloud.android.db;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
+import com.owncloud.android.utils.Log_OC;
 
 import android.content.ContentValues;
 import android.content.Context;
index 8a8c430..e90e8d4 100644 (file)
@@ -18,8 +18,8 @@
 
 package com.owncloud.android.files;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.files.services.FileObserverService;
+import com.owncloud.android.utils.Log_OC;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
index fbb6888..1943d32 100644 (file)
@@ -20,12 +20,12 @@ package com.owncloud.android.files;
 
 import java.io.File;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
index 964b61c..68c97e4 100644 (file)
@@ -20,13 +20,13 @@ package com.owncloud.android.files;
 
 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.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFileOperation;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.content.Context;
index 2e479f4..232a042 100644 (file)
@@ -28,23 +28,22 @@ import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.network.OwnCloudClientUtils;
+
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
 import com.owncloud.android.operations.DownloadFileOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.accounts.AccountsException;
@@ -62,8 +61,6 @@ import android.os.Message;
 import android.os.Process;
 import android.widget.RemoteViews;
 
-import eu.alefzero.webdav.WebdavClient;
-
 public class FileDownloader extends Service implements OnDatatransferProgressListener {
     
     public static final String EXTRA_ACCOUNT = "ACCOUNT";
@@ -355,7 +352,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
                 if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
                     mLastAccount = mCurrentDownload.getAccount();
                     mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                    mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
+                    mDownloadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
                 }
 
                 /// perform the download
@@ -476,7 +473,8 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
                                                 // (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection()
                                                   (downloadResult.isIdPRedirection()
-                                                        && MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
+                                                        && mDownloadClient.getCredentials() == null));
+                                                        //&& MainApp.getAuthTokenTypeSamlSessionCookie().equals(mDownloadClient.getAuthTokenType())));
             if (needsToUpdateCredentials) {
                 // let the user update credentials with one click
                 Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
index 502d459..fa1fec2 100644 (file)
@@ -22,13 +22,13 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.files.OwnCloudFileObserver;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
index 7f45b6b..d9f3a32 100644 (file)
@@ -33,7 +33,6 @@ import org.apache.jackrabbit.webdav.DavConstants;
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountAuthenticator;
@@ -41,27 +40,27 @@ import com.owncloud.android.authentication.AuthenticatorActivity;
 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.CreateFolderOperation;
 import com.owncloud.android.operations.ExistenceCheckOperation;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.operations.UploadFileOperation;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
 import com.owncloud.android.ui.activity.FailedUploadActivity;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.InstantUploadActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
-import com.owncloud.android.utils.OwnCloudVersion;
-
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-import eu.alefzero.webdav.WebdavEntry;
-import eu.alefzero.webdav.WebdavUtils;
-
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -82,7 +81,6 @@ import android.webkit.MimeTypeMap;
 import android.widget.RemoteViews;
 
 
-import eu.alefzero.webdav.WebdavClient;
 
 public class FileUploader extends Service implements OnDatatransferProgressListener {
 
@@ -261,8 +259,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             }
         }
 
-        OwnCloudVersion ocv = new OwnCloudVersion(AccountManager.get(this).getUserData(account,
-                AccountAuthenticator.KEY_OC_VERSION));
+        OwnCloudVersion ocv = new OwnCloudVersion(AccountManager.get(this).getUserData(account, OwnCloudAccount.Constants.KEY_OC_VERSION));
         boolean chunked = FileUploader.chunkedUploadIsSupported(ocv);
         AbstractList<String> requestedUploads = new Vector<String>();
         String uploadKey = null;
@@ -504,7 +501,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
                     mLastAccount = mCurrentUpload.getAccount();
                     mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                    mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
+                    mUploadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
                 }
                 
                 /// check the existence of the parent folder for the file to upload
@@ -567,9 +564,9 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
         RemoteOperation operation = new ExistenceCheckOperation(pathToGrant, this, false);
         RemoteOperationResult result = operation.execute(mUploadClient);
         if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) {
-            operation = new CreateFolderOperation(  pathToGrant,
-                                                    true,
-                                                    mStorageManager    );
+            operation = new CreateFolderOperation( pathToGrant,
+                    true,
+                    mStorageManager    );
             result = operation.execute(mUploadClient);
         }
         if (result.isSuccess()) {
@@ -823,7 +820,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
                     //(uploadResult.isTemporalRedirection() && uploadResult.isIdPRedirection() && 
                     (uploadResult.isIdPRedirection() &&
-                            MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
+                            mUploadClient.getCredentials() == null));
+                            //MainApp.getAuthTokenTypeSamlSessionCookie().equals(mUploadClient.getAuthTokenType())));
             if (needsToUpdateCredentials) {
                 // let the user update credentials with one click
                 Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
index eb57222..0a74635 100644 (file)
@@ -37,11 +37,11 @@ import android.widget.Toast;
 
 import java.io.IOException;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
index ab018f6..d2a42c7 100644 (file)
@@ -18,9 +18,9 @@
 package com.owncloud.android.media;
 
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaService.State;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.content.Intent;
diff --git a/src/com/owncloud/android/network/AdvancedSslSocketFactory.java b/src/com/owncloud/android/network/AdvancedSslSocketFactory.java
deleted file mode 100644 (file)
index 6a69871..0000000
+++ /dev/null
@@ -1,241 +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.network;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-
-import org.apache.commons.httpclient.ConnectTimeoutException;
-import org.apache.commons.httpclient.params.HttpConnectionParams;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-
-import com.owncloud.android.Log_OC;
-
-
-/**
- * AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with 
- * a custom SSLContext and an optional Hostname Verifier.
- * 
- * @author David A. Velasco
- */
-
-public class AdvancedSslSocketFactory implements ProtocolSocketFactory {
-
-    private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
-    
-    private SSLContext mSslContext = null;
-    private AdvancedX509TrustManager mTrustManager = null;
-    private X509HostnameVerifier mHostnameVerifier = null;
-
-    public SSLContext getSslContext() {
-        return mSslContext;
-    }
-    
-    /**
-     * Constructor for AdvancedSSLProtocolSocketFactory.
-     */
-    public AdvancedSslSocketFactory(SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier) {
-        if (sslContext == null)
-            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
-        if (trustManager == null)
-            throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null Trust Manager");
-        mSslContext = sslContext;
-        mTrustManager = trustManager;
-        mHostnameVerifier = hostnameVerifier;
-    }
-
-    /**
-     * @see ProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
-     */
-    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
-        Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
-        verifyPeerIdentity(host, port, socket);
-        return socket;
-    }
-
-    
-    /**
-     * Attempts to get a new socket connection to the given host within the
-     * given time limit.
-     * 
-     * @param host the host name/IP
-     * @param port the port on the host
-     * @param clientHost the local host name/IP to bind the socket to
-     * @param clientPort the port on the local machine
-     * @param params {@link HttpConnectionParams Http connection parameters}
-     * 
-     * @return Socket a new socket
-     * 
-     * @throws IOException if an I/O error occurs while creating the socket
-     * @throws UnknownHostException if the IP address of the host cannot be
-     *             determined
-     */
-    public Socket createSocket(final String host, final int port,
-            final InetAddress localAddress, final int localPort,
-            final HttpConnectionParams params) throws IOException,
-            UnknownHostException, ConnectTimeoutException {
-        Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" + localPort + ", params: " + params);
-        if (params == null) {
-            throw new IllegalArgumentException("Parameters may not be null");
-        } 
-        int timeout = params.getConnectionTimeout();
-        SocketFactory socketfactory = mSslContext.getSocketFactory();
-        Log_OC.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
-        Socket socket = socketfactory.createSocket();
-        SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
-        SocketAddress remoteaddr = new InetSocketAddress(host, port);
-        socket.setSoTimeout(params.getSoTimeout());
-        socket.bind(localaddr);
-        socket.connect(remoteaddr, timeout);
-        verifyPeerIdentity(host, port, socket);
-        return socket;
-    }
-
-    /**
-     * @see ProtocolSocketFactory#createSocket(java.lang.String,int)
-     */
-    public Socket createSocket(String host, int port) throws IOException,
-            UnknownHostException {
-        Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
-        Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
-        verifyPeerIdentity(host, port, socket);
-        return socket; 
-    }
-
-    public boolean equals(Object obj) {
-        return ((obj != null) && obj.getClass().equals(
-                AdvancedSslSocketFactory.class));
-    }
-
-    public int hashCode() {
-        return AdvancedSslSocketFactory.class.hashCode();
-    }
-
-
-    public X509HostnameVerifier getHostNameVerifier() {
-        return mHostnameVerifier;
-    }
-    
-    
-    public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
-        mHostnameVerifier = hostnameVerifier;
-    }
-    
-    /**
-     * Verifies the identity of the server. 
-     * 
-     * The server certificate is verified first.
-     * 
-     * Then, the host name is compared with the content of the server certificate using the current host name verifier, if any.
-     * @param socket
-     */
-    private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
-        try {
-            CertificateCombinedException failInHandshake = null;
-            /// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager (that should be an instance of AdvancedX509TrustManager) 
-            try {
-                SSLSocket sock = (SSLSocket) socket;    // a new SSLSession instance is created as a "side effect" 
-                sock.startHandshake();
-                
-            } catch (RuntimeException e) {
-                
-                if (e instanceof CertificateCombinedException) {
-                    failInHandshake = (CertificateCombinedException) e;
-                } else {
-                    Throwable cause = e.getCause();
-                    Throwable previousCause = null;
-                    while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
-                        previousCause = cause;
-                        cause = cause.getCause();
-                    }
-                    if (cause != null && cause instanceof CertificateCombinedException) {
-                        failInHandshake = (CertificateCombinedException)cause;
-                    }
-                }
-                if (failInHandshake == null) {
-                    throw e;
-                }
-                failInHandshake.setHostInUrl(host);
-                
-            }
-            
-            /// 2. VERIFY HOSTNAME
-            SSLSession newSession = null;
-            boolean verifiedHostname = true;
-            if (mHostnameVerifier != null) {
-                if (failInHandshake != null) {
-                    /// 2.1 : a new SSLSession instance was NOT created in the handshake
-                    X509Certificate serverCert = failInHandshake.getServerCertificate();
-                    try {
-                        mHostnameVerifier.verify(host, serverCert);
-                    } catch (SSLException e) {
-                        verifiedHostname = false;
-                    }
-                
-                } else {
-                    /// 2.2 : a new SSLSession instance was created in the handshake
-                    newSession = ((SSLSocket)socket).getSession();
-                    if (!mTrustManager.isKnownServer((X509Certificate)(newSession.getPeerCertificates()[0]))) {
-                        verifiedHostname = mHostnameVerifier.verify(host, newSession); 
-                    }
-                }
-            }
-
-            /// 3. Combine the exceptions to throw, if any
-            if (!verifiedHostname) {
-                SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException("Names in the server certificate do not match to " + host + " in the URL");
-                if (failInHandshake == null) {
-                    failInHandshake = new CertificateCombinedException((X509Certificate) newSession.getPeerCertificates()[0]);
-                    failInHandshake.setHostInUrl(host);
-                }
-                failInHandshake.setSslPeerUnverifiedException(pue);
-                pue.initCause(failInHandshake);
-                throw pue;
-                
-            } else if (failInHandshake != null) {
-                SSLHandshakeException hse = new SSLHandshakeException("Server certificate could not be verified");
-                hse.initCause(failInHandshake);
-                throw hse;
-            }
-            
-        } catch (IOException io) {        
-            try {
-                socket.close();
-            } catch (Exception x) {
-                // NOTHING - irrelevant exception for the caller 
-            }
-            throw io;
-        }
-    }
-
-}
diff --git a/src/com/owncloud/android/network/AdvancedX509TrustManager.java b/src/com/owncloud/android/network/AdvancedX509TrustManager.java
deleted file mode 100644 (file)
index 81dcdbd..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* 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.network;
-
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import com.owncloud.android.Log_OC;
-
-
-/**
- * @author David A. Velasco
- */
-public class AdvancedX509TrustManager implements X509TrustManager {
-    
-    private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
-
-    private X509TrustManager mStandardTrustManager = null;
-    private KeyStore mKnownServersKeyStore;
-
-    /**
-     * Constructor for AdvancedX509TrustManager
-     * 
-     * @param  knownServersCertStore    Local certificates store with server certificates explicitly trusted by the user.
-     * @throws CertStoreException       When no default X509TrustManager instance was found in the system.
-     */
-    public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
-            throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
-        super();
-        TrustManagerFactory factory = TrustManagerFactory
-                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
-        factory.init((KeyStore)null);
-        mStandardTrustManager = findX509TrustManager(factory);
-
-        mKnownServersKeyStore = knownServersKeyStore;
-    }
-    
-    
-    /**
-     * Locates the first X509TrustManager provided by a given TrustManagerFactory
-     * @param factory               TrustManagerFactory to inspect in the search for a X509TrustManager
-     * @return                      The first X509TrustManager found in factory.
-     * @throws CertStoreException   When no X509TrustManager instance was found in factory
-     */
-    private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
-        TrustManager tms[] = factory.getTrustManagers();
-        for (int i = 0; i < tms.length; i++) {
-            if (tms[i] instanceof X509TrustManager) {
-                return (X509TrustManager) tms[i];
-            }
-        }
-        return null;
-    }
-    
-
-    /**
-     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
-     *      String authType)
-     */
-    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
-        mStandardTrustManager.checkClientTrusted(certificates, authType);
-    }
-
-    
-    /**
-     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
-     *      String authType)
-     */
-    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
-        if (!isKnownServer(certificates[0])) {
-               CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
-               try {
-                       certificates[0].checkValidity();
-               } catch (CertificateExpiredException c) {
-                       result.setCertificateExpiredException(c);
-                       
-               } catch (CertificateNotYetValidException c) {
-                result.setCertificateNotYetException(c);
-               }
-               
-               try {
-                   mStandardTrustManager.checkServerTrusted(certificates, authType);
-               } catch (CertificateException c) {
-                Throwable cause = c.getCause();
-                Throwable previousCause = null;
-                while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) {     // getCause() is not funny
-                    previousCause = cause;
-                    cause = cause.getCause();
-                }
-                if (cause != null && cause instanceof CertPathValidatorException) {
-                       result.setCertPathValidatorException((CertPathValidatorException)cause);
-                } else {
-                       result.setOtherCertificateException(c);
-                }
-               }
-               
-               if (result.isException())
-                       throw result;
-
-        }
-    }
-    
-    
-    /**
-     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
-     */
-    public X509Certificate[] getAcceptedIssuers() {
-        return mStandardTrustManager.getAcceptedIssuers();
-    }
-
-    
-    public boolean isKnownServer(X509Certificate cert) {
-        try {
-            return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
-        } catch (KeyStoreException e) {
-            Log_OC.d(TAG, "Fail while checking certificate in the known-servers store");
-            return false;
-        }
-    }
-    
-}
\ No newline at end of file
diff --git a/src/com/owncloud/android/network/BearerAuthScheme.java b/src/com/owncloud/android/network/BearerAuthScheme.java
deleted file mode 100644 (file)
index 16791c2..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/* 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");
-    }
-    
-}
diff --git a/src/com/owncloud/android/network/BearerCredentials.java b/src/com/owncloud/android/network/BearerCredentials.java
deleted file mode 100644 (file)
index 50799b0..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* 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;
-    }
-
-}
-
diff --git a/src/com/owncloud/android/network/CertificateCombinedException.java b/src/com/owncloud/android/network/CertificateCombinedException.java
deleted file mode 100644 (file)
index e96d9dc..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* 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.network;
-
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLPeerUnverifiedException;
-
-/**
- * Exception joining all the problems that {@link AdvancedX509TrustManager} can find in
- * a certificate chain for a server.
- * 
- * This was initially created as an extension of CertificateException, but some
- * implementations of the SSL socket layer in existing devices are REPLACING the CertificateException
- * instances thrown by {@link javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], String)}
- * with SSLPeerUnverifiedException FORGETTING THE CAUSING EXCEPTION instead of wrapping it. 
- * 
- * Due to this, extending RuntimeException is necessary to get that the CertificateCombinedException 
- * instance reaches {@link AdvancedSslSocketFactory#verifyPeerIdentity}.
- * 
- * BE CAREFUL. As a RuntimeException extensions, Java compilers do not require to handle it
- * in client methods. Be sure to use it only when you know exactly where it will go.
- * 
- * @author David A. Velasco
- */
-public class CertificateCombinedException extends RuntimeException {
-
-    /** Generated - to refresh every time the class changes */
-    private static final long serialVersionUID = -8875782030758554999L;
-    
-    private X509Certificate mServerCert = null;
-    private String mHostInUrl;
-
-    private CertificateExpiredException mCertificateExpiredException = null;
-    private CertificateNotYetValidException mCertificateNotYetValidException = null;
-    private CertPathValidatorException mCertPathValidatorException = null;
-    private CertificateException mOtherCertificateException = null;
-    private SSLPeerUnverifiedException mSslPeerUnverifiedException = null;
-    
-    public CertificateCombinedException(X509Certificate x509Certificate) {
-        mServerCert = x509Certificate;
-    }
-
-    public X509Certificate getServerCertificate() {
-        return mServerCert;
-    }
-
-    public String getHostInUrl() {
-        return mHostInUrl;
-    }
-
-    public void setHostInUrl(String host) {
-        mHostInUrl = host;
-    }
-
-    public CertificateExpiredException getCertificateExpiredException() {
-        return mCertificateExpiredException;
-    }
-
-    public void setCertificateExpiredException(CertificateExpiredException c) {
-        mCertificateExpiredException  = c;
-    }
-
-    public CertificateNotYetValidException getCertificateNotYetValidException() {
-        return mCertificateNotYetValidException;
-    }
-
-    public void setCertificateNotYetException(CertificateNotYetValidException c) {
-        mCertificateNotYetValidException = c;
-    }
-
-    public CertPathValidatorException getCertPathValidatorException() {
-        return mCertPathValidatorException;
-    }
-
-    public void setCertPathValidatorException(CertPathValidatorException c) {
-        mCertPathValidatorException = c;
-    }
-
-    public CertificateException getOtherCertificateException() {
-        return mOtherCertificateException;
-    }
-
-    public void setOtherCertificateException(CertificateException c) {
-        mOtherCertificateException = c;
-    }
-
-    public SSLPeerUnverifiedException getSslPeerUnverifiedException() {
-        return mSslPeerUnverifiedException ; 
-    }
-
-    public void setSslPeerUnverifiedException(SSLPeerUnverifiedException s) {
-        mSslPeerUnverifiedException = s;
-    }
-
-    public boolean isException() {
-        return (mCertificateExpiredException != null ||
-                mCertificateNotYetValidException != null ||
-                mCertPathValidatorException != null ||
-                mOtherCertificateException != null ||
-                mSslPeerUnverifiedException != null);
-    }
-
-    public boolean isRecoverable() {
-        return (mCertificateExpiredException != null ||
-                mCertificateNotYetValidException != null ||
-                mCertPathValidatorException != null ||
-                mSslPeerUnverifiedException != null);
-    }
-
-}
diff --git a/src/com/owncloud/android/network/OwnCloudClientUtils.java b/src/com/owncloud/android/network/OwnCloudClientUtils.java
deleted file mode 100644 (file)
index bb29938..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/* 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.network;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
-import org.apache.http.conn.ssl.X509HostnameVerifier;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
-import com.owncloud.android.authentication.AccountAuthenticator;
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
-
-
-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.os.Bundle;
-
-public class OwnCloudClientUtils {
-    
-    final private static String TAG = OwnCloudClientUtils.class.getSimpleName();
-    
-    /** Default timeout for waiting data from the server */
-    public static final int DEFAULT_DATA_TIMEOUT = 60000;
-    
-    /** Default timeout for establishing a connection */
-    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
-
-    /** Connection manager for all the WebdavClients */
-    private static MultiThreadedHttpConnectionManager mConnManager = null;
-    
-    private static Protocol mDefaultHttpsProtocol = null;
-
-    private static AdvancedSslSocketFactory mAdvancedSslSocketFactory = null;
-
-    private static X509HostnameVerifier mHostnameVerifier = null;
-    
-    
-    /**
-     * Creates a WebdavClient setup for an ownCloud account
-     * 
-     * 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.
-     * @throws AccountNotFoundException     If 'account' is unknown for the AccountManager
-     */
-    public static WebdavClient createOwnCloudClient (Account account, Context appContext) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
-        //Log_OC.d(TAG, "Creating WebdavClient associated to " + account.name);
-       
-        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        AccountManager am = AccountManager.get(appContext);
-        boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
-        boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null;
-        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
-        if (isOauth2) {    
-            String accessToken = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypeAccessToken(), false);
-            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
-        
-        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
-            String accessToken = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypeSamlSessionCookie(), false);
-            client.setSsoSessionCookie(accessToken);
-            
-        } else {
-            String username = account.name.substring(0, account.name.lastIndexOf('@'));
-            //String password = am.getPassword(account);
-            String password = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypePass(), false);
-            client.setBasicCredentials(username, password);
-        }
-        
-        return client;
-    }
-    
-    
-    public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
-        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
-        AccountManager am = AccountManager.get(appContext);
-        boolean isOauth2 = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null;   // TODO avoid calling to getUserData here
-        boolean isSamlSso = am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_SAML_WEB_SSO) != null;
-        WebdavClient client = createOwnCloudClient(uri, appContext, !isSamlSso);
-        
-        if (isOauth2) {    // TODO avoid a call to getUserData here
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, MainApp.getAuthTokenTypeAccessToken(), null, currentActivity, null, null);
-            Bundle result = future.getResult();
-            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
-            if (accessToken == null) throw new AuthenticatorException("WTF!");
-            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
-
-        } else if (isSamlSso) {    // TODO avoid a call to getUserData here
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, MainApp.getAuthTokenTypeSamlSessionCookie(), null, currentActivity, null, null);
-            Bundle result = future.getResult();
-            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
-            if (accessToken == null) throw new AuthenticatorException("WTF!");
-            client.setSsoSessionCookie(accessToken);
-
-        } else {
-            String username = account.name.substring(0, account.name.lastIndexOf('@'));
-            //String password = am.getPassword(account);
-            //String password = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypePass(), false);
-            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, MainApp.getAuthTokenTypePass(), 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.
-     * 
-     * @param uri       URL to the ownCloud server
-     * @param context   Android context where the WebdavClient is being created.
-     * @return          A WebdavClient object ready to be used
-     */
-    public static WebdavClient createOwnCloudClient(Uri uri, Context context, boolean followRedirects) {
-        try {
-            registerAdvancedSslContext(true, context);
-        }  catch (GeneralSecurityException e) {
-            Log_OC.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in the system will be used for HTTPS connections", e);
-            
-        } catch (IOException e) {
-            Log_OC.e(TAG, "The local server truststore could not be read. Default SSL management in the system will be used for HTTPS connections", e);
-        }
-        
-        WebdavClient client = new WebdavClient(getMultiThreadedConnManager());
-        
-        client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
-        client.setBaseUri(uri);
-        client.setFollowRedirects(followRedirects);
-        
-        return client;
-    }
-    
-    
-    /**
-     * Registers or unregisters the proper components for advanced SSL handling.
-     * @throws IOException 
-     */
-    private static void registerAdvancedSslContext(boolean register, Context context) throws GeneralSecurityException, IOException {
-        Protocol pr = null;
-        try {
-            pr = Protocol.getProtocol("https");
-            if (pr != null && mDefaultHttpsProtocol == null) {
-                mDefaultHttpsProtocol = pr;
-            }
-        } catch (IllegalStateException e) {
-            // nothing to do here; really
-        }
-        boolean isRegistered = (pr != null && pr.getSocketFactory() instanceof AdvancedSslSocketFactory);
-        if (register && !isRegistered) {
-            Protocol.registerProtocol("https", new Protocol("https", getAdvancedSslSocketFactory(context), 443));
-            
-        } else if (!register && isRegistered) {
-            if (mDefaultHttpsProtocol != null) {
-                Protocol.registerProtocol("https", mDefaultHttpsProtocol);
-            }
-        }
-    }
-    
-    public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
-        if (mAdvancedSslSocketFactory  == null) {
-            KeyStore trustStore = getKnownServersStore(context);
-            AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
-            TrustManager[] tms = new TrustManager[] { trustMgr };
-                
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, tms, null);
-                    
-            mHostnameVerifier = new BrowserCompatHostnameVerifier();
-            mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
-        }
-        return mAdvancedSslSocketFactory;
-    }
-
-
-    private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
-    
-    private static String LOCAL_TRUSTSTORE_PASSWORD = "password";
-
-    private static KeyStore mKnownServersStore = null;
-    
-    /**
-     * Returns the local store of reliable server certificates, explicitly accepted by the user.
-     * 
-     * Returns a KeyStore instance with empty content if the local store was never created.
-     * 
-     * Loads the store from the storage environment if needed.
-     * 
-     * @param context                       Android context where the operation is being performed.
-     * @return                              KeyStore instance with explicitly-accepted server certificates. 
-     * @throws KeyStoreException            When the KeyStore instance could not be created.
-     * @throws IOException                  When an existing local trust store could not be loaded.
-     * @throws NoSuchAlgorithmException     When the existing local trust store was saved with an unsupported algorithm.
-     * @throws CertificateException         When an exception occurred while loading the certificates from the local trust store.
-     */
-    private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
-        if (mKnownServersStore == null) {
-            //mKnownServersStore = KeyStore.getInstance("BKS");
-            mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());
-            File localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
-            Log_OC.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
-            if (localTrustStoreFile.exists()) {
-                InputStream in = new FileInputStream(localTrustStoreFile);
-                try {
-                    mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
-                } finally {
-                    in.close();
-                }
-            } else {
-                mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
-            }
-        }
-        return mKnownServersStore;
-    }
-    
-    
-    public static void addCertToKnownServersStore(Certificate cert, Context context) throws  KeyStoreException, NoSuchAlgorithmException, 
-                                                                                            CertificateException, IOException {
-        KeyStore knownServers = getKnownServersStore(context);
-        knownServers.setCertificateEntry(Integer.toString(cert.hashCode()), cert);
-        FileOutputStream fos = null;
-        try {
-            fos = context.openFileOutput(LOCAL_TRUSTSTORE_FILENAME, Context.MODE_PRIVATE);
-            knownServers.store(fos, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
-        } finally {
-            fos.close();
-        }
-    }
-    
-    
-    static private MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
-        if (mConnManager == null) {
-            mConnManager = new MultiThreadedHttpConnectionManager();
-            mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
-            mConnManager.getParams().setMaxTotalConnections(5);
-        }
-        return mConnManager;
-    }
-
-
-}
diff --git a/src/com/owncloud/android/network/ProgressiveDataTransferer.java b/src/com/owncloud/android/network/ProgressiveDataTransferer.java
deleted file mode 100644 (file)
index c6fa545..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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.network;
-
-import java.util.Collection;
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
-public interface ProgressiveDataTransferer {
-
-    public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
-    
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
-
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
-
-}
index 2649d19..fd8a5a6 100644 (file)
@@ -27,16 +27,16 @@ import java.util.Random;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.methods.PutMethod;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.network.ProgressiveDataTransferer;
+import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
+import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
 
-import eu.alefzero.webdav.ChunkFromFileChannelRequestEntity;
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
 
 public class ChunkedUploadFileOperation extends UploadFileOperation {
     
index f28ad29..1cf1f84 100644 (file)
 
 package com.owncloud.android.operations;
 
-import java.io.File;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
-
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
-
 /**
- * Remote operation performing the creation of a new folder in the ownCloud server.
+ * Access to remote operation performing the creation of a new folder in the ownCloud server.
+ * Save the new folder in Database
  * 
  * @author David A. Velasco 
+ * @author masensio
  */
-public class CreateFolderOperation extends RemoteOperation {
+public class CreateFolderOperation extends RemoteOperation implements OnRemoteOperationListener{
     
     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 boolean mCreateFullPath;
@@ -49,7 +46,6 @@ public class CreateFolderOperation extends RemoteOperation {
     /**
      * Constructor
      * 
-     * @param remotePath            Full path to the new directory to create in the remote server.
      * @param createFullPath        'True' means that all the ancestor folders should be created if don't exist yet.
      * @param storageManager        Reference to the local database corresponding to the account where the file is contained. 
      */
@@ -57,62 +53,55 @@ public class CreateFolderOperation extends RemoteOperation {
         mRemotePath = remotePath;
         mCreateFullPath = createFullPath;
         mStorageManager = storageManager;
+        
     }
-    
-    
-    /**
-     * Performs the 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() && mkcol.getStatusCode() == HttpStatus.SC_CONFLICT && mCreateFullPath) {
-                result = createParentFolder(getParentPath(), client);
-                status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);    // second (and last) try
-            }
-            if (mkcol.succeeded()) {
-                // Save new directory in local database
-                OCFile newDir = new OCFile(mRemotePath);
-                newDir.setMimetype("DIR");
-                long parentId = mStorageManager.getFileByPath(getParentPath()).getFileId();
-                newDir.setParentId(parentId);
-                newDir.setModificationTimestamp(System.currentTimeMillis());
-                mStorageManager.saveFile(newDir);
-            }
-            result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders());
-            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();
+        CreateRemoteFolderOperation operation = new CreateRemoteFolderOperation(mRemotePath, mCreateFullPath);
+        RemoteOperationResult result =  operation.execute(client);
+        
+        if (result.isSuccess()) {
+            saveFolderInDB();
+        } else {
+            Log_OC.e(TAG, mRemotePath + "hasn't been created");
         }
+        
         return result;
     }
 
-
-    private String getParentPath() {
-        String parentPath = new File(mRemotePath).getParent();
-        parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
-        return parentPath;
+    @Override
+    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+        if (operation instanceof CreateRemoteFolderOperation) {
+            onCreateRemoteFolderOperationFinish((CreateRemoteFolderOperation)operation, result);
+        }
+    }
+    
+    
+    private void onCreateRemoteFolderOperationFinish(CreateRemoteFolderOperation operation, RemoteOperationResult result) {
+       if (result.isSuccess()) {
+           saveFolderInDB();
+       } else {
+           Log_OC.e(TAG, mRemotePath + "hasn't been created");
+       }
     }
 
     
-    private RemoteOperationResult createParentFolder(String parentPath, WebdavClient client) {
-        RemoteOperation operation = new CreateFolderOperation(  parentPath,
-                                                                mCreateFullPath,
-                                                                mStorageManager    );
-        return operation.execute(client);
+    /**
+     * Save new directory in local database
+     */
+    public void saveFolderInDB() {
+        OCFile newDir = new OCFile(mRemotePath);
+        newDir.setMimetype("DIR");
+        long parentId = mStorageManager.getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId();
+        newDir.setParentId(parentId);
+        newDir.setModificationTimestamp(System.currentTimeMillis());
+        mStorageManager.saveFile(newDir);
+
+        Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database");
+
     }
 
+
 }
index db986f4..eb45d4b 100644 (file)
@@ -32,16 +32,16 @@ import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.http.HttpStatus;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.OperationCancelledException;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
 import android.accounts.Account;
 import android.webkit.MimeTypeMap;
 
index 24336bd..d92190c 100644 (file)
@@ -20,11 +20,12 @@ 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 com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.utils.Log_OC;
 
-
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
 import android.content.Context;
 import android.net.ConnectivityManager;
 
index 09a6e1e..d392645 100644 (file)
@@ -8,13 +8,14 @@ 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 com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.WebdavClient;
-
 public class OAuth2GetAccessToken extends RemoteOperation {
     
     private static final String TAG = OAuth2GetAccessToken.class.getSimpleName();
diff --git a/src/com/owncloud/android/operations/OnRemoteOperationListener.java b/src/com/owncloud/android/operations/OnRemoteOperationListener.java
deleted file mode 100644 (file)
index e6a58e7..0000000
+++ /dev/null
@@ -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.operations;
-
-public interface OnRemoteOperationListener {
-
-       void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
-       
-}
diff --git a/src/com/owncloud/android/operations/OperationCancelledException.java b/src/com/owncloud/android/operations/OperationCancelledException.java
deleted file mode 100644 (file)
index 0b7878c..0000000
+++ /dev/null
@@ -1,28 +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.operations;
-
-public class OperationCancelledException extends Exception {
-
-    /**
-     * Generated serial version - to avoid Java warning
-     */
-    private static final long serialVersionUID = -6350981497740424983L;
-
-}
index 6234224..8209685 100644 (file)
@@ -22,12 +22,13 @@ import org.apache.commons.httpclient.methods.GetMethod;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
+import com.owncloud.android.utils.Log_OC;
 
-
-import eu.alefzero.webdav.WebdavClient;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.Uri;
diff --git a/src/com/owncloud/android/operations/RemoteOperation.java b/src/com/owncloud/android/operations/RemoteOperation.java
deleted file mode 100644 (file)
index 6e674c4..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* 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.operations;
-
-import java.io.IOException;
-
-import org.apache.commons.httpclient.Credentials;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
-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;
-
-/**
- * Operation which execution involves one or several interactions with an ownCloud server.
- * 
- * Provides methods to execute the operation both synchronously or asynchronously.
- * 
- * @author David A. Velasco 
- */
-public abstract class RemoteOperation implements Runnable {
-       
-    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 */
-       private OnRemoteOperationListener mListener = null;
-       
-       /** 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.
-        */
-       public final RemoteOperationResult execute(WebdavClient client) {
-               if (client == null)
-                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
-               mClient = client;
-               return run(client);
-       }
-
-       
-    /**
-     * 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
-        
-        mListener = listener;
-        
-        mListenerHandler = listenerHandler;
-        
-        Thread runnerThread = new Thread(this);
-        runnerThread.start();
-        return runnerThread;
-    }
-
-    
-       /**
-        * Asynchronously executes the remote operation
-        * 
-        * @param client                        Client object to reach an ownCloud server during the execution of the operation.
-        * @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(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
-               if (client == null) {
-                       throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
-               }
-               mClient = client;
-               
-               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;
-       }
-       
-    /**
-     * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
-     * 
-     * @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 RemoteOperationResult retry() {
-        return execute(mClient);
-    }
-    
-    /**
-     * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
-     * 
-     * @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 retry(OnRemoteOperationListener listener, Handler listenerHandler) {
-        return execute(mClient, listener, listenerHandler);
-    }
-       
-       
-       /**
-        * 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() {
-        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 || (result.isTemporalRedirection() && result.isIdPRedirection()))) {
-                    (result.getCode() == ResultCode.UNAUTHORIZED || result.isIdPRedirection())) {
-                /// possible fail due to lack of authorization in an operation performed in foreground
-                Credentials cred = mClient.getCredentials();
-                String ssoSessionCookie = mClient.getSsoSessionCookie();
-                if (cred != null || ssoSessionCookie != null) {
-                    /// confirmed : unauthorized operation
-                    AccountManager am = AccountManager.get(mContext);
-                    boolean bearerAuthorization = (cred != null && cred instanceof BearerCredentials);
-                    boolean samlBasedSsoAuthorization = (cred == null && ssoSessionCookie != null);
-                    if (bearerAuthorization) {
-                        am.invalidateAuthToken(MainApp.getAccountType(), ((BearerCredentials)cred).getAccessToken());
-                    } else if (samlBasedSsoAuthorization ) {
-                        am.invalidateAuthToken(MainApp.getAccountType(), ssoSessionCookie);
-                    } 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, 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;
-    }
-
-
-}
diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java
deleted file mode 100644 (file)
index 8d9b3ee..0000000
+++ /dev/null
@@ -1,338 +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.operations;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-
-import javax.net.ssl.SSLException;
-
-import org.apache.commons.httpclient.ConnectTimeoutException;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.jackrabbit.webdav.DavException;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
-import com.owncloud.android.network.CertificateCombinedException;
-
-import android.accounts.Account;
-import android.accounts.AccountsException;
-
-
-/**
- * The result of a remote operation required to an ownCloud server.
- * 
- * Provides a common classification of remote operation results for all the
- * application.
- * 
- * @author David A. Velasco
- */
-public class RemoteOperationResult implements Serializable {
-
-    /** Generated - should be refreshed every time the class changes!! */
-    private static final long serialVersionUID = -4415103901492836870L;
-    
-
-    
-    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, 
-        OAUTH2_ERROR,
-        SYNC_CONFLICT,
-        LOCAL_STORAGE_FULL, 
-        LOCAL_STORAGE_NOT_MOVED, 
-        LOCAL_STORAGE_NOT_COPIED, 
-        OAUTH2_ERROR_ACCESS_DENIED,
-        QUOTA_EXCEEDED, 
-        ACCOUNT_NOT_FOUND, 
-        ACCOUNT_EXCEPTION, 
-        ACCOUNT_NOT_NEW, 
-        ACCOUNT_NOT_THE_SAME
-    }
-
-    private boolean mSuccess = false;
-    private int mHttpCode = -1;
-    private Exception mException = null;
-    private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
-    private String mRedirectedLocation;
-
-    public RemoteOperationResult(ResultCode code) {
-        mCode = code;
-        mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
-    }
-
-    private RemoteOperationResult(boolean success, int httpCode) {
-        mSuccess = success;
-        mHttpCode = httpCode;
-
-        if (success) {
-            mCode = ResultCode.OK;
-
-        } else if (httpCode > 0) {
-            switch (httpCode) {
-            case HttpStatus.SC_UNAUTHORIZED:
-                mCode = ResultCode.UNAUTHORIZED;
-                break;
-            case HttpStatus.SC_NOT_FOUND:
-                mCode = ResultCode.FILE_NOT_FOUND;
-                break;
-            case HttpStatus.SC_INTERNAL_SERVER_ERROR:
-                mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
-                break;
-            case HttpStatus.SC_CONFLICT:
-                mCode = ResultCode.CONFLICT;
-                break;
-            case HttpStatus.SC_INSUFFICIENT_STORAGE:
-                mCode = ResultCode.QUOTA_EXCEEDED;
-                break;
-            default:
-                mCode = ResultCode.UNHANDLED_HTTP_CODE;
-                Log_OC.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
-            }
-        }
-    }
-    
-    public RemoteOperationResult(boolean success, int httpCode, Header[] headers) {
-        this(success, httpCode);
-        if (headers != null) {
-            Header current;
-            for (int i=0; i<headers.length; i++) {
-                current = headers[i];
-                if ("Location".equals(current.getName())) {
-                    mRedirectedLocation = current.getValue();
-                    break;
-                }
-            }
-        }
-    }    
-
-    public RemoteOperationResult(Exception e) {
-        mException = e;
-
-        if (e instanceof OperationCancelledException) {
-            mCode = ResultCode.CANCELLED;
-
-        } else if (e instanceof SocketException) {
-            mCode = ResultCode.WRONG_CONNECTION;
-
-        } else if (e instanceof SocketTimeoutException) {
-            mCode = ResultCode.TIMEOUT;
-
-        } else if (e instanceof ConnectTimeoutException) {
-            mCode = ResultCode.TIMEOUT;
-
-        } else if (e instanceof MalformedURLException) {
-            mCode = ResultCode.INCORRECT_ADDRESS;
-
-        } else if (e instanceof UnknownHostException) {
-            mCode = ResultCode.HOST_NOT_AVAILABLE;
-
-        } else if (e instanceof AccountNotFoundException) {
-            mCode = ResultCode.ACCOUNT_NOT_FOUND;
-            
-        } else if (e instanceof AccountsException) {
-            mCode = ResultCode.ACCOUNT_EXCEPTION;
-            
-        } else if (e instanceof SSLException || e instanceof RuntimeException) {
-            CertificateCombinedException se = getCertificateCombinedException(e);
-            if (se != null) {
-                mException = se;
-                if (se.isRecoverable()) {
-                    mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
-                }
-            } else if (e instanceof RuntimeException) {
-                mCode = ResultCode.HOST_NOT_AVAILABLE;
-
-            } else {
-                mCode = ResultCode.SSL_ERROR;
-            }
-
-        } else {
-            mCode = ResultCode.UNKNOWN_ERROR;
-        }
-
-    }
-
-    public boolean isSuccess() {
-        return mSuccess;
-    }
-
-    public boolean isCancelled() {
-        return mCode == ResultCode.CANCELLED;
-    }
-
-    public int getHttpCode() {
-        return mHttpCode;
-    }
-
-    public ResultCode getCode() {
-        return mCode;
-    }
-
-    public Exception getException() {
-        return mException;
-    }
-
-    public boolean isSslRecoverableException() {
-        return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
-    }
-
-    private CertificateCombinedException getCertificateCombinedException(Exception e) {
-        CertificateCombinedException result = null;
-        if (e instanceof CertificateCombinedException) {
-            return (CertificateCombinedException) e;
-        }
-        Throwable cause = mException.getCause();
-        Throwable previousCause = null;
-        while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
-            previousCause = cause;
-            cause = cause.getCause();
-        }
-        if (cause != null && cause instanceof CertificateCombinedException) {
-            result = (CertificateCombinedException) cause;
-        }
-        return result;
-    }
-
-    public String getLogMessage() {
-
-        if (mException != null) {
-            if (mException instanceof OperationCancelledException) {
-                return "Operation cancelled by the caller";
-
-            } else if (mException instanceof SocketException) {
-                return "Socket exception";
-
-            } else if (mException instanceof SocketTimeoutException) {
-                return "Socket timeout exception";
-
-            } else if (mException instanceof ConnectTimeoutException) {
-                return "Connect timeout exception";
-
-            } else if (mException instanceof MalformedURLException) {
-                return "Malformed URL exception";
-
-            } else if (mException instanceof UnknownHostException) {
-                return "Unknown host exception";
-
-            } else if (mException instanceof CertificateCombinedException) {
-                if (((CertificateCombinedException) mException).isRecoverable())
-                    return "SSL recoverable exception";
-                else
-                    return "SSL exception";
-
-            } else if (mException instanceof SSLException) {
-                return "SSL exception";
-
-            } else if (mException instanceof DavException) {
-                return "Unexpected WebDAV exception";
-
-            } else if (mException instanceof HttpException) {
-                return "HTTP violation";
-
-            } else if (mException instanceof IOException) {
-                return "Unrecovered transport exception";
-
-            } else if (mException instanceof AccountNotFoundException) {
-                Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
-                return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
-                
-            } else if (mException instanceof AccountsException) {
-                return "Exception while using account";
-                
-            } else {
-                return "Unexpected exception";
-            }
-        }
-
-        if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
-            return "The ownCloud server is not configured!";
-
-        } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
-            return "No network connection";
-
-        } else if (mCode == ResultCode.BAD_OC_VERSION) {
-            return "No valid ownCloud version was found at the server";
-
-        } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
-            return "Local storage full";
-
-        } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
-            return "Error while moving file to final directory";
-
-        } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
-            return "Account already existing when creating a new one";
-
-        } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
-            return "Authenticated with a different account than the one updating";
-        }
-
-        return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
-
-    }
-
-    public boolean isServerFail() {
-        return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
-    }
-
-    public boolean isException() {
-        return (mException != null);
-    }
-
-    public boolean isTemporalRedirection() {
-        return (mHttpCode == 302 || mHttpCode == 307);
-    }
-
-    public String getRedirectedLocation() {
-        return mRedirectedLocation;
-    }
-    
-    public boolean isIdPRedirection() {
-        return (mRedirectedLocation != null &&
-                (mRedirectedLocation.toUpperCase().contains("SAML") || 
-                mRedirectedLocation.toLowerCase().contains("wayf")));
-    }
-
-}
index 659037b..34926af 100644 (file)
@@ -20,14 +20,15 @@ package com.owncloud.android.operations;
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
-
 /**
  * Remote operation performing the removal of a remote file or folder in the ownCloud server.
  * 
index a2370f3..2b352bd 100644 (file)
@@ -22,18 +22,20 @@ import java.io.IOException;
 
 import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 //import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
 
 import android.accounts.Account;
 
 
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
 
 /**
  * Remote operation performing the rename of a remote file (or folder?) in the ownCloud server.
index 2e15c2f..f087aa5 100644 (file)
@@ -23,22 +23,23 @@ import org.apache.jackrabbit.webdav.DavConstants;
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 
 
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavEntry;
-import eu.alefzero.webdav.WebdavUtils;
-
 public class SynchronizeFileOperation extends RemoteOperation {
 
     private String TAG = SynchronizeFileOperation.class.getSimpleName();
index 09683d6..780fd42 100644 (file)
@@ -37,16 +37,18 @@ import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.syncadapter.FileSyncService;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavEntry;
-import eu.alefzero.webdav.WebdavUtils;
 
 
 /**
index 2e116ac..7e33060 100644 (file)
@@ -22,19 +22,20 @@ import org.apache.commons.httpclient.methods.GetMethod;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.Context;
 
 
-import eu.alefzero.webdav.WebdavClient;
-
 /**
  * Remote operation that checks the version of an ownCloud server and stores it locally
  * 
@@ -57,7 +58,7 @@ public class UpdateOCVersionOperation extends RemoteOperation {
     @Override
     protected RemoteOperationResult run(WebdavClient client) {
         AccountManager accountMngr = AccountManager.get(mContext); 
-        String statUrl = accountMngr.getUserData(mAccount, AccountAuthenticator.KEY_OC_BASE_URL);
+        String statUrl = accountMngr.getUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_BASE_URL);
         statUrl += AccountUtils.STATUS_PATH;
         RemoteOperationResult result = null;
         GetMethod get = null;
@@ -75,7 +76,7 @@ public class UpdateOCVersionOperation extends RemoteOperation {
                     if (json != null && json.getString("version") != null) {
                         OwnCloudVersion ocver = new OwnCloudVersion(json.getString("version"));
                         if (ocver.isVersionValid()) {
-                            accountMngr.setUserData(mAccount, AccountAuthenticator.KEY_OC_VERSION, ocver.toString());
+                            accountMngr.setUserData(mAccount, OwnCloudAccount.Constants.KEY_OC_VERSION, ocver.toString());
                             Log_OC.d(TAG, "Got new OC version " + ocver.toString());
                             result = new RemoteOperationResult(ResultCode.OK);
                             
index 936ac01..80a3463 100644 (file)
@@ -32,23 +32,23 @@ import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.http.HttpStatus;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.network.ProgressiveDataTransferer;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
+import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity;
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.OperationCancelledException;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 
 
-import eu.alefzero.webdav.FileRequestEntity;
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-import eu.alefzero.webdav.WebdavClient;
-import eu.alefzero.webdav.WebdavUtils;
-
 /**
  * Remote operation performing the upload of a file to an ownCloud server
  * 
index 41b643c..9e7cd3f 100644 (file)
@@ -21,11 +21,11 @@ package com.owncloud.android.providers;
 import java.util.ArrayList;
 import java.util.HashMap;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.db.ProviderMeta;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.utils.Log_OC;
 
 
 
index 6e81557..74d2686 100644 (file)
@@ -24,10 +24,11 @@ import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;\r
 import org.apache.http.client.ClientProtocolException;\r
 \r
-import com.owncloud.android.authentication.AccountUtils;\r
-import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;\r
 import com.owncloud.android.datamodel.FileDataStorageManager;\r
-import com.owncloud.android.network.OwnCloudClientUtils;\r
+import com.owncloud.android.oc_framework.accounts.AccountUtils;\r
+import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;\r
+import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;\r
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;\r
 \r
 \r
 import android.accounts.Account;\r
@@ -37,7 +38,6 @@ import android.accounts.OperationCanceledException;
 import android.content.AbstractThreadedSyncAdapter;\r
 import android.content.ContentProviderClient;\r
 import android.content.Context;\r
-import eu.alefzero.webdav.WebdavClient;\r
 \r
 /**\r
  * Base synchronization adapter for ownCloud designed to be subclassed for different\r
@@ -102,7 +102,7 @@ public abstract class AbstractOwnCloudSyncAdapter extends
 \r
     protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {\r
         AccountUtils.constructFullURLForAccount(getContext(), account);\r
-        mClient = OwnCloudClientUtils.createOwnCloudClient(account, getContext());\r
+        mClient = OwnCloudClientFactory.createOwnCloudClient(account, getContext());\r
     }\r
     \r
     protected WebdavClient getClient() {\r
index 662c8a6..9bf5d83 100644 (file)
@@ -26,6 +26,7 @@ import org.apache.http.entity.ByteArrayEntity;
 
 import com.owncloud.android.authentication.AccountAuthenticator;
 import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
 
 
 import android.accounts.Account;
@@ -92,7 +93,7 @@ public class ContactSyncAdapter extends AbstractOwnCloudSyncAdapter {
         AccountManager am = getAccountManager();
         @SuppressWarnings("deprecation")
         String uri = am.getUserData(getAccount(),
-                AccountAuthenticator.KEY_OC_URL).replace(
+                OwnCloudAccount.Constants.KEY_OC_URL).replace(
                 AccountUtils.WEBDAV_PATH_2_0, AccountUtils.CARDDAV_PATH_2_0);
         uri += "/addressbooks/"
                 + getAccount().name.substring(0,
index 5b0376c..f0bc870 100644 (file)
@@ -26,17 +26,17 @@ import java.util.Map;
 
 import org.apache.jackrabbit.webdav.DavException;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
 import com.owncloud.android.operations.UpdateOCVersionOperation;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
@@ -279,8 +279,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         } else {
             // in failures, the statistics for the global result are updated
             if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
-                    ( result.isIdPRedirection() && 
-                            MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
+                    ( result.isIdPRedirection() &&
+                            getClient().getCredentials() == null      )) {
+                            //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
                 mSyncResult.stats.numAuthExceptions++;
                 
             } else if (result.getException() instanceof DavException) {
@@ -371,9 +372,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         notification.flags |= Notification.FLAG_AUTO_CANCEL;
         boolean needsToUpdateCredentials = (mLastFailedResult != null && 
                                              (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
-                                                // (mLastFailedResult.isTemporalRedirection() && mLastFailedResult.isIdPRedirection() && 
                                                 ( mLastFailedResult.isIdPRedirection() && 
-                                                 MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
+                                                  getClient().getCredentials() == null      )
+                                                 //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
                                              )
                                            );
         // TODO put something smart in the contentIntent below for all the possible errors
index dafc771..1e1e11f 100644 (file)
@@ -17,7 +17,7 @@
  */\r
 package com.owncloud.android.syncadapter;\r
 \r
-import com.owncloud.android.Log_OC;\r
+import com.owncloud.android.utils.Log_OC;\r
 \r
 import android.app.Service;\r
 import android.content.Intent;\r
index 716d6df..b1ff845 100644 (file)
@@ -47,12 +47,12 @@ import com.actionbarsherlock.app.SherlockListActivity;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.Log_OC;
+import com.owncloud.android.authentication.AuthenticatorActivity;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
+import com.owncloud.android.utils.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
-import com.owncloud.android.authentication.AccountAuthenticator;
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.authentication.AuthenticatorActivity;
 
 
 public class AccountSelectActivity extends SherlockListActivity implements
@@ -211,7 +211,7 @@ public class AccountSelectActivity extends SherlockListActivity implements
                 h.put("VER",
                         "ownCloud version: "
                                 + am.getUserData(a,
-                                        AccountAuthenticator.KEY_OC_VERSION));
+                                        OwnCloudAccount.Constants.KEY_OC_VERSION));
                 ll.add(h);
             }
 
index f0895bf..2d13a66 100644 (file)
 
 package com.owncloud.android.ui.activity;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener;
+import com.owncloud.android.utils.Log_OC;
 
 import android.content.Intent;
 import android.os.Bundle;
index 056ffd6..cf69a48 100644 (file)
@@ -39,13 +39,13 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
 import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 
index cddf9b6..59b4443 100644 (file)
@@ -29,15 +29,14 @@ import android.os.Bundle;
 import android.webkit.MimeTypeMap;
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.WebdavUtils;
-
 /**
  * Activity with common behaviour for activities handling {@link OCFile}s in ownCloud {@link Account}s .
  * 
index 39b7bd8..685cff2 100644 (file)
@@ -31,7 +31,6 @@ import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.IntentFilter.AuthorityEntry;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.SyncRequest;
@@ -59,7 +58,6 @@ import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.Window;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -70,10 +68,10 @@ import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
@@ -90,6 +88,7 @@ import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
 import com.owncloud.android.ui.preview.PreviewVideoActivity;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
@@ -1335,6 +1334,9 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
 
         } else {
             dismissLoadingDialog();
+            if (result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME) {
+                Toast.makeText(FileDisplayActivity.this, R.string.filename_forbidden_characters, Toast.LENGTH_LONG).show();
+            } else {
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG); 
                 msg.show();
@@ -1342,6 +1344,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
             } catch (NotFoundException e) {
                 Log_OC.e(TAG, "Error while trying to show fail message " , e);
             }
+            }
         }
     }
 
index a851dd1..0d455bd 100644 (file)
@@ -19,13 +19,13 @@ package com.owncloud.android.ui.activity;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.InstantUploadBroadcastReceiver;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.app.Activity;
index e94942e..678dad6 100644 (file)
@@ -36,10 +36,10 @@ import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.SherlockPreferenceActivity;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.OwnCloudSession;
 import com.owncloud.android.R;
 import com.owncloud.android.db.DbHandler;
+import com.owncloud.android.utils.Log_OC;
+import com.owncloud.android.utils.OwnCloudSession;
 
 
 /**
index cc1f7de..7c941e8 100644 (file)
@@ -35,13 +35,13 @@ import android.widget.TextView;
 import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.LocalFileListFragment;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
 import com.owncloud.android.utils.FileStorageUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java
new file mode 100644 (file)
index 0000000..08e2d21
--- /dev/null
@@ -0,0 +1,432 @@
+/* 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.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.R.id;
+import com.owncloud.android.R.layout;
+import com.owncloud.android.R.string;
+import com.owncloud.android.authentication.AccountAuthenticator;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.utils.Log_OC;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.ListActivity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.SimpleAdapter;
+import android.widget.Toast;
+
+
+/**
+ * This can be used to upload things to an ownCloud instance.
+ * 
+ * @author Bartek Przybylski
+ * 
+ */
+public class Uploader extends ListActivity implements OnItemClickListener, android.view.View.OnClickListener {
+    private static final String TAG = "ownCloudUploader";
+
+    private Account mAccount;
+    private AccountManager mAccountManager;
+    private Stack<String> mParents;
+    private ArrayList<Parcelable> mStreamsToUpload;
+    private boolean mCreateDir;
+    private String mUploadPath;
+    private FileDataStorageManager mStorageManager;
+    private OCFile mFile;
+
+    private final static int DIALOG_NO_ACCOUNT = 0;
+    private final static int DIALOG_WAITING = 1;
+    private final static int DIALOG_NO_STREAM = 2;
+    private final static int DIALOG_MULTIPLE_ACCOUNT = 3;
+
+    private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+        mParents = new Stack<String>();
+        mParents.add("");
+        if (prepareStreamsToUpload()) {
+            mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
+            Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
+            if (accounts.length == 0) {
+                Log_OC.i(TAG, "No ownCloud account is available");
+                showDialog(DIALOG_NO_ACCOUNT);
+            } else if (accounts.length > 1) {
+                Log_OC.i(TAG, "More then one ownCloud is available");
+                showDialog(DIALOG_MULTIPLE_ACCOUNT);
+            } else {
+                mAccount = accounts[0];
+                mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                populateDirectoryList();
+            }
+        } else {
+            showDialog(DIALOG_NO_STREAM);
+        }
+    }
+    
+    @Override
+    protected Dialog onCreateDialog(final int id) {
+        final AlertDialog.Builder builder = new Builder(this);
+        switch (id) {
+        case DIALOG_WAITING:
+            ProgressDialog pDialog = new ProgressDialog(this);
+            pDialog.setIndeterminate(false);
+            pDialog.setCancelable(false);
+            pDialog.setMessage(getResources().getString(R.string.uploader_info_uploading));
+            return pDialog;
+        case DIALOG_NO_ACCOUNT:
+            builder.setIcon(android.R.drawable.ic_dialog_alert);
+            builder.setTitle(R.string.uploader_wrn_no_account_title);
+            builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
+            builder.setCancelable(false);
+            builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ECLAIR_MR1) {
+                        // using string value since in API7 this
+                        // constatn is not defined
+                        // in API7 < this constatant is defined in
+                        // Settings.ADD_ACCOUNT_SETTINGS
+                        // and Settings.EXTRA_AUTHORITIES
+                        Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT);
+                        intent.putExtra("authorities", new String[] { MainApp.getAuthTokenType() });
+                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
+                    } else {
+                        // since in API7 there is no direct call for
+                        // account setup, so we need to
+                        // show our own AccountSetupAcricity, get
+                        // desired results and setup
+                        // everything for ourself
+                        Intent intent = new Intent(getBaseContext(), AccountAuthenticator.class);
+                        startActivityForResult(intent, REQUEST_CODE_SETUP_ACCOUNT);
+                    }
+                }
+            });
+            builder.setNegativeButton(R.string.uploader_wrn_no_account_quit_btn_text, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    finish();
+                }
+            });
+            return builder.create();
+        case DIALOG_MULTIPLE_ACCOUNT:
+            CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
+            for (int i = 0; i < ac.length; ++i) {
+                ac[i] = mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name;
+            }
+            builder.setTitle(R.string.common_choose_account);
+            builder.setItems(ac, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
+                    mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                    populateDirectoryList();
+                }
+            });
+            builder.setCancelable(true);
+            builder.setOnCancelListener(new OnCancelListener() {
+                @Override
+                public void onCancel(DialogInterface dialog) {
+                    dialog.cancel();
+                    finish();
+                }
+            });
+            return builder.create();
+        case DIALOG_NO_STREAM:
+            builder.setIcon(android.R.drawable.ic_dialog_alert);
+            builder.setTitle(R.string.uploader_wrn_no_content_title);
+            builder.setMessage(R.string.uploader_wrn_no_content_text);
+            builder.setCancelable(false);
+            builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    finish();
+                }
+            });
+            return builder.create();
+        default:
+            throw new IllegalArgumentException("Unknown dialog id: " + id);
+        }
+    }
+
+    class a implements OnClickListener {
+        String mPath;
+        EditText mDirname;
+
+        public a(String path, EditText dirname) {
+            mPath = path; 
+            mDirname = dirname;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            Uploader.this.mUploadPath = mPath + mDirname.getText().toString();
+            Uploader.this.mCreateDir = true;
+            uploadFiles();
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+
+        if (mParents.size() <= 1) {
+            super.onBackPressed();
+            return;
+        } else {
+            mParents.pop();
+            populateDirectoryList();
+        }
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        // click on folder in the list
+        Log_OC.d(TAG, "on item click");
+        Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile);
+        if (tmpfiles.size() <= 0) return;
+        // filter on dirtype
+        Vector<OCFile> files = new Vector<OCFile>();
+        for (OCFile f : tmpfiles)
+            if (f.isFolder())
+                files.add(f);
+        if (files.size() < position) {
+            throw new IndexOutOfBoundsException("Incorrect item selected");
+        }
+        mParents.push(files.get(position).getFileName());
+        populateDirectoryList();
+    }
+
+    @Override
+    public void onClick(View v) {
+        // click on button
+        switch (v.getId()) {
+        case R.id.uploader_choose_folder:
+            mUploadPath = "";   // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
+            for (String p : mParents)
+                mUploadPath += p + OCFile.PATH_SEPARATOR;
+            Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
+
+            uploadFiles();
+
+            break;
+        default:
+            throw new IllegalArgumentException("Wrong element clicked");
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        Log_OC.i(TAG, "result received. req: " + requestCode + " res: " + resultCode);
+        if (requestCode == REQUEST_CODE_SETUP_ACCOUNT) {
+            dismissDialog(DIALOG_NO_ACCOUNT);
+            if (resultCode == RESULT_CANCELED) {
+                finish();
+            }
+            Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAuthTokenType());
+            if (accounts.length == 0) {
+                showDialog(DIALOG_NO_ACCOUNT);
+            } else {
+                // there is no need for checking for is there more then one
+                // account at this point
+                // since account setup can set only one account at time
+                mAccount = accounts[0];
+                populateDirectoryList();
+            }
+        }
+    }
+
+    private void populateDirectoryList() {
+        setContentView(R.layout.uploader_layout);
+
+        String full_path = "";
+        for (String a : mParents)
+            full_path += a + "/";
+        
+        Log_OC.d(TAG, "Populating view with content of : " + full_path);
+        
+        mFile = mStorageManager.getFileByPath(full_path);
+        if (mFile != null) {
+            Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
+            List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
+            for (OCFile f : files) {
+                HashMap<String, Object> h = new HashMap<String, Object>();
+                if (f.isFolder()) {
+                    h.put("dirname", f.getFileName());
+                    data.add(h);
+                }
+            }
+            SimpleAdapter sa = new SimpleAdapter(this,
+                                                data,
+                                                R.layout.uploader_list_item_layout,
+                                                new String[] {"dirname"},
+                                                new int[] {R.id.textView1});
+            setListAdapter(sa);
+            Button btn = (Button) findViewById(R.id.uploader_choose_folder);
+            btn.setOnClickListener(this);
+            getListView().setOnItemClickListener(this);
+        }
+    }
+
+    private boolean prepareStreamsToUpload() {
+        if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
+            mStreamsToUpload = new ArrayList<Parcelable>();
+            mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
+        } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
+            mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+        }
+        return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
+    }
+
+    public void uploadFiles() {
+        try {
+            //WebdavClient 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);
+            }
+            */
+            
+            // 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.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));
+            Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
+        }
+    }
+
+}
index a864f7a..841a5d0 100644 (file)
@@ -31,7 +31,6 @@ import android.widget.TextView;
 \r
 import java.util.Vector;\r
 \r
-import com.owncloud.android.DisplayUtils;\r
 import com.owncloud.android.R;\r
 import com.owncloud.android.authentication.AccountUtils;\r
 import com.owncloud.android.datamodel.FileDataStorageManager;\r
@@ -39,6 +38,7 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
 import com.owncloud.android.ui.activity.TransferServiceGetter;\r
+import com.owncloud.android.utils.DisplayUtils;\r
 \r
 \r
 /**\r
index ff883c5..7cd2c2a 100644 (file)
@@ -21,8 +21,8 @@ import java.io.File;
 import java.util.Arrays;
 import java.util.Comparator;
 
-import com.owncloud.android.DisplayUtils;
 import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 import android.content.Context;
index 4d6243a..862715f 100644 (file)
@@ -27,10 +27,11 @@ import android.view.View;
 import android.view.WindowManager.LayoutParams;
 import android.widget.EditText;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.R;
-
+import com.owncloud.android.oc_framework.utils.FileUtils;
 
 
 /**
@@ -129,6 +130,10 @@ public class EditNameDialog extends SherlockDialogFragment implements DialogInte
         switch (which) {
             case AlertDialog.BUTTON_POSITIVE: {
                 mNewFilename = ((TextView)(getDialog().findViewById(R.id.user_input))).getText().toString();
+                if (!FileUtils.isValidName(mNewFilename)) {
+                    Toast.makeText(getSherlockActivity(), R.string.filename_forbidden_characters, Toast.LENGTH_LONG).show();
+                    return;
+                }
                 mResult = true;
             }
             case AlertDialog.BUTTON_NEGATIVE: { // fall through
index 516fce1..91c607e 100644 (file)
@@ -35,14 +35,13 @@ import android.webkit.WebSettings;
 import android.webkit.WebView;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.SsoWebViewClient;
 import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;
+import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.WebdavClient;
-
 /**
  * Dialog to show the WebView for SAML Authentication
  * 
index 1ccc8fa..a50ecc9 100644 (file)
@@ -29,11 +29,7 @@ import java.util.Map;
 
 import javax.security.auth.x500.X500Principal;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import com.owncloud.android.network.CertificateCombinedException;
-import com.owncloud.android.network.OwnCloudClientUtils;
-import com.owncloud.android.operations.RemoteOperationResult;
 
 import android.app.Dialog;
 import android.content.Context;
@@ -43,6 +39,10 @@ import android.view.Window;
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.owncloud.android.oc_framework.network.CertificateCombinedException;
+import com.owncloud.android.oc_framework.network.NetworkUtils;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.utils.Log_OC;
 
 /**
  * Dialog to request the user about a certificate that could not be validated with the certificates store in the system.
@@ -343,7 +343,7 @@ public class SslValidatorDialog extends Dialog {
     private void saveServerCert() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
         if (mException.getServerCertificate() != null) {
             // TODO make this asynchronously, it can take some time
-            OwnCloudClientUtils.addCertToKnownServersStore(mException.getServerCertificate(), getContext());
+            NetworkUtils.addCertToKnownServersStore(mException.getServerCertificate(), getContext());
         }
     }
 
index 869cb26..bb9adbe 100644 (file)
@@ -24,7 +24,7 @@ import android.content.DialogInterface;
 import android.os.Bundle;
 
 import com.actionbarsherlock.app.SherlockDialogFragment;
-import com.owncloud.android.Log_OC;
+import com.owncloud.android.utils.Log_OC;
 
 
 public class ConfirmationDialogFragment extends SherlockDialogFragment {
index a57fb09..409c5e6 100644 (file)
@@ -19,9 +19,9 @@
 package com.owncloud.android.ui.fragment;
 
 import com.actionbarsherlock.app.SherlockFragment;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.ui.ExtendedListView;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.os.Bundle;
index af73766..01ef8d0 100644 (file)
@@ -43,8 +43,6 @@ import android.widget.Toast;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.DisplayUtils;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
@@ -52,23 +50,24 @@ import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
 import com.owncloud.android.ui.activity.FileActivity;
 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.ui.preview.PreviewImageFragment;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
 /**
  * This Fragment is used to display the details about a file.
  * 
index 40c03a4..270a8d5 100644 (file)
@@ -19,9 +19,9 @@ package com.owncloud.android.ui.fragment;
 
 import java.io.File;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.ui.adapter.LocalFileListAdapter;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.app.Activity;
index a3c6d3b..c75eedb 100644 (file)
@@ -21,7 +21,6 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -29,8 +28,8 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.FileHandler;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
@@ -42,6 +41,7 @@ import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
+import com.owncloud.android.utils.Log_OC;
 
 
 import android.accounts.Account;
index 306df1f..c18f84b 100644 (file)
@@ -19,11 +19,11 @@ package com.owncloud.android.ui.preview;
 
 import java.lang.ref.WeakReference;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 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.utils.Log_OC;
 
 import android.accounts.Account;
 import android.app.Activity;
@@ -37,10 +37,9 @@ import android.widget.ImageButton;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
 
 
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
 /**
  * This Fragment is used to monitor the progress of a file downloading.
  * 
index ef48d12..fde70df 100644 (file)
@@ -35,7 +35,6 @@ import android.view.View.OnTouchListener;
 import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.view.MenuItem;
 import com.actionbarsherlock.view.Window;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -48,6 +47,7 @@ import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
index 9ef4db4..ebc17c6 100644 (file)
@@ -50,18 +50,17 @@ import android.widget.Toast;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
-
-import eu.alefzero.webdav.WebdavUtils;
+import com.owncloud.android.utils.Log_OC;
 
 
 /**
index 815dbbd..0cce76a 100644 (file)
@@ -52,23 +52,23 @@ import android.widget.VideoView;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 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.operations.OnRemoteOperationListener;
-import com.owncloud.android.operations.RemoteOperation;
-import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
+import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
+import com.owncloud.android.oc_framework.operations.RemoteOperation;
+import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.utils.Log_OC;
 
-import eu.alefzero.webdav.WebdavUtils;
 
 /**
  * This fragment shows a preview of a downloaded media file (audio or video).
index 7db07b3..59d9655 100644 (file)
 
 package com.owncloud.android.ui.preview;
 
-import com.owncloud.android.Log_OC;
 import com.owncloud.android.R;
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.authentication.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.media.MediaService;
 import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.app.AlertDialog;
@@ -39,6 +37,9 @@ import android.os.Bundle;
 import android.widget.MediaController;
 import android.widget.VideoView;
 
+import com.owncloud.android.oc_framework.accounts.AccountUtils;
+import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
+
 /**
  *  Activity implementing a basic video player.
  * 
diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java
new file mode 100644 (file)
index 0000000..e4bdd99
--- /dev/null
@@ -0,0 +1,193 @@
+/* ownCloud Android client application\r
+ *   Copyright (C) 2011  Bartek Przybylski\r
+ *   Copyright (C) 2012-2013 ownCloud Inc.\r
+ *\r
+ *   This program is free software: you can redistribute it and/or modify\r
+ *   it under the terms of the GNU General Public License version 2,\r
+ *   as published by the Free Software Foundation.\r
+ *\r
+ *   This program is distributed in the hope that it will be useful,\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *   GNU General Public License for more details.\r
+ *\r
+ *   You should have received a copy of the GNU General Public License\r
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
+ *\r
+ */\r
+\r
+package com.owncloud.android.utils;\r
+\r
+import java.util.Arrays;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+\r
+import com.owncloud.android.R;\r
+import com.owncloud.android.R.drawable;\r
+\r
+/**\r
+ * A helper class for some string operations.\r
+ * \r
+ * @author Bartek Przybylski\r
+ * @author David A. Velasco\r
+ */\r
+public class DisplayUtils {\r
+    \r
+    //private static String TAG = DisplayUtils.class.getSimpleName(); \r
+    \r
+    private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };\r
+\r
+    private static HashMap<String, String> mimeType2HUmanReadable;\r
+    static {\r
+        mimeType2HUmanReadable = new HashMap<String, String>();\r
+        // images\r
+        mimeType2HUmanReadable.put("image/jpeg", "JPEG image");\r
+        mimeType2HUmanReadable.put("image/jpg", "JPEG image");\r
+        mimeType2HUmanReadable.put("image/png", "PNG image");\r
+        mimeType2HUmanReadable.put("image/bmp", "Bitmap image");\r
+        mimeType2HUmanReadable.put("image/gif", "GIF image");\r
+        mimeType2HUmanReadable.put("image/svg+xml", "JPEG image");\r
+        mimeType2HUmanReadable.put("image/tiff", "TIFF image");\r
+        // music\r
+        mimeType2HUmanReadable.put("audio/mpeg", "MP3 music file");\r
+        mimeType2HUmanReadable.put("application/ogg", "OGG music file");\r
+\r
+    }\r
+\r
+    private static final String TYPE_APPLICATION = "application";\r
+    private static final String TYPE_AUDIO = "audio";\r
+    private static final String TYPE_IMAGE = "image";\r
+    private static final String TYPE_TXT = "text";\r
+    private static final String TYPE_VIDEO = "video";\r
+    \r
+    private static final String SUBTYPE_PDF = "pdf";\r
+    private static final String[] SUBTYPES_DOCUMENT = { "msword", "mspowerpoint", "msexcel", \r
+                                                        "vnd.oasis.opendocument.presentation",\r
+                                                        "vnd.oasis.opendocument.spreadsheet",\r
+                                                        "vnd.oasis.opendocument.text"\r
+                                                        };\r
+    private static Set<String> SUBTYPES_DOCUMENT_SET = new HashSet<String>(Arrays.asList(SUBTYPES_DOCUMENT));\r
+    private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"};\r
+    private static final Set<String> SUBTYPES_COMPRESSED_SET = new HashSet<String>(Arrays.asList(SUBTYPES_COMPRESSED));\r
+    \r
+    /**\r
+     * Converts the file size in bytes to human readable output.\r
+     * \r
+     * @param bytes Input file size\r
+     * @return Like something readable like "12 MB"\r
+     */\r
+    public static String bytesToHumanReadable(long bytes) {\r
+        double result = bytes;\r
+        int attachedsuff = 0;\r
+        while (result > 1024 && attachedsuff < sizeSuffixes.length) {\r
+            result /= 1024.;\r
+            attachedsuff++;\r
+        }\r
+        result = ((int) (result * 100)) / 100.;\r
+        return result + " " + sizeSuffixes[attachedsuff];\r
+    }\r
+\r
+    /**\r
+     * Removes special HTML entities from a string\r
+     * \r
+     * @param s Input string\r
+     * @return A cleaned version of the string\r
+     */\r
+    public static String HtmlDecode(String s) {\r
+        /*\r
+         * TODO: Perhaps we should use something more proven like:\r
+         * http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#unescapeHtml%28java.lang.String%29\r
+         */\r
+\r
+        String ret = "";\r
+        for (int i = 0; i < s.length(); ++i) {\r
+            if (s.charAt(i) == '%') {\r
+                ret += (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);\r
+                i += 2;\r
+            } else {\r
+                ret += s.charAt(i);\r
+            }\r
+        }\r
+        return ret;\r
+    }\r
+\r
+    /**\r
+     * Converts MIME types like "image/jpg" to more end user friendly output\r
+     * like "JPG image".\r
+     * \r
+     * @param mimetype MIME type to convert\r
+     * @return A human friendly version of the MIME type\r
+     */\r
+    public static String convertMIMEtoPrettyPrint(String mimetype) {\r
+        if (mimeType2HUmanReadable.containsKey(mimetype)) {\r
+            return mimeType2HUmanReadable.get(mimetype);\r
+        }\r
+        if (mimetype.split("/").length >= 2)\r
+            return mimetype.split("/")[1].toUpperCase() + " file";\r
+        return "Unknown type";\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Returns the resource identifier of an image resource to use as icon associated to a \r
+     * known MIME type.\r
+     * \r
+     * @param mimetype      MIME type string.\r
+     * @return              Resource identifier of an image resource.\r
+     */\r
+    public static int getResourceId(String mimetype) {\r
+\r
+        if (mimetype == null || "DIR".equals(mimetype)) {\r
+            return R.drawable.ic_menu_archive;\r
+            \r
+        } else {\r
+            String [] parts = mimetype.split("/");\r
+            String type = parts[0];\r
+            String subtype = (parts.length > 1) ? parts[1] : "";\r
+            \r
+            if(TYPE_TXT.equals(type)) {\r
+                return R.drawable.file_doc;\r
+    \r
+            } else if(TYPE_IMAGE.equals(type)) {\r
+                return R.drawable.file_image;\r
+                \r
+            } else if(TYPE_VIDEO.equals(type)) {\r
+                return R.drawable.file_movie;\r
+                \r
+            } else if(TYPE_AUDIO.equals(type)) {  \r
+                return R.drawable.file_sound;\r
+                \r
+            } else if(TYPE_APPLICATION.equals(type)) {\r
+                \r
+                if (SUBTYPE_PDF.equals(subtype)) {\r
+                    return R.drawable.file_pdf;\r
+                    \r
+                } else if (SUBTYPES_DOCUMENT_SET.contains(subtype)) {\r
+                    return R.drawable.file_doc;\r
+\r
+                } else if (SUBTYPES_COMPRESSED_SET.contains(subtype)) {\r
+                    return R.drawable.file_zip;\r
+                }\r
+    \r
+            }\r
+            // problems: RAR, RTF, 3GP are send as application/octet-stream from the server ; extension in the filename should be explicitly reviewed\r
+        }\r
+\r
+        // default icon\r
+        return R.drawable.file;\r
+    }\r
+\r
+    \r
+\r
+    /**\r
+     * Converts Unix time to human readable format\r
+     * @param miliseconds that have passed since 01/01/1970\r
+     * @return The human readable time for the users locale\r
+     */\r
+    public static String unixTimeToHumanReadable(long milliseconds) {\r
+        Date date = new Date(milliseconds);\r
+        return date.toLocaleString();\r
+    }\r
+}\r
index 0c7e991..2520644 100644 (file)
@@ -76,5 +76,11 @@ public class FileStorageUtils {
         String value = uploadPath + OCFile.PATH_SEPARATOR +  (fileName == null ? "" : fileName);
         return value;
     }
+    
+    public static String getParentPath(String remotePath) {
+        String parentPath = new File(remotePath).getParent();
+        parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
+        return parentPath;
+    }
   
 }
\ No newline at end of file
diff --git a/src/com/owncloud/android/utils/Log_OC.java b/src/com/owncloud/android/utils/Log_OC.java
new file mode 100644 (file)
index 0000000..098625a
--- /dev/null
@@ -0,0 +1,129 @@
+package com.owncloud.android.utils;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import com.owncloud.android.MainApp;
+
+import android.util.Log;
+
+
+
+public class Log_OC {
+    
+
+    private static boolean isEnabled = false;
+    private static File logFile;
+    private static File folder;
+    private static BufferedWriter buf;  
+    
+    public static void i(String TAG, String message){
+        // Printing the message to LogCat console
+        int a = Log.i(TAG, message);
+        // Write the log message to the file
+        appendLog(TAG+" : "+message);
+    }
+
+    public static void d(String TAG, String message){
+        Log.d(TAG, message);
+        appendLog(TAG + " : " + message);
+    }
+    public static void d(String TAG, String message, Exception e) {
+        Log.d(TAG, message, e);
+        appendLog(TAG + " : " + message + " Exception : "+ e.getStackTrace());
+    }
+    public static void e(String TAG, String message){
+        Log.e(TAG, message);
+        appendLog(TAG + " : " + message);
+    }
+    
+    public static void e(String TAG, String message, Throwable e) {
+        Log.e(TAG, message, e);
+        appendLog(TAG+" : " + message +" Exception : " + e.getStackTrace());
+    }
+    
+    public static void v(String TAG, String message){
+        Log.v(TAG, message);
+        appendLog(TAG+" : "+ message);
+    }
+    
+    public static void w(String TAG, String message) {
+        Log.w(TAG,message); 
+        appendLog(TAG+" : "+ message);
+    }
+    
+    public static void wtf(String TAG, String message) {
+        Log.wtf(TAG,message); 
+        appendLog(TAG+" : "+ message);
+    }
+    
+    public static void startLogging(String logPath) {
+        folder = new File(logPath);
+        logFile = new File(folder + File.separator + "log.txt");
+        
+        if (!folder.exists()) {
+            folder.mkdirs();
+        }
+        if (logFile.exists()) {
+            logFile.delete();
+        }
+        try { 
+            logFile.createNewFile();
+            buf = new BufferedWriter(new FileWriter(logFile, true));
+            isEnabled = true;
+            appendPhoneInfo();
+        }catch (IOException e){ 
+            e.printStackTrace(); 
+        } 
+    }
+    
+    public static void stopLogging() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());
+        String currentDateandTime = sdf.format(new Date());
+        if (logFile != null) {
+            logFile.renameTo(new File(folder + File.separator + MainApp.getLogName() + currentDateandTime+".log"));
+          
+            isEnabled = false;
+            try {
+                buf.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            } 
+        
+        }
+        
+    }
+    
+    private static void appendPhoneInfo() {
+        appendLog("Model : " + android.os.Build.MODEL);
+        appendLog("Brand : " + android.os.Build.BRAND);
+        appendLog("Product : " + android.os.Build.PRODUCT);
+        appendLog("Device : " + android.os.Build.DEVICE);
+        appendLog("Version-Codename : " + android.os.Build.VERSION.CODENAME);
+        appendLog("Version-Release : " + android.os.Build.VERSION.RELEASE);
+    }
+    
+    private static void appendLog(String text) { 
+        if (isEnabled) {
+           try { 
+               buf.append(text); 
+               buf.newLine(); 
+           } catch (IOException e) { 
+               e.printStackTrace(); 
+        } 
+    }
+}
+
+    
+   
+
+  
+
+   
+   
+}
diff --git a/src/com/owncloud/android/utils/OwnCloudSession.java b/src/com/owncloud/android/utils/OwnCloudSession.java
new file mode 100644 (file)
index 0000000..13ead88
--- /dev/null
@@ -0,0 +1,56 @@
+/* ownCloud Android client application\r
+ *   Copyright (C) 2011  Bartek Przybylski\r
+ *   Copyright (C) 2012-2013 ownCloud Inc.\r
+ *\r
+ *   This program is free software: you can redistribute it and/or modify\r
+ *   it under the terms of the GNU General Public License version 2,\r
+ *   as published by the Free Software Foundation.\r
+ *\r
+ *   This program is distributed in the hope that it will be useful,\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *   GNU General Public License for more details.\r
+ *\r
+ *   You should have received a copy of the GNU General Public License\r
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
+ *\r
+ */\r
+package com.owncloud.android.utils;\r
+\r
+/**\r
+ * Represents a session to an ownCloud instance\r
+ * \r
+ * @author Bartek Przybylski\r
+ * \r
+ */\r
+public class OwnCloudSession {\r
+    private String mSessionName;\r
+    private String mSessionUrl;\r
+    private int mEntryId;\r
+\r
+    public OwnCloudSession(String name, String url, int entryId) {\r
+        mSessionName = name;\r
+        mSessionUrl = url;\r
+        mEntryId = entryId;\r
+    }\r
+\r
+    public void setName(String name) {\r
+        mSessionName = name;\r
+    }\r
+\r
+    public String getName() {\r
+        return mSessionName;\r
+    }\r
+\r
+    public void setUrl(String url) {\r
+        mSessionUrl = url;\r
+    }\r
+\r
+    public String getUrl() {\r
+        return mSessionUrl;\r
+    }\r
+\r
+    public int getEntryId() {\r
+        return mEntryId;\r
+    }\r
+}\r
diff --git a/src/com/owncloud/android/utils/OwnCloudVersion.java b/src/com/owncloud/android/utils/OwnCloudVersion.java
deleted file mode 100644 (file)
index 630e7ac..0000000
+++ /dev/null
@@ -1,85 +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.utils;
-
-public class OwnCloudVersion implements Comparable<OwnCloudVersion> {
-    public static final OwnCloudVersion owncloud_v1 = new OwnCloudVersion(
-            0x010000);
-    public static final OwnCloudVersion owncloud_v2 = new OwnCloudVersion(
-            0x020000);
-    public static final OwnCloudVersion owncloud_v3 = new OwnCloudVersion(
-            0x030000);
-    public static final OwnCloudVersion owncloud_v4 = new OwnCloudVersion(
-            0x040000);
-    public static final OwnCloudVersion owncloud_v4_5 = new OwnCloudVersion(
-            0x040500);
-
-    // format is in version
-    // 0xAABBCC
-    // for version AA.BB.CC
-    // ie version 2.0.3 will be stored as 0x030003
-    private int mVersion;
-    private boolean mIsValid;
-
-    public OwnCloudVersion(int version) {
-        mVersion = version;
-        mIsValid = true;
-    }
-
-    public OwnCloudVersion(String version) {
-        mVersion = 0;
-        mIsValid = false;
-        parseVersionString(version);
-    }
-
-    public String toString() {
-        return ((mVersion >> 16) % 256) + "." + ((mVersion >> 8) % 256) + "."
-                + ((mVersion) % 256);
-    }
-
-    public boolean isVersionValid() {
-        return mIsValid;
-    }
-
-    @Override
-    public int compareTo(OwnCloudVersion another) {
-        return another.mVersion == mVersion ? 0
-                : another.mVersion < mVersion ? 1 : -1;
-    }
-
-    private void parseVersionString(String version) {
-        try {
-            String[] nums = version.split("\\.");
-            if (nums.length > 0) {
-                mVersion += Integer.parseInt(nums[0]);
-            }
-            mVersion = mVersion << 8;
-            if (nums.length > 1) {
-                mVersion += Integer.parseInt(nums[1]);
-            }
-            mVersion = mVersion << 8;
-            if (nums.length > 2) {
-                mVersion += Integer.parseInt(nums[2]);
-            }
-            mIsValid = true;
-        } catch (Exception e) {
-            mIsValid = false;
-        }
-    }
-}
diff --git a/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java b/src/eu/alefzero/webdav/ChunkFromFileChannelRequestEntity.java
deleted file mode 100644 (file)
index a91b64e..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* 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 eu.alefzero.webdav;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.httpclient.methods.RequestEntity;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.network.ProgressiveDataTransferer;
-
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
-
-/**
- * A RequestEntity that represents a PIECE of a file.
- * 
- * @author David A. Velasco
- */
-public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
-
-    private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
-    
-    //private final File mFile;
-    private final FileChannel mChannel;
-    private final String mContentType;
-    private final long mChunkSize;
-    private final File mFile;
-    private long mOffset;
-    private long mTransferred;
-    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
-    private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
-
-    public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
-        super();
-        if (channel == null) {
-            throw new IllegalArgumentException("File may not be null");
-        }
-        if (chunkSize <= 0) {
-            throw new IllegalArgumentException("Chunk size must be greater than zero");
-        }
-        mChannel = channel;
-        mContentType = contentType;
-        mChunkSize = chunkSize;
-        mFile = file;
-        mOffset = 0;
-        mTransferred = 0;
-    }
-    
-    public void setOffset(long offset) {
-        mOffset = offset;
-    }
-    
-    public long getContentLength() {
-        try {
-            return Math.min(mChunkSize, mChannel.size() - mChannel.position());
-        } catch (IOException e) {
-            return mChunkSize;
-        }
-    }
-
-    public String getContentType() {
-        return mContentType;
-    }
-
-    public boolean isRepeatable() {
-        return true;
-    }
-    
-    @Override
-    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.add(listener);
-        }
-    }
-    
-    @Override
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.addAll(listeners);
-        }
-    }
-    
-    @Override
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.remove(listener);
-        }
-    }
-    
-    
-    public void writeRequest(final OutputStream out) throws IOException {
-        int readCount = 0;
-        Iterator<OnDatatransferProgressListener> it = null;
-        
-       try {
-            mChannel.position(mOffset);
-            long size = mFile.length();
-            if (size == 0) size = -1;
-            long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
-            while (mChannel.position() < maxCount) {
-                readCount = mChannel.read(mBuffer);
-                out.write(mBuffer.array(), 0, readCount);
-                mBuffer.clear();
-                if (mTransferred < maxCount) {  // condition to avoid accumulate progress for repeated chunks
-                    mTransferred += readCount;
-                }
-                synchronized (mDataTransferListeners) {
-                    it = mDataTransferListeners.iterator();
-                    while (it.hasNext()) {
-                        it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
-                    }
-                }
-            }
-            
-        } catch (IOException io) {
-            Log_OC.e(TAG, io.getMessage());
-            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
-            
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/eu/alefzero/webdav/FileRequestEntity.java b/src/eu/alefzero/webdav/FileRequestEntity.java
deleted file mode 100644 (file)
index 1d525c4..0000000
+++ /dev/null
@@ -1,134 +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 eu.alefzero.webdav;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.httpclient.methods.RequestEntity;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.network.ProgressiveDataTransferer;
-
-
-import eu.alefzero.webdav.OnDatatransferProgressListener;
-
-
-/**
- * A RequestEntity that represents a File.
- * 
- */
-public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
-
-    final File mFile;
-    final String mContentType;
-    Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
-
-    public FileRequestEntity(final File file, final String contentType) {
-        super();
-        this.mFile = file;
-        this.mContentType = contentType;
-        if (file == null) {
-            throw new IllegalArgumentException("File may not be null");
-        }
-    }
-    
-    @Override
-    public long getContentLength() {
-        return mFile.length();
-    }
-
-    @Override
-    public String getContentType() {
-        return mContentType;
-    }
-
-    @Override
-    public boolean isRepeatable() {
-        return true;
-    }
-
-    @Override
-    public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.add(listener);
-        }
-    }
-    
-    @Override
-    public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.addAll(listeners);
-        }
-    }
-    
-    @Override
-    public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
-        synchronized (mDataTransferListeners) {
-            mDataTransferListeners.remove(listener);
-        }
-    }
-    
-    
-    @Override
-    public void writeRequest(final OutputStream out) throws IOException {
-        //byte[] tmp = new byte[4096];
-        ByteBuffer tmp = ByteBuffer.allocate(4096);
-        int readResult = 0;
-        
-        // TODO(bprzybylski): each mem allocation can throw OutOfMemoryError we need to handle it
-        //                    globally in some fashionable manner
-        RandomAccessFile raf = new RandomAccessFile(mFile, "r");
-        FileChannel channel = raf.getChannel();
-        Iterator<OnDatatransferProgressListener> it = null;
-        long transferred = 0;
-        long size = mFile.length();
-        if (size == 0) size = -1;
-        try {
-            while ((readResult = channel.read(tmp)) >= 0) {
-                out.write(tmp.array(), 0, readResult);
-                tmp.clear();
-                transferred += readResult;
-                synchronized (mDataTransferListeners) {
-                    it = mDataTransferListeners.iterator();
-                    while (it.hasNext()) {
-                        it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
-                    }
-                }
-            }
-            
-        } catch (IOException io) {
-            Log_OC.e("FileRequestException", io.getMessage());
-            throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);   
-            
-        } finally {
-            channel.close();
-            raf.close();
-        }
-    }
-
-}
diff --git a/src/eu/alefzero/webdav/OnDatatransferProgressListener.java b/src/eu/alefzero/webdav/OnDatatransferProgressListener.java
deleted file mode 100644 (file)
index 5c4783a..0000000
+++ /dev/null
@@ -1,24 +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 eu.alefzero.webdav;
-
-public interface OnDatatransferProgressListener {
-    public void onTransferProgress(long progressRate);
-    public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName);
-}
diff --git a/src/eu/alefzero/webdav/WebdavClient.java b/src/eu/alefzero/webdav/WebdavClient.java
deleted file mode 100644 (file)
index 5120928..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2011  Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License 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 eu.alefzero.webdav;
-
-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.Header;
-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.HttpVersion;
-import org.apache.commons.httpclient.URI;
-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.cookie.CookiePolicy;
-import org.apache.commons.httpclient.methods.HeadMethod;
-import org.apache.commons.httpclient.params.HttpMethodParams;
-import org.apache.http.HttpStatus;
-import org.apache.http.params.CoreProtocolPNames;
-
-import com.owncloud.android.Log_OC;
-import com.owncloud.android.MainApp;
-import com.owncloud.android.network.BearerAuthScheme;
-import com.owncloud.android.network.BearerCredentials;
-
-
-
-import android.net.Uri;
-
-public class WebdavClient extends HttpClient {
-    private static final int MAX_REDIRECTIONS_COUNT = 3;
-    
-    private Uri mUri;
-    private Credentials mCredentials;
-    private boolean mFollowRedirects;
-    private String mSsoSessionCookie;
-    private String mAuthTokenType;
-    final private static String TAG = "WebdavClient";
-    public static final String USER_AGENT = "Android-ownCloud";
-    
-    static private byte[] sExhaustBuffer = new byte[1024];
-    
-    /**
-     * Constructor
-     */
-    public WebdavClient(HttpConnectionManager connectionMgr) {
-        super(connectionMgr);
-        Log_OC.d(TAG, "Creating WebdavClient");
-        getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
-        getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
-        mFollowRedirects = true;
-        mSsoSessionCookie = null;
-        mAuthTokenType = MainApp.getAuthTokenTypePass();
-    }
-
-    public void setBearerCredentials(String accessToken) {
-        AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
-        
-        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);
-        mSsoSessionCookie = null;
-        mAuthTokenType = MainApp.getAuthTokenTypeAccessToken();
-    }
-
-    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);
-        mSsoSessionCookie = null;
-        mAuthTokenType = MainApp.getAuthTokenTypePass();
-    }
-    
-    public void setSsoSessionCookie(String accessToken) {
-        getParams().setAuthenticationPreemptive(false);
-        getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
-        mSsoSessionCookie = accessToken;
-        mCredentials = null;
-        mAuthTokenType = MainApp.getAuthTokenTypeSamlSessionCookie();
-    }
-    
-    
-    /**
-     * 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
-     */
-    public boolean existsFile(String path) throws IOException, HttpException {
-        HeadMethod head = new HeadMethod(mUri.toString() + WebdavUtils.encodePath(path));
-        try {
-            int status = executeMethod(head);
-            Log_OC.d(TAG, "HEAD to " + path + " finished with HTTP status " + status + ((status != HttpStatus.SC_OK)?"(FAIL)":""));
-            exhaustResponse(head.getResponseBodyAsStream());
-            return (status == HttpStatus.SC_OK);
-            
-        } finally {
-            head.releaseConnection();    // let the connection available for other methods
-        }
-    }
-    
-    /**
-     * Requests the received method with the received timeout (milliseconds).
-     * 
-     * Executes the method through the inherited HttpClient.executedMethod(method).
-     * 
-     * Sets the socket and connection timeouts only for the method received.
-     * 
-     * The timeouts are both in milliseconds; 0 means 'infinite'; < 0 means 'do not change the default'
-     * 
-     * @param method            HTTP method request.
-     * @param readTimeout       Timeout to set for data reception
-     * @param conntionTimout    Timeout to set for connection establishment
-     */
-    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws HttpException, IOException {
-        int oldSoTimeout = getParams().getSoTimeout();
-        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
-        try {
-            if (readTimeout >= 0) { 
-                method.getParams().setSoTimeout(readTimeout);   // this should be enough...
-                getParams().setSoTimeout(readTimeout);          // ... but this looks like necessary for HTTPS
-            }
-            if (connectionTimeout >= 0) {
-                getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
-            }
-            return executeMethod(method);
-        } finally {
-            getParams().setSoTimeout(oldSoTimeout);
-            getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
-        }
-    }
-    
-    
-    @Override
-    public int executeMethod(HttpMethod method) throws IOException, HttpException {
-        boolean customRedirectionNeeded = false;
-        try {
-            method.setFollowRedirects(mFollowRedirects);
-        } catch (Exception e) {
-            //if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
-            customRedirectionNeeded = mFollowRedirects;
-        }
-        if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
-            method.setRequestHeader("Cookie", mSsoSessionCookie);
-        }
-        int status = super.executeMethod(method);
-        int redirectionsCount = 0;
-        while (customRedirectionNeeded &&
-                redirectionsCount < MAX_REDIRECTIONS_COUNT &&
-                (   status == HttpStatus.SC_MOVED_PERMANENTLY || 
-                    status == HttpStatus.SC_MOVED_TEMPORARILY ||
-                    status == HttpStatus.SC_TEMPORARY_REDIRECT)
-                ) {
-            
-            Header location = method.getResponseHeader("Location");
-            if (location != null) {
-                Log_OC.d(TAG,  "Location to redirect: " + location.getValue());
-                method.setURI(new URI(location.getValue(), true));
-                status = super.executeMethod(method);
-                redirectionsCount++;
-                
-            } else {
-                Log_OC.d(TAG,  "No location to redirect!");
-                status = HttpStatus.SC_NOT_FOUND;
-            }
-        }
-        
-        return status;
-    }
-
-
-    /**
-     * Exhausts a not interesting HTTP response. Encouraged by HttpClient documentation.
-     * 
-     * @param responseBodyAsStream      InputStream with the HTTP response to exhaust.
-     */
-    public void exhaustResponse(InputStream responseBodyAsStream) {
-        if (responseBodyAsStream != null) {
-            try {
-                while (responseBodyAsStream.read(sExhaustBuffer) >= 0);
-                responseBodyAsStream.close();
-            
-            } catch (IOException io) {
-                Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response; will be IGNORED", io);
-            }
-        }
-    }
-
-    /**
-     * Sets the connection and wait-for-data timeouts to be applied by default to the methods performed by this client.
-     */
-    public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
-            getParams().setSoTimeout(defaultDataTimeout);
-            getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
-    }
-
-    /**
-     * Sets the base URI for the helper methods that receive paths as parameters, instead of full URLs
-     * @param uri
-     */
-    public void setBaseUri(Uri uri) {
-        mUri = uri;
-    }
-
-    public Uri getBaseUri() {
-        return mUri;
-    }
-
-    public final Credentials getCredentials() {\r
-        return mCredentials;\r
-    }
-    
-    public final String getSsoSessionCookie() {
-        return mSsoSessionCookie;
-    }
-
-    public void setFollowRedirects(boolean followRedirects) {
-        mFollowRedirects = followRedirects;
-    }
-
-    public String getAuthTokenType() {
-        return mAuthTokenType;
-    }
-
-}
diff --git a/src/eu/alefzero/webdav/WebdavEntry.java b/src/eu/alefzero/webdav/WebdavEntry.java
deleted file mode 100644 (file)
index 1c6ba69..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2012  ownCloud
- *
- *   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 eu.alefzero.webdav;
-
-import java.util.Date;
-
-import org.apache.jackrabbit.webdav.MultiStatusResponse;
-import org.apache.jackrabbit.webdav.property.DavProperty;
-import org.apache.jackrabbit.webdav.property.DavPropertyName;
-import org.apache.jackrabbit.webdav.property.DavPropertySet;
-
-import com.owncloud.android.Log_OC;
-
-
-import android.net.Uri;
-
-public class WebdavEntry {
-    private String mName, mPath, mUri, mContentType, mEtag;
-    private long mContentLength, mCreateTimestamp, mModifiedTimestamp;
-
-    public WebdavEntry(MultiStatusResponse ms, String splitElement) {
-        resetData();
-        if (ms.getStatus().length != 0) {
-            mUri = ms.getHref();
-
-            mPath = mUri.split(splitElement, 2)[1];
-
-            int status = ms.getStatus()[0].getStatusCode();
-            DavPropertySet propSet = ms.getProperties(status);
-            @SuppressWarnings("rawtypes")
-            DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
-            if (prop != null) {
-                mName = (String) prop.getName().toString();
-                mName = mName.substring(1, mName.length()-1);
-            }
-            else {
-                String[] tmp = mPath.split("/");
-                if (tmp.length > 0)
-                    mName = tmp[tmp.length - 1];
-            }
-
-            // use unknown mimetype as default behavior
-            mContentType = "application/octet-stream";
-            prop = propSet.get(DavPropertyName.GETCONTENTTYPE);
-            if (prop != null) {
-                mContentType = (String) prop.getValue();
-                // dvelasco: some builds of ownCloud server 4.0.x added a trailing ';' to the MIME type ; if looks fixed, but let's be cautious
-                if (mContentType.indexOf(";") >= 0) {
-                    mContentType = mContentType.substring(0, mContentType.indexOf(";"));
-                }
-            }
-            
-            // check if it's a folder in the standard way: see RFC2518 12.2 . RFC4918 14.3 
-            prop = propSet.get(DavPropertyName.RESOURCETYPE);
-            if (prop!= null) {
-                Object value = prop.getValue();
-                if (value != null) {
-                    mContentType = "DIR";   // a specific attribute would be better, but this is enough; unless while we have no reason to distinguish MIME types for folders
-                }
-            }
-
-            prop = propSet.get(DavPropertyName.GETCONTENTLENGTH);
-            if (prop != null)
-                mContentLength = Long.parseLong((String) prop.getValue());
-
-            prop = propSet.get(DavPropertyName.GETLASTMODIFIED);
-            if (prop != null) {
-                Date d = WebdavUtils
-                        .parseResponseDate((String) prop.getValue());
-                mModifiedTimestamp = (d != null) ? d.getTime() : 0;
-            }
-
-            prop = propSet.get(DavPropertyName.CREATIONDATE);
-            if (prop != null) {
-                Date d = WebdavUtils
-                        .parseResponseDate((String) prop.getValue());
-                mCreateTimestamp = (d != null) ? d.getTime() : 0;
-            }
-            
-            prop = propSet.get(DavPropertyName.GETETAG);
-            if (prop != null) {
-                mEtag = (String) prop.getValue();
-                mEtag = mEtag.substring(1, mEtag.length()-1);
-            }
-
-        } else {
-            Log_OC.e("WebdavEntry",
-                    "General fuckup, no status for webdav response");
-        }
-    }
-
-    public String path() {
-        return mPath;
-    }
-    
-    public String decodedPath() {
-        return Uri.decode(mPath);
-    }
-
-    public String name() {
-        return mName;
-    }
-
-    public boolean isDirectory() {
-        return mContentType.equals("DIR");
-    }
-
-    public String contentType() {
-        return mContentType;
-    }
-
-    public String uri() {
-        return mUri;
-    }
-
-    public long contentLength() {
-        return mContentLength;
-    }
-
-    public long createTimestamp() {
-        return mCreateTimestamp;
-    }
-
-    public long modifiedTimestamp() {
-        return mModifiedTimestamp;
-    }
-    
-    public String etag() {
-        return mEtag;
-    }
-
-    private void resetData() {
-        mName = mUri = mContentType = null;
-        mContentLength = mCreateTimestamp = mModifiedTimestamp = 0;
-    }
-}
diff --git a/src/eu/alefzero/webdav/WebdavUtils.java b/src/eu/alefzero/webdav/WebdavUtils.java
deleted file mode 100644 (file)
index 132a1f9..0000000
+++ /dev/null
@@ -1,76 +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 eu.alefzero.webdav;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-import android.net.Uri;
-
-public class WebdavUtils {
-    public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
-            "dd.MM.yyyy hh:mm");
-    private static final SimpleDateFormat DATETIME_FORMATS[] = {
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
-            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US),
-            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US),
-            new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US),
-            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
-            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
-
-    public static String prepareXmlForPropFind() {
-        String ret = "<?xml version=\"1.0\" ?><D:propfind xmlns:D=\"DAV:\"><D:allprop/></D:propfind>";
-        return ret;
-    }
-
-    public static String prepareXmlForPatch() {
-        return "<?xml version=\"1.0\" ?><D:propertyupdate xmlns:D=\"DAV:\"></D:propertyupdate>";
-    }
-
-    public static Date parseResponseDate(String date) {
-        Date returnDate = null;
-        for (int i = 0; i < DATETIME_FORMATS.length; ++i) {
-            try {
-                returnDate = DATETIME_FORMATS[i].parse(date);
-                return returnDate;
-            } catch (ParseException e) {
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Encodes a path according to URI RFC 2396. 
-     * 
-     * If the received path doesn't start with "/", the method adds it.
-     * 
-     * @param remoteFilePath    Path
-     * @return                  Encoded path according to RFC 2396, always starting with "/"
-     */
-    public static String encodePath(String remoteFilePath) {
-        String encodedPath = Uri.encode(remoteFilePath, "/");
-        if (!encodedPath.startsWith("/"))
-            encodedPath = "/" + encodedPath;
-        return encodedPath;
-    }
-    
-}
index 6652724..9b141f6 100644 (file)
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry combineaccessrules="false" kind="src" path="/owncloud-android"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/owncloud-android"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="gen"/>
        <classpathentry kind="output" path="bin/classes"/>
 </classpath>
diff --git a/tests/ant.properties b/tests/ant.properties
new file mode 100644 (file)
index 0000000..1624402
--- /dev/null
@@ -0,0 +1,18 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked into Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+#  'source.dir' for the location of your java source folder and
+#  'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+#  'key.store' for the location of your keystore and
+#  'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
+tested.project.dir=..
diff --git a/tests/build.xml b/tests/build.xml
new file mode 100644 (file)
index 0000000..3e82196
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="ownCloudTest" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
index a3ee5ab..4ab1256 100644 (file)
@@ -11,4 +11,4 @@
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
 # Project target.
-target=android-17
+target=android-19
index 529776b..1524d3b 100644 (file)
@@ -20,8 +20,8 @@ package com.owncloud.android.test;
 
 import android.test.AndroidTestCase;
 
-import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.utils.OwnCloudVersion;
+import com.owncloud.android.oc_framework.accounts.AccountUtils;
+import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
 
 public class AccountUtilsTest extends AndroidTestCase {