Merge branch 'develop' into introduce-travis-ci

This commit is contained in:
Thomas Müller 2014-03-13 11:01:19 +01:00
commit c0b85157a9
244 changed files with 6058 additions and 7306 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "actionbarsherlock"] [submodule "actionbarsherlock"]
path = actionbarsherlock path = actionbarsherlock
url = git://github.com/JakeWharton/ActionBarSherlock.git url = git://github.com/JakeWharton/ActionBarSherlock.git
[submodule "owncloud-android-library"]
path = owncloud-android-library
url = git://github.com/owncloud/android-library.git

View file

@ -18,8 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
--> -->
<manifest package="com.owncloud.android" <manifest package="com.owncloud.android"
android:versionCode="105002" android:versionCode="105004"
android:versionName="1.5.2" xmlns:android="http://schemas.android.com/apk/res/android"> android:versionName="1.5.4" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.USE_CREDENTIALS" />
@ -54,7 +54,6 @@
> >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -83,7 +82,8 @@
<data android:mimeType="*/*" > <data android:mimeType="*/*" >
</data> </data>
</intent-filter>
</intent-filter>
</activity> </activity>
<activity <activity
android:name=".ui.activity.Preferences" android:name=".ui.activity.Preferences"
@ -92,11 +92,15 @@
<activity android:name=".ui.activity.PreferencesNewSessionewSession" > <activity android:name=".ui.activity.PreferencesNewSessionewSession" >
</activity> </activity>
<activity android:name=".ui.preview.PreviewImageActivity" /> <activity
android:name=".ui.preview.PreviewImageActivity"
/>
<activity android:name=".ui.preview.PreviewVideoActivity" <activity
android:label="@string/app_name" android:name=".ui.preview.PreviewVideoActivity"
android:theme="@style/Theme.ownCloud.Fullscreen" > android:label="@string/app_name"
android:theme="@style/Theme.ownCloud.Fullscreen"
>
</activity> </activity>
<service <service
@ -149,6 +153,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".services.OperationsService" />
<service android:name=".files.services.FileDownloader" /> <service android:name=".files.services.FileDownloader" />
<service android:name=".files.services.FileUploader" /> <service android:name=".files.services.FileUploader" />
<service android:name=".media.MediaService" /> <service android:name=".media.MediaService" />
@ -180,6 +185,11 @@
</receiver> </receiver>
<service android:name=".files.services.FileObserverService"/> <service android:name=".files.services.FileObserverService"/>
<activity
android:name=".ui.activity.CopyToClipboardActivity"
android:label="@string/copy_link"
android:icon="@drawable/copy_link" />
</application> </application>
</manifest> </manifest>

View file

@ -12,6 +12,7 @@ NOTE: You must have git in your environment path variable to perform the next op
* Pull changes from your develop branch: "git pull 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 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" * Make sure to get the latest changes from official android/develop branch: "git pull upstream develop"
* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" .
At this point you can continue using different tools to build the project. Section 2, 3 and 4 describe some of the existing alternatives. At this point you can continue using different tools to build the project. Section 2, 3 and 4 describe some of the existing alternatives.
@ -19,23 +20,24 @@ At this point you can continue using different tools to build the project. Secti
NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable. 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 clean" .
* Run "ant debug" to generate a debuggable version of the ownCkoud app. * Run "ant debug" to generate a debuggable version of the ownCloud app.
### 3. Building with console/maven: ### 3. Building with console/maven:
NOTE: You must have mvn (version >= 3.1.1) in your environment path. Current Android 'platforms-tools' need to be installed. NOTE: You must have mvn (version >= 3.1.1) in your environment path. Current Android 'platforms-tools' need to be installed.
* Download/install Android plugin for Maven, then build ownCloud with mvn: Download/install Android plugin for Maven, install owncloud-android-library, then build ownCloud with mvn:
* "cd .."
* "git clone https://github.com/mosabua/maven-android-sdk-deployer.git" * cd ..
* "cd maven-android-sdk-deployer" * git clone https://github.com/mosabua/maven-android-sdk-deployer.git
* "mvn -pl com.simpligility.android.sdk-deployer:android-19 -am install" * cd maven-android-sdk-deployer
* "cd ../android/oc_framework" * mvn -pl com.simpligility.android.sdk-deployer:android-19 -am install
* "mvn install" * cd ../android/owncloud-android-library
* "cd .." * mvn install
* Now you can create ownCloud APK using "mvn package" * cd ..
Now you can create ownCloud APK using "mvn package"
### 4. Building with Eclipse: ### 4. Building with Eclipse:
@ -46,15 +48,15 @@ NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in
* Clean project and compile. * 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. * 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. * Make sure android/actionbarsherlock/library/bin/library.jar was created.
* Create a new "Android Project from Existing Code". Choose android/oc_framework as root. * Create a new "Android Project from Existing Code". Choose android/owncloud-android-library as root.
* Clean project and compile. * Clean project and compile.
* If any error appear, check the project properties; in the 'Android' section, API Level should be 19 or greater. * 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. * Make sure android/owncloud-android-library/bin/classes.jar was created.
* Import ownCloud Android project. * Import ownCloud Android project.
* Clean project and compile. * Clean project and compile.
* If any error appears, check the project properties of owncloud-android project; in the 'Android' section: * If any error appears, check the project properties of owncloud-android project; in the 'Android' section:
- API Level should be 19 or greater. - 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. - Two library projects should appear referred in the bottom square: actionbarsherlock/library and owncloud-android-library. Add them if needed.
* After those actions you should be good to go. HAVE FUN! * 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. NOTE: Even though API level is set to 19, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8.
@ -70,6 +72,16 @@ NOTE: You must sign the [Contributor Agreement][1] before your changes can be ac
* Again, click "Edit" and set "compare:develop" * Again, click "Edit" and set "compare:develop"
* Enter description and send pull request. * Enter description and send pull request.
### 6. Create another pull request:
To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/develop.
* git fetch upstream
* git checkout -b my_new_develop_branch upstream/develop
* If you want to rename that branch later: "git checkout -b my_new_develop_branch_with_new_name"
* Push branch to server: "git push -u origin name_of_local_develop_branch"
* Use Github to issue PR
[0]: https://github.com/owncloud/android/blob/master/CONTRIBUTING.md [0]: https://github.com/owncloud/android/blob/master/CONTRIBUTING.md
[1]: http://owncloud.org/about/contributor-agreement/ [1]: http://owncloud.org/about/contributor-agreement/

View file

@ -1,10 +0,0 @@
<?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 exported="true" kind="lib" path="/oc_framework/bin/oc_framework.jar" sourcepath="/oc_framework"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,33 +0,0 @@
<?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>

View file

@ -1,4 +0,0 @@
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

View file

@ -1,36 +0,0 @@
<?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-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<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="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View file

@ -1,34 +0,0 @@
<?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>

View file

@ -1,4 +0,0 @@
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

View file

@ -1,17 +0,0 @@
<?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>

View file

@ -1,14 +0,0 @@
# 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Oc_framework-testTest</string>
</resources>

View file

@ -1,113 +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.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);
}
}

View file

@ -1,80 +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.oc_framework_test_project.test;
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 Delete a File Operation
* @author masensio
*
*/
public class DeleteFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Folder data to delete. */
private final String mFolderPath = "/folderToDelete";
/* File to delete. */
private final String mFilePath = "fileToDelete.png";
private TestActivity mActivity;
public DeleteFileTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
}
/**
* Test Remove Folder
*/
public void testRemoveFolder() {
RemoteOperationResult result = mActivity.removeFile(mFolderPath);
assertTrue(result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND);
}
/**
* Test Remove File
*/
public void testRemoveFile() {
RemoteOperationResult result = mActivity.removeFile(mFilePath);
assertTrue(result.isSuccess() || result.getCode() == ResultCode.FILE_NOT_FOUND);
}
/**
* Restore initial conditions
*/
public void testRestoreInitialConditions() {
RemoteOperationResult result = mActivity.createFolder(mFolderPath, true);
assertTrue(result.isSuccess());
}
}

View file

@ -1,123 +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.oc_framework_test_project.test;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.owncloud.android.oc_framework.operations.RemoteFile;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework_test_project.TestActivity;
import android.test.ActivityInstrumentationTestCase2;
/**
* Class to test Download File Operation
* @author masensio
*
*/
public class DownloadFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Files to download. These files must exist on the account */
private final String mRemoteFilePng = "/fileToDownload.png";
private final String mRemoteFileChunks = "/fileToDownload.mp4";
private final String mRemoteFileSpecialChars = "/@file@download.png";
private final String mRemoteFileSpecialCharsChunks = "/@file@download.mp4";
private final String mRemoteFileNotFound = "/fileNotFound.png"; /* This file mustn't exist on the account */
private String mCurrentDate;
private TestActivity mActivity;
public DownloadFileTest() {
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 Download a File
*/
public void testDownloadFile() {
String temporalFolder = "/download" + mCurrentDate;
RemoteFile remoteFile= new RemoteFile(mRemoteFilePng);
RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder);
assertTrue(result.isSuccess());
}
/**
* Test Download a File with chunks
*/
public void testDownloadFileChunks() {
String temporalFolder = "/download" + mCurrentDate;
RemoteFile remoteFile= new RemoteFile(mRemoteFileChunks);
RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder);
assertTrue(result.isSuccess());
}
/**
* Test Download a File with special chars
*/
public void testDownloadFileSpecialChars() {
String temporalFolder = "/download" + mCurrentDate;
RemoteFile remoteFile= new RemoteFile(mRemoteFileSpecialChars);
RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder);
assertTrue(result.isSuccess());
}
/**
* Test Download a File with special chars and chunks
*/
public void testDownloadFileSpecialCharsChunks() {
String temporalFolder = "/download" + mCurrentDate;
RemoteFile remoteFile= new RemoteFile(mRemoteFileSpecialCharsChunks);
RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder);
assertTrue(result.isSuccess());
}
/**
* Test Download a Not Found File
*/
public void testDownloadFileNotFound() {
String temporalFolder = "/download" + mCurrentDate;
RemoteFile remoteFile = new RemoteFile(mRemoteFileNotFound);
RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder);
assertFalse(result.isSuccess());
}
}

View file

@ -1,61 +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.oc_framework_test_project.test;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework_test_project.TestActivity;
import android.test.ActivityInstrumentationTestCase2;
/**
* Class to test Read File Operation
* @author masensio
*
*/
public class ReadFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* File data to read. This file must exist on the account */
private final String mRemoteFolderPath = "/fileToRead.txt";
private TestActivity mActivity;
public ReadFileTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
}
/**
* Test Read File
*/
public void testReadFile() {
RemoteOperationResult result = mActivity.readFile(mRemoteFolderPath);
assertTrue(result.getData().size() == 1);
assertTrue(result.isSuccess());
}
}

View file

@ -1,62 +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.oc_framework_test_project.test;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework_test_project.TestActivity;
import android.test.ActivityInstrumentationTestCase2;
/**
* Class to test Read Folder Operation
* @author masensio
*
*/
public class ReadFolderTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Folder data to read. This folder must exist on the account */
private final String mRemoteFolderPath = "/folderToRead";
private TestActivity mActivity;
public ReadFolderTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
}
/**
* Test Read Folder
*/
public void testReadFolder() {
RemoteOperationResult result = mActivity.readFile(mRemoteFolderPath);
assertTrue(result.getData().size() > 1);
assertTrue(result.getData().size() == 4);
assertTrue(result.isSuccess());
}
}

View file

@ -1,170 +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.oc_framework_test_project.test;
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 Rename File Operation
* @author masensio
*
*/
public class RenameFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Folder data to rename. This folder must exist on the account */
private final String mOldFolderName = "folderToRename";
private final String mOldFolderPath = "/folderToRename";
private final String mNewFolderName = "renamedFolder";
private final String mNewFolderPath = "/renamedFolder";
/* File data to rename. This file must exist on the account */
private final String mOldFileName = "fileToRename.png";
private final String mOldFilePath = "/fileToRename.png";
private final String mNewFileName = "renamedFile";
private final String mFileExtension = ".png";
private final String mNewFilePath ="/renamedFile.png";
private TestActivity mActivity;
public RenameFileTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
}
/**
* Test Rename Folder
*/
public void testRenameFolder() {
RemoteOperationResult result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName, true);
assertTrue(result.isSuccess());
}
/**
* Test Rename Folder with forbidden characters : \ < > : " | ? *
*/
public void testRenameFolderForbiddenChars() {
RemoteOperationResult result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "\\", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "<", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + ">", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + ":", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "\"", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "|", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "?", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFolderName, mOldFolderPath,
mNewFolderName + "*", true);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
}
/**
* Test Rename File
*/
public void testRenameFile() {
RemoteOperationResult result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + mFileExtension, false);
assertTrue(result.isSuccess());
}
/**
* Test Rename Folder with forbidden characters: \ < > : " | ? *
*/
public void testRenameFileForbiddenChars() {
RemoteOperationResult result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "\\" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "<" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + ">" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + ":" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "\"" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "|" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "?" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
result = mActivity.renameFile(mOldFileName, mOldFilePath,
mNewFileName + "*" + mFileExtension, false);
assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME);
}
/**
* Restore initial conditions
*/
public void testRestoreInitialConditions() {
RemoteOperationResult result = mActivity.renameFile(mNewFolderName, mNewFolderPath, mOldFolderName, true);
assertTrue(result.isSuccess());
result = mActivity.renameFile(mNewFileName + mFileExtension, mNewFilePath, mOldFileName, false);
assertTrue(result.isSuccess());
}
}

View file

@ -1,161 +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.oc_framework_test_project.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.res.AssetManager;
import android.os.Environment;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework_test_project.TestActivity;
/**
* Class to test Update File Operation
* @author masensio
*
*/
public class UploadFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Files to upload. These files must exists on the device */
private final String mFileToUpload = "fileToUpload.png";
private final String mMimeType = "image/png";
private final String mFileToUploadWithChunks = "fileToUploadChunks.MP4";
private final String mMimeTypeWithChunks = "video/mp4";
private final String mFileNotFound = "fileNotFound.png";
private final String mStoragePath = "/owncloud/tmp/uploadTest";
private String mPath;
private String mCurrentDate;
private TestActivity mActivity;
public UploadFileTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
mCurrentDate = sdf.format(new Date());
File sdCard = Environment.getExternalStorageDirectory();
mPath = sdCard.getAbsolutePath() + "/" + mStoragePath + mCurrentDate;
//mActivity.createFolder(mPath, true);
copyAssets();
}
/**
* Copy Files to ulpload to SdCard
*/
private void copyAssets() {
AssetManager assetManager = getActivity().getAssets();
String[] files = { mFileToUpload, mFileToUploadWithChunks };
// Folder with contents
File folder = new File(mPath);
folder.mkdirs();
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(folder, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
/**
* Test Upload File without chunks
*/
public void testUploadFile() {
String storagePath = mPath + "/" + mFileToUpload;
//String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload;
String remotePath = "/" + mFileToUpload;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType);
assertTrue(result.isSuccess());
}
/**
* Test Upload File with chunks
*/
public void testUploadFileWithChunks() {
String storagePath = mPath + "/" + mFileToUploadWithChunks;
//String remotePath = "/uploadTest" + mCurrentDate + "/" +mFileToUploadWithChunks;
String remotePath = "/" + mFileToUploadWithChunks;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeTypeWithChunks);
assertTrue(result.isSuccess());
}
/**
* Test Upload Not Found File
*/
public void testUploadFileNotFound() {
String storagePath = mPath + "/" + mFileNotFound;
//String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload;
String remotePath = "/" + mFileNotFound;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType);
assertFalse(result.isSuccess());
}
}

View file

@ -1,15 +0,0 @@
# 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,16 +0,0 @@
<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>

View file

@ -1,9 +0,0 @@
<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>

View file

@ -1,8 +0,0 @@
<resources>
<!--
Customize dimensions originally defined in res/values/dimens.xml (such as
screen margins) for sw600dp devices (e.g. 7" tablets) here.
-->
</resources>

View file

@ -1,9 +0,0 @@
<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>

View file

@ -1,11 +0,0 @@
<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>

View file

@ -1,12 +0,0 @@
<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>

View file

@ -1,7 +0,0 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View file

@ -1,9 +0,0 @@
<?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>
<string name="test_account_not_found">The test account %1$s could not be found in the device</string>
</resources>

View file

@ -1,20 +0,0 @@
<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>

View file

@ -1,173 +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.oc_framework_test_project;
import java.io.File;
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.RemoteFile;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework.operations.remote.ChunkedUploadRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
import com.owncloud.android.oc_framework.operations.remote.DownloadRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFolderOperation;
import com.owncloud.android.oc_framework.operations.remote.RemoveRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.RenameRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.UploadRemoteFileOperation;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
/**
* Activity to test OC framework
* @author masensio
* @author David A. Velasco
*/
public class TestActivity extends Activity {
// This account must exists on the simulator / device
private static final String mServerUri = "https://beta.owncloud.com/owncloud/remote.php/webdav";
private static final String mUser = "testandroid";
private static final String mPass = "testandroid";
private static final boolean mChunked = true;
//private Account mAccount = null;
private WebdavClient mClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Uri uri = Uri.parse(mServerUri);
mClient = OwnCloudClientFactory.createOwnCloudClient(uri ,getApplicationContext(), true);
mClient.setBasicCredentials(mUser, mPass);
}
@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 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.
*
* @return
*/
public RemoteOperationResult createFolder(String remotePath, boolean createFullPath) {
CreateRemoteFolderOperation createOperation = new CreateRemoteFolderOperation(remotePath, createFullPath);
RemoteOperationResult result = createOperation.execute(mClient);
return result;
}
/**
* Access to the library method to Rename a File or Folder
* @param oldName Old name of the file.
* @param oldRemotePath Old remote path of the file. For folders it starts and ends by "/"
* @param newName New name to set as the name of file.
* @param isFolder 'true' for folder and 'false' for files
*
* @return
*/
public RemoteOperationResult renameFile(String oldName, String oldRemotePath, String newName, boolean isFolder) {
RenameRemoteFileOperation renameOperation = new RenameRemoteFileOperation(oldName, oldRemotePath, newName, isFolder);
RemoteOperationResult result = renameOperation.execute(mClient);
return result;
}
/**
* Access to the library method to Remove a File or Folder
*
* @param remotePath Remote path of the file or folder in the server.
* @return
*/
public RemoteOperationResult removeFile(String remotePath) {
RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
RemoteOperationResult result = removeOperation.execute(mClient);
return result;
}
/**
* Access to the library method to Read a Folder (PROPFIND DEPTH 1)
* @param remotePath
*
* @return
*/
public RemoteOperationResult readFile(String remotePath) {
ReadRemoteFolderOperation readOperation= new ReadRemoteFolderOperation(remotePath);
RemoteOperationResult result = readOperation.execute(mClient);
return result;
}
/**
* Access to the library method to Download a File
* @param remotePath
*
* @return
*/
public RemoteOperationResult downloadFile(RemoteFile remoteFile, String temporalFolder) {
// Create folder
String path = "/owncloud/tmp/" + temporalFolder;
File sdCard = Environment.getExternalStorageDirectory();
File folder = new File(sdCard.getAbsolutePath() + "/" + path);
folder.mkdirs();
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remoteFile, folder.getAbsolutePath());
RemoteOperationResult result = downloadOperation.execute(mClient);
return result;
}
/** Access to the library method to Upload a File
* @param storagePath
* @param remotePath
* @param mimeType
*
* @return
*/
public RemoteOperationResult uploadFile(String storagePath, String remotePath, String mimeType) {
UploadRemoteFileOperation uploadOperation;
if ( mChunked && (new File(storagePath)).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
uploadOperation = new ChunkedUploadRemoteFileOperation(storagePath, remotePath, mimeType);
} else {
uploadOperation = new UploadRemoteFileOperation(storagePath, remotePath, mimeType);
}
RemoteOperationResult result = uploadOperation.execute(mClient);
return result;
}
}

View file

@ -1,9 +0,0 @@
<?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>

View file

@ -1,33 +0,0 @@
<?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>

View file

@ -1,4 +0,0 @@
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

View file

@ -1,11 +0,0 @@
<?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>

View file

@ -1,92 +0,0 @@
<?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>

View file

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.owncloud.android</groupId>
<artifactId>oc_framework</artifactId>
<version>${owncloud.version}</version>
<packaging>jar</packaging>
<name>oc_framework for Owncloud Android</name>
<properties>
<owncloud.version>1.5.1-SNAPSHOT</owncloud.version>
<java-version>1.6</java-version>
<!-- Given by maven-android-sdk-deployer -->
<google.android-version>4.4_r1</google.android-version>
<!-- Usually the latest Android API -->
<google.android-api>19</google.android-api>
</properties>
<description>oc_framwork for Owncloud for Android</description>
<dependencies>
<dependency>
<groupId>android</groupId>
<artifactId>android</artifactId>
<version>${google.android-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-webdav</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
</configuration>
</plugin>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<sdk>
<path>${env.ANDROID_HOME}</path>
<platform>${google.android-api}</platform>
</sdk>
</configuration>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</project>

View file

@ -1,15 +0,0 @@
# 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

View file

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources/>

View file

@ -1,43 +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.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";
}
}

View file

@ -1,128 +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.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 = -1684392454798508693L;
private Account mFailedAccount;
public AccountNotFoundException(Account failedAccount, String message, Throwable cause) {
super(message, cause);
mFailedAccount = failedAccount;
}
public Account getFailedAccount() {
return mFailedAccount;
}
}
}

View file

@ -1,289 +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.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.Provider;
import java.security.cert.X509Certificate;
//import java.util.Enumeration;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
//import javax.net.ssl.SSLParameters;
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.os.Build;
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;
}
/*
private void logSslInfo() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
Log.v(TAG, "SUPPORTED SSL PARAMETERS");
logSslParameters(mSslContext.getSupportedSSLParameters());
Log.v(TAG, "DEFAULT SSL PARAMETERS");
logSslParameters(mSslContext.getDefaultSSLParameters());
Log.i(TAG, "CURRENT PARAMETERS");
Log.i(TAG, "Protocol: " + mSslContext.getProtocol());
}
Log.i(TAG, "PROVIDER");
logSecurityProvider(mSslContext.getProvider());
}
private void logSecurityProvider(Provider provider) {
Log.i(TAG, "name: " + provider.getName());
Log.i(TAG, "version: " + provider.getVersion());
Log.i(TAG, "info: " + provider.getInfo());
Enumeration<?> keys = provider.propertyNames();
String key;
while (keys.hasMoreElements()) {
key = (String) keys.nextElement();
Log.i(TAG, " property " + key + " : " + provider.getProperty(key));
}
}
private void logSslParameters(SSLParameters params) {
Log.v(TAG, "Cipher suites: ");
String [] elements = params.getCipherSuites();
for (int i=0; i<elements.length ; i++) {
Log.v(TAG, " " + elements[i]);
}
Log.v(TAG, "Protocols: ");
elements = params.getProtocols();
for (int i=0; i<elements.length ; i++) {
Log.v(TAG, " " + elements[i]);
}
}
*/
/**
* 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();
//logSslInfo();
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);
ServerNameIndicator.setServerNameIndication(host, (SSLSocket)socket);
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;
}
}
}

View file

@ -1,148 +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.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;
}
}
}

View file

@ -1,272 +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.oc_framework.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 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");
}
}

View file

@ -1,98 +0,0 @@
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;
}
}

View file

@ -1,131 +0,0 @@
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);
}
}

View file

@ -1,168 +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.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;
}
}

View file

@ -1,34 +0,0 @@
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);
}

View file

@ -1,144 +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.oc_framework.network;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLSocket;
import android.util.Log;
/**
* Enables the support of Server Name Indication if existing
* in the underlying network implementation.
*
* Build as a singleton.
*
* @author David A. Velasco
*/
public class ServerNameIndicator {
private static final String TAG = ServerNameIndicator.class.getSimpleName();
private static final AtomicReference<ServerNameIndicator> mSingleInstance = new AtomicReference<ServerNameIndicator>();
private static final String METHOD_NAME = "setHostname";
private final WeakReference<Class<?>> mSSLSocketClassRef;
private final WeakReference<Method> mSetHostnameMethodRef;
/**
* Private constructor, class is a singleton.
*
* @param sslSocketClass Underlying implementation class of {@link SSLSocket} used to connect with the server.
* @param setHostnameMethod Name of the method to call to enable the SNI support.
*/
private ServerNameIndicator(Class<?> sslSocketClass, Method setHostnameMethod) {
mSSLSocketClassRef = new WeakReference<Class<?>>(sslSocketClass);
mSetHostnameMethodRef = (setHostnameMethod == null) ? null : new WeakReference<Method>(setHostnameMethod);
}
/**
* Calls the {@code #setHostname(String)} method of the underlying implementation
* of {@link SSLSocket} if exists.
*
* Creates and initializes the single instance of the class when needed
*
* @param hostname The name of the server host of interest.
* @param sslSocket Client socket to connect with the server.
*/
public static void setServerNameIndication(String hostname, SSLSocket sslSocket) {
final Method setHostnameMethod = getMethod(sslSocket);
if (setHostnameMethod != null) {
try {
setHostnameMethod.invoke(sslSocket, hostname);
Log.i(TAG, "SNI done, hostname: " + hostname);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (IllegalAccessException e) {
Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "Call to SSLSocket#setHost(String) failed ", e);
}
} else {
Log.i(TAG, "SNI not supported");
}
}
/**
* Gets the method to invoke trying to minimize the effective
* application of reflection.
*
* @param sslSocket Instance of the SSL socket to use in connection with server.
* @return Method to call to indicate the server name of interest to the server.
*/
private static Method getMethod(SSLSocket sslSocket) {
final Class<?> sslSocketClass = sslSocket.getClass();
final ServerNameIndicator instance = mSingleInstance.get();
if (instance == null) {
return initFrom(sslSocketClass);
} else if (instance.mSSLSocketClassRef.get() != sslSocketClass) {
// the underlying class changed
return initFrom(sslSocketClass);
} else if (instance.mSetHostnameMethodRef == null) {
// SNI not supported
return null;
} else {
final Method cachedSetHostnameMethod = instance.mSetHostnameMethodRef.get();
return (cachedSetHostnameMethod == null) ? initFrom(sslSocketClass) : cachedSetHostnameMethod;
}
}
/**
* Singleton initializer.
*
* Uses reflection to extract and 'cache' the method to invoke to indicate the desited host name to the server side.
*
* @param sslSocketClass Underlying class providing the implementation of {@link SSLSocket}.
* @return Method to call to indicate the server name of interest to the server.
*/
private static Method initFrom(Class<?> sslSocketClass) {
Log.i(TAG, "SSLSocket implementation: " + sslSocketClass.getCanonicalName());
Method setHostnameMethod = null;
try {
setHostnameMethod = sslSocketClass.getMethod(METHOD_NAME, String.class);
} catch (SecurityException e) {
Log.e(TAG, "Could not access to SSLSocket#setHostname(String) method ", e);
} catch (NoSuchMethodException e) {
Log.i(TAG, "Could not find SSLSocket#setHostname(String) method - SNI not supported");
}
mSingleInstance.set(new ServerNameIndicator(sslSocketClass, setHostnameMethod));
return setHostnameMethod;
}
}

View file

@ -1,145 +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.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);
}
}
}

View file

@ -1,132 +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.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();
}
}
}

View file

@ -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 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);
}

View file

@ -1,151 +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.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;
}
}

View file

@ -1,245 +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 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;
}
}

View file

@ -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 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;
}
}

View file

@ -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 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;
}
}

View file

@ -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.oc_framework.operations;
public interface OnRemoteOperationListener {
void onRemoteOperationFinish(RemoteOperation caller, RemoteOperationResult result);
}

View file

@ -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.oc_framework.operations;
public class OperationCancelledException extends Exception {
/**
* Generated serial version - to avoid Java warning
*/
private static final long serialVersionUID = -6350981497740424983L;
}

View file

@ -1,180 +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.oc_framework.operations;
import java.io.Serializable;
import android.os.Parcel;
import android.os.Parcelable;
import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
import com.owncloud.android.oc_framework.utils.FileUtils;
/**
* Contains the data of a Remote File from a WebDavEntry
*
* @author masensio
*/
public class RemoteFile implements Parcelable, Serializable {
/** Generated - should be refreshed every time the class changes!! */
private static final long serialVersionUID = 532139091191390616L;
private String mRemotePath;
private String mMimeType;
private long mLength;
private long mCreationTimestamp;
private long mModifiedTimestamp;
private String mEtag;
/**
* Getters and Setters
*/
public String getRemotePath() {
return mRemotePath;
}
public void setRemotePath(String remotePath) {
this.mRemotePath = remotePath;
}
public String getMimeType() {
return mMimeType;
}
public void setMimeType(String mimeType) {
this.mMimeType = mimeType;
}
public long getLength() {
return mLength;
}
public void setLength(long length) {
this.mLength = length;
}
public long getCreationTimestamp() {
return mCreationTimestamp;
}
public void setCreationTimestamp(long creationTimestamp) {
this.mCreationTimestamp = creationTimestamp;
}
public long getModifiedTimestamp() {
return mModifiedTimestamp;
}
public void setModifiedTimestamp(long modifiedTimestamp) {
this.mModifiedTimestamp = modifiedTimestamp;
}
public String getEtag() {
return mEtag;
}
public void setEtag(String etag) {
this.mEtag = etag;
}
/**
* Create new {@link RemoteFile} with given path.
*
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
*
* @param path The remote path of the file.
*/
public RemoteFile(String path) {
resetData();
if (path == null || path.length() <= 0 || !path.startsWith(FileUtils.PATH_SEPARATOR)) {
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
}
mRemotePath = path;
}
public RemoteFile(WebdavEntry we) {
this(we.decodedPath());
this.setCreationTimestamp(we.createTimestamp());
this.setLength(we.contentLength());
this.setMimeType(we.contentType());
this.setModifiedTimestamp(we.modifiedTimestamp());
this.setEtag(we.etag());
}
/**
* Used internally. Reset all file properties
*/
private void resetData() {
mRemotePath = null;
mMimeType = null;
mLength = 0;
mCreationTimestamp = 0;
mModifiedTimestamp = 0;
mEtag = null;
}
/**
* Parcelable Methods
*/
public static final Parcelable.Creator<RemoteFile> CREATOR = new Parcelable.Creator<RemoteFile>() {
@Override
public RemoteFile createFromParcel(Parcel source) {
return new RemoteFile(source);
}
@Override
public RemoteFile[] newArray(int size) {
return new RemoteFile[size];
}
};
/**
* Reconstruct from parcel
*
* @param source The source parcel
*/
private RemoteFile(Parcel source) {
mRemotePath = source.readString();
mMimeType = source.readString();
mLength = source.readLong();
mCreationTimestamp = source.readLong();
mModifiedTimestamp = source.readLong();
mEtag = source.readString();
}
@Override
public int describeContents() {
return this.hashCode();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mRemotePath);
dest.writeString(mMimeType);
dest.writeLong(mLength);
dest.writeLong(mCreationTimestamp);
dest.writeLong(mModifiedTimestamp);
dest.writeString(mEtag);
}
}

View file

@ -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.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;
}
}

View file

@ -1,356 +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.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 java.util.ArrayList;
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 org.json.JSONException;
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 = -8257349554488668693L;
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;
private ArrayList<RemoteFile> mFiles;
public RemoteOperationResult(ResultCode code) {
mCode = code;
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
mFiles = null;
}
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 void setData(ArrayList<RemoteFile> files){
mFiles = files;
}
public ArrayList<RemoteFile> getData(){
return mFiles;
}
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 if (mException instanceof JSONException) {
return "JSON exception";
} 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")));
}
}

View file

@ -1,94 +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.oc_framework.operations.remote;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.Random;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
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 android.util.Log;
public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation {
public static final long CHUNK_SIZE = 1024000;
private static final String OC_CHUNKED_HEADER = "OC-Chunked";
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) {
super(storagePath, remotePath, mimeType);
}
@Override
protected int uploadFile(WebdavClient client) throws HttpException, IOException {
int status = -1;
FileChannel channel = null;
RandomAccessFile raf = null;
try {
File file = new File(mStoragePath);
raf = new RandomAccessFile(file, "r");
channel = raf.getChannel();
mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
//((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
synchronized (mDataTransferListeners) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
}
long offset = 0;
String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(mRemotePath) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
if (mPutMethod != null) {
mPutMethod.releaseConnection(); // let the connection available for other methods
}
mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
Log.d(TAG, "Upload of " + mStoragePath + " to " + mRemotePath + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
if (!isSuccess(status))
break;
}
} finally {
if (channel != null)
channel.close();
if (raf != null)
raf.close();
if (mPutMethod != null)
mPutMethod.releaseConnection(); // let the connection available for other methods
}
return status;
}
}

View file

@ -1,111 +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.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);
}
}

View file

@ -1,169 +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.oc_framework.operations.remote;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.http.HttpStatus;
import android.util.Log;
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.RemoteFile;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
/**
* Remote operation performing the download of a remote file in the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class DownloadRemoteFileOperation extends RemoteOperation {
private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName();
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
private long mModificationTimestamp = 0;
private GetMethod mGet;
private RemoteFile mRemoteFile;
private String mTemporalFolder;
public DownloadRemoteFileOperation(RemoteFile remoteFile, String temporalFolder) {
mRemoteFile = remoteFile;
mTemporalFolder = temporalFolder;
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
/// download will be performed to a temporal file, then moved to the final location
File tmpFile = new File(getTmpPath());
/// perform the download
try {
tmpFile.getParentFile().mkdirs();
int status = downloadFile(client, tmpFile);
result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null));
Log.i(TAG, "Download of " + mRemoteFile.getRemotePath() + " to " + getTmpPath() + ": " + result.getLogMessage());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log.e(TAG, "Download of " + mRemoteFile.getRemotePath() + " to " + getTmpPath() + ": " + result.getLogMessage(), e);
}
return result;
}
protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException {
int status = -1;
boolean savedFile = false;
mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemoteFile.getRemotePath()));
Iterator<OnDatatransferProgressListener> it = null;
FileOutputStream fos = null;
try {
status = client.executeMethod(mGet);
if (isSuccess(status)) {
targetFile.createNewFile();
BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
fos = new FileOutputStream(targetFile);
long transferred = 0;
byte[] bytes = new byte[4096];
int readResult = 0;
while ((readResult = bis.read(bytes)) != -1) {
synchronized(mCancellationRequested) {
if (mCancellationRequested.get()) {
mGet.abort();
throw new OperationCancelledException();
}
}
fos.write(bytes, 0, readResult);
transferred += readResult;
synchronized (mDataTransferListeners) {
it = mDataTransferListeners.iterator();
while (it.hasNext()) {
it.next().onTransferProgress(readResult, transferred, mRemoteFile.getLength(), targetFile.getName());
}
}
}
savedFile = true;
Header modificationTime = mGet.getResponseHeader("Last-Modified");
if (modificationTime != null) {
Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue());
mModificationTimestamp = (d != null) ? d.getTime() : 0;
}
} else {
client.exhaustResponse(mGet.getResponseBodyAsStream());
}
} finally {
if (fos != null) fos.close();
if (!savedFile && targetFile.exists()) {
targetFile.delete();
}
mGet.releaseConnection(); // let the connection available for other methods
}
return status;
}
private boolean isSuccess(int status) {
return (status == HttpStatus.SC_OK);
}
private String getTmpPath() {
return mTemporalFolder + mRemoteFile.getRemotePath();
}
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.add(listener);
}
}
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.remove(listener);
}
}
public void cancel() {
mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
}
}

View file

@ -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.oc_framework.operations.remote;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.HeadMethod;
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 android.content.Context;
import android.net.ConnectivityManager;
import android.util.Log;
/**
* Operation to check the existence or absence of a path in a remote server.
*
* @author David A. Velasco
*/
public class ExistenceCheckRemoteOperation extends RemoteOperation {
/** Maximum time to wait for a response from the server in MILLISECONDs. */
public static final int TIMEOUT = 10000;
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
private String mPath;
private Context mContext;
private boolean mSuccessIfAbsent;
/**
* Full constructor. Success of the operation will depend upon the value of successIfAbsent.
*
* @param path Path to append to the URL owned by the client instance.
* @param context Android application context.
* @param successIfAbsent When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404).
*/
public ExistenceCheckRemoteOperation(String path, Context context, boolean successIfAbsent) {
mPath = (path != null) ? path : "";
mContext = context;
mSuccessIfAbsent = successIfAbsent;
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
if (!isOnline()) {
return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
}
RemoteOperationResult result = null;
HeadMethod head = null;
try {
head = new HeadMethod(client.getBaseUri() + WebdavUtils.encodePath(mPath));
int status = client.executeMethod(head, TIMEOUT, TIMEOUT);
client.exhaustResponse(head.getResponseBodyAsStream());
boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
result = new RemoteOperationResult(success, status, head.getResponseHeaders());
Log.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":""));
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException());
} finally {
if (head != null)
head.releaseConnection();
}
return result;
}
private boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm != null && cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
}

View file

@ -1,127 +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.oc_framework.operations.remote;
import java.io.IOException;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.http.HttpStatus;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
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;
/**
* @author masensio
*
* Get the UserName for a SAML connection, from a JSON with the format:
* id
* display-name
* email
*/
public class GetUserNameRemoteOperation extends RemoteOperation {
private static final String TAG = GetUserNameRemoteOperation.class.getSimpleName();
// HEADER
private static final String HEADER_OCS_API = "OCS-APIREQUEST";
private static final String HEADER_OCS_API_VALUE = "true";
// OCS Route
private static final String OCS_ROUTE ="/index.php/ocs/cloud/user?format=json";
// JSON Node names
private static final String NODE_OCS = "ocs";
private static final String NODE_DATA = "data";
private static final String NODE_ID = "id";
private static final String NODE_DISPLAY_NAME= "display-name";
private static final String NODE_EMAIL= "email";
private String mUserName;
public String getUserName() {
return mUserName;
}
public GetUserNameRemoteOperation() {
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
int status = -1;
// Get Method
GetMethod get = new GetMethod(client.getBaseUri() + OCS_ROUTE);
Log.d(TAG, "URL ------> " + client.getBaseUri() + OCS_ROUTE);
// Add the Header
get.addRequestHeader(HEADER_OCS_API, HEADER_OCS_API_VALUE);
//Get the user
try {
status = client.executeMethod(get);
if(isSuccess(status)) {
Log.d(TAG, "Obtain RESPONSE");
String response = get.getResponseBodyAsString();
Log.d(TAG, "GET RESPONSE.................... " + response);
// Parse the response
JSONObject respJSON = new JSONObject(response);
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
String id = respData.getString(NODE_ID);
String displayName = respData.getString(NODE_DISPLAY_NAME);
String email = respData.getString(NODE_EMAIL);
// Result
result = new RemoteOperationResult(isSuccess(status), status, (get != null ? get.getResponseHeaders() : null));
mUserName = displayName;
Log.d(TAG, "Response: " + id + " - " + displayName + " - " + email);
}
} catch (HttpException e) {
result = new RemoteOperationResult(e);
e.printStackTrace();
} catch (IOException e) {
result = new RemoteOperationResult(e);
e.printStackTrace();
} catch (JSONException e) {
result = new RemoteOperationResult(e);
e.printStackTrace();
} finally {
get.releaseConnection();
}
return result;
}
private boolean isSuccess(int status) {
return (status == HttpStatus.SC_OK);
}
}

View file

@ -1,108 +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.oc_framework.operations.remote;
import java.util.ArrayList;
import org.apache.http.HttpStatus;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import android.util.Log;
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.RemoteFile;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
/**
* Remote operation performing the read a file from the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class ReadRemoteFileOperation extends RemoteOperation {
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
private static final int SYNC_READ_TIMEOUT = 10000;
private static final int SYNC_CONNECTION_TIMEOUT = 5000;
private String mRemotePath;
/**
* Constructor
*
* @param remotePath Remote path of the file.
*/
public ReadRemoteFileOperation(String remotePath) {
mRemotePath = remotePath;
}
/**
* Performs the read operation.
*
* @param client Client object to communicate with the remote ownCloud server.
*/
@Override
protected RemoteOperationResult run(WebdavClient client) {
PropFindMethod propfind = null;
RemoteOperationResult result = null;
/// take the duty of check the server for the current state of the file there
try {
propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath),
DavConstants.PROPFIND_ALL_PROP,
DavConstants.DEPTH_0);
int status;
status = client.executeMethod(propfind, SYNC_READ_TIMEOUT, SYNC_CONNECTION_TIMEOUT);
boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS;
if (isMultiStatus) {
// Parse response
MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
WebdavEntry we = new WebdavEntry(resp.getResponses()[0], client.getBaseUri().getPath());
RemoteFile remoteFile = new RemoteFile(we);
ArrayList<RemoteFile> files = new ArrayList<RemoteFile>();
files.add(remoteFile);
// Result of the operation
result = new RemoteOperationResult(true, status, propfind.getResponseHeaders());
result.setData(files);
} else {
client.exhaustResponse(propfind.getResponseBodyAsStream());
result = new RemoteOperationResult(false, status, propfind.getResponseHeaders());
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
e.printStackTrace();
Log.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(), result.getException());
} finally {
if (propfind != null)
propfind.releaseConnection();
}
return result;
}
}

View file

@ -1,162 +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.oc_framework.operations.remote;
import java.util.ArrayList;
import org.apache.http.HttpStatus;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import android.util.Log;
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.RemoteFile;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
/**
* Remote operation performing the read of remote file or folder in the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class ReadRemoteFolderOperation extends RemoteOperation {
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
private String mRemotePath;
private ArrayList<RemoteFile> mFolderAndFiles;
/**
* Constructor
*
* @param remotePath Remote path of the file.
*/
public ReadRemoteFolderOperation(String remotePath) {
mRemotePath = remotePath;
}
/**
* Performs the read operation.
*
* @param client Client object to communicate with the remote ownCloud server.
*/
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
PropFindMethod query = null;
try {
// remote request
query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath),
DavConstants.PROPFIND_ALL_PROP,
DavConstants.DEPTH_1);
int status = client.executeMethod(query);
// check and process response
if (isMultiStatus(status)) {
// get data from remote folder
MultiStatus dataInServer = query.getResponseBodyAsMultiStatus();
readData(dataInServer, client);
// Result of the operation
result = new RemoteOperationResult(true, status, query.getResponseHeaders());
// Add data to the result
if (result.isSuccess()) {
result.setData(mFolderAndFiles);
}
} else {
// synchronization failed
client.exhaustResponse(query.getResponseBodyAsStream());
result = new RemoteOperationResult(false, status, query.getResponseHeaders());
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
} finally {
if (query != null)
query.releaseConnection(); // let the connection available for other methods
if (result.isSuccess()) {
Log.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
} else {
if (result.isException()) {
Log.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(), result.getException());
} else {
Log.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
}
}
}
return result;
}
public boolean isMultiStatus(int status) {
return (status == HttpStatus.SC_MULTI_STATUS);
}
/**
* Read the data retrieved from the server about the contents of the target folder
*
*
* @param dataInServer Full response got from the server with the data of the target
* folder and its direct children.
* @param client Client instance to the remote server where the data were
* retrieved.
* @return
*/
private void readData(MultiStatus dataInServer, WebdavClient client) {
mFolderAndFiles = new ArrayList<RemoteFile>();
// parse data from remote folder
WebdavEntry we = new WebdavEntry(dataInServer.getResponses()[0], client.getBaseUri().getPath());
mFolderAndFiles.add(fillOCFile(we));
// loop to update every child
RemoteFile remoteFile = null;
for (int i = 1; i < dataInServer.getResponses().length; ++i) {
/// new OCFile instance with the data from the server
we = new WebdavEntry(dataInServer.getResponses()[i], client.getBaseUri().getPath());
remoteFile = fillOCFile(we);
mFolderAndFiles.add(remoteFile);
}
}
/**
* Creates and populates a new {@link RemoteFile} object with the data read from the server.
*
* @param we WebDAV entry read from the server for a WebDAV resource (remote file or folder).
* @return New OCFile instance representing the remote resource described by we.
*/
private RemoteFile fillOCFile(WebdavEntry we) {
RemoteFile file = new RemoteFile(we.decodedPath());
file.setCreationTimestamp(we.createTimestamp());
file.setLength(we.contentLength());
file.setMimeType(we.contentType());
file.setModifiedTimestamp(we.modifiedTimestamp());
file.setEtag(we.etag());
return file;
}
}

View file

@ -1,83 +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.oc_framework.operations.remote;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
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;
/**
* Remote operation performing the removal of a remote file or folder in the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class RemoveRemoteFileOperation extends RemoteOperation {
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
private static final int REMOVE_READ_TIMEOUT = 10000;
private static final int REMOVE_CONNECTION_TIMEOUT = 5000;
private String mRemotePath;
/**
* Constructor
*
* @param remotePath RemotePath of the remote file or folder to remove from the server
*/
public RemoveRemoteFileOperation(String remotePath) {
mRemotePath = remotePath;
}
/**
* Performs the rename operation.
*
* @param client Client object to communicate with the remote ownCloud server.
*/
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
DeleteMethod delete = null;
try {
delete = new DeleteMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
delete.getResponseBodyAsString(); // exhaust the response, although not interesting
result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
Log.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
} finally {
if (delete != null)
delete.releaseConnection();
}
return result;
}
}

View file

@ -1,146 +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.oc_framework.operations.remote;
import java.io.File;
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
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 rename of a remote file or folder in the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class RenameRemoteFileOperation extends RemoteOperation {
private static final String TAG = RenameRemoteFileOperation.class.getSimpleName();
private static final int RENAME_READ_TIMEOUT = 10000;
private static final int RENAME_CONNECTION_TIMEOUT = 5000;
private String mOldName;
private String mOldRemotePath;
private String mNewName;
private String mNewRemotePath;
/**
* Constructor
*
* @param oldName Old name of the file.
* @param oldRemotePath Old remote path of the file.
* @param newName New name to set as the name of file.
* @param isFolder 'true' for folder and 'false' for files
*/
public RenameRemoteFileOperation(String oldName, String oldRemotePath, String newName, boolean isFolder) {
mOldName = oldName;
mOldRemotePath = oldRemotePath;
mNewName = newName;
String parent = (new File(mOldRemotePath)).getParent();
parent = (parent.endsWith(FileUtils.PATH_SEPARATOR)) ? parent : parent + FileUtils.PATH_SEPARATOR;
mNewRemotePath = parent + mNewName;
if (isFolder) {
mNewRemotePath += FileUtils.PATH_SEPARATOR;
}
}
/**
* Performs the rename operation.
*
* @param client Client object to communicate with the remote ownCloud server.
*/
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
LocalMoveMethod move = null;
boolean noInvalidChars = FileUtils.isValidPath(mNewRemotePath);
if (noInvalidChars) {
try {
if (mNewName.equals(mOldName)) {
return new RemoteOperationResult(ResultCode.OK);
}
// check if a file with the new name already exists
if (client.existsFile(mNewRemotePath)) {
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
}
move = new LocalMoveMethod( client.getBaseUri() + WebdavUtils.encodePath(mOldRemotePath),
client.getBaseUri() + WebdavUtils.encodePath(mNewRemotePath));
int status = client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
move.getResponseBodyAsString(); // exhaust response, although not interesting
result = new RemoteOperationResult(move.succeeded(), status, move.getResponseHeaders());
Log.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " + result.getLogMessage());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log.e(TAG, "Rename " + mOldRemotePath + " to " + ((mNewRemotePath==null) ? mNewName : mNewRemotePath) + ": " + result.getLogMessage(), e);
} finally {
if (move != null)
move.releaseConnection();
}
} else {
result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
}
return result;
}
/**
* Move operation
*
*/
private class LocalMoveMethod extends DavMethodBase {
public LocalMoveMethod(String uri, String dest) {
super(uri);
addRequestHeader(new org.apache.commons.httpclient.Header("Destination", dest));
}
@Override
public String getName() {
return "MOVE";
}
@Override
protected boolean isSuccess(int status) {
return status == 201 || status == 204;
}
}
}

View file

@ -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.oc_framework.operations.remote;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.http.HttpStatus;
import 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;
/**
* Remote operation performing the upload of a remote file to the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class UploadRemoteFileOperation extends RemoteOperation {
protected String mStoragePath;
protected String mRemotePath;
protected String mMimeType;
protected PutMethod mPutMethod = null;
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
protected RequestEntity mEntity = null;
public UploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) {
mStoragePath = storagePath;
mRemotePath = remotePath;
mMimeType = mimeType;
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
try {
// / perform the upload
synchronized (mCancellationRequested) {
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
} else {
mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
}
}
int status = uploadFile(client);
result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
} catch (Exception e) {
// TODO something cleaner with cancellations
if (mCancellationRequested.get()) {
result = new RemoteOperationResult(new OperationCancelledException());
} else {
result = new RemoteOperationResult(e);
}
}
return result;
}
public boolean isSuccess(int status) {
return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
}
protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
int status = -1;
try {
File f = new File(mStoragePath);
mEntity = new FileRequestEntity(f, mMimeType);
synchronized (mDataTransferListeners) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
}
mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
} finally {
mPutMethod.releaseConnection(); // let the connection available for other methods
}
return status;
}
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
return mDataTransferListeners;
}
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.add(listener);
}
if (mEntity != null) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
}
}
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.remove(listener);
}
if (mEntity != null) {
((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
}
}
public void cancel() {
synchronized (mCancellationRequested) {
mCancellationRequested.set(true);
if (mPutMethod != null)
mPutMethod.abort();
}
}
}

View file

@ -1,71 +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.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;
}
}

View file

@ -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.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;
}
}
}

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.owncloud.android.workaround.accounts" package="com.owncloud.android.workaround.accounts"
android:versionCode="0100011" android:versionCode="0100013"
android:versionName="1.0.11" > android:versionName="1.0.13" >
<uses-sdk <uses-sdk
android:minSdkVersion="16" android:minSdkVersion="16"

@ -0,0 +1 @@
Subproject commit 30acd4875dda3fd0bec83daaad522f3d5a02ead6

View file

@ -13,7 +13,7 @@
<owncloud.version>1.5.1-SNAPSHOT</owncloud.version> <owncloud.version>1.5.1-SNAPSHOT</owncloud.version>
<java-version>1.6</java-version> <java-version>1.6</java-version>
<!-- Given by maven-android-sdk-deployer --> <!-- Given by maven-android-sdk-deployer -->
<google.android-version>4.4_r1</google.android-version> <google.android-version>4.4.2_r2</google.android-version>
<!-- Usually the latest Android API --> <!-- Usually the latest Android API -->
<google.android-api>19</google.android-api> <google.android-api>19</google.android-api>
<actionbarsherlock-version>4.2.0</actionbarsherlock-version> <actionbarsherlock-version>4.2.0</actionbarsherlock-version>
@ -50,10 +50,10 @@
<type>apklib</type> <type>apklib</type>
</dependency> </dependency>
<!-- MUST BE INSTALLED FIRST: cd oc_framework; mvn install --> <!-- MUST BE INSTALLED FIRST: cd owncloud-android-library; mvn install -->
<dependency> <dependency>
<groupId>com.owncloud.android</groupId> <groupId>com.owncloud.android</groupId>
<artifactId>oc_framework</artifactId> <artifactId>owncloud-android-library</artifactId>
<version>${owncloud.version}</version> <version>${owncloud.version}</version>
</dependency> </dependency>

View file

@ -10,4 +10,4 @@
# Project target. # Project target.
target=android-19 target=android-19
android.library.reference.1=actionbarsherlock/library android.library.reference.1=actionbarsherlock/library
android.library.reference.2=oc_framework android.library.reference.2=owncloud-android-library

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
res/drawable-xhdpi/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Some files were not shown because too many files have changed in this diff Show more