mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-28 10:16:35 +00:00
add dav4droid support part1
This commit is contained in:
parent
9ab1b40682
commit
cd3d20db07
3
.gitignore
vendored
3
.gitignore
vendored
@ -31,3 +31,6 @@ proguard-project.txt
|
|||||||
sample_client/proguard-project.txt
|
sample_client/proguard-project.txt
|
||||||
tests/proguard-project.txt
|
tests/proguard-project.txt
|
||||||
tests/test_cases/proguard-project.txt
|
tests/test_cases/proguard-project.txt
|
||||||
|
|
||||||
|
# setup.xml login credentials
|
||||||
|
sample_client/res/values/setup.xml
|
||||||
|
@ -14,12 +14,14 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'org.apache.jackrabbit:jackrabbit-webdav:2.12.4'
|
api 'org.apache.jackrabbit:jackrabbit-webdav:2.12.4'
|
||||||
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
|
api 'com.gitlab.derSchabi:dav4android:dev2'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -52,4 +54,8 @@ android {
|
|||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,27 +24,22 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.owncloud.android.lib.sampleclient"
|
package="com.owncloud.android.lib.sampleclient"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="14"
|
||||||
android:targetSdkVersion="26"/>
|
android:targetSdkVersion="26"/>
|
||||||
<application
|
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
|
||||||
android:icon="@drawable/ic_launcher"
|
<activity android:name="MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@android:style/Theme.Light.NoTitleBar">
|
android:screenOrientation="portrait"
|
||||||
<activity
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:name="MainActivity"
|
>
|
||||||
android:configChanges="orientation|keyboardHidden"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:screenOrientation="portrait"
|
|
||||||
>
|
|
||||||
<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>
|
||||||
</application>
|
</application>
|
||||||
|
@ -42,4 +42,8 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,150 +24,99 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
>
|
>
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/server_address"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_toLeftOf="@+id/button_check_server"
|
|
||||||
android:layout_toStartOf="@+id/button_check_server"
|
|
||||||
android:ems="10"
|
|
||||||
android:hint="Server address (with http or https)"
|
|
||||||
android:inputType="textPersonName"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_check_server"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignBaseline="@+id/server_address"
|
|
||||||
android:layout_alignBottom="@+id/server_address"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:onClick="onClickHandler"
|
|
||||||
android:text="@string/check_server"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_refresh"
|
android:id="@+id/button_refresh"
|
||||||
|
style="@style/ButtonStyle"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:text="@string/refresh"
|
||||||
|
android:onClick="onClickHandler"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/list_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_below="@+id/button_refresh"
|
||||||
|
android:layout_above="@+id/button_upload"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_below="@id/server_address"
|
>
|
||||||
android:layout_marginTop="10dp"
|
</ListView>
|
||||||
android:onClick="onClickHandler"
|
|
||||||
android:text="@string/refresh"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_upload"
|
android:id="@+id/button_upload"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_below="@id/button_refresh"
|
android:layout_above="@+id/frame"
|
||||||
android:layout_marginTop="10dp"
|
android:text="@string/upload"
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/upload"/>
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/upload_progress"
|
||||||
|
style="@style/ProgressStyle"
|
||||||
|
android:layout_below="@id/list_view"
|
||||||
|
android:layout_above="@id/frame"
|
||||||
|
android:layout_toRightOf="@id/button_upload"
|
||||||
|
android:layout_toLeftOf="@+id/button_delete_remote"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="0%"
|
||||||
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_download"
|
android:id="@id/button_delete_remote"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_above="@id/frame"
|
||||||
android:layout_below="@id/button_upload"
|
android:text="@string/delete_remote_file"
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/download"/>
|
/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@id/frame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/frame_height"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_above="@+id/button_download"
|
||||||
|
>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_delete_remote"
|
android:id="@id/button_download"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_below="@id/button_download"
|
android:text="@string/download"
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/delete_remote_file"/>
|
/>
|
||||||
|
|
||||||
<!--<ListView-->
|
<TextView
|
||||||
<!--android:id="@+id/list_view"-->
|
android:id="@+id/download_progress"
|
||||||
<!--android:layout_width="match_parent"-->
|
style="@style/ProgressStyle"
|
||||||
<!--android:layout_height="wrap_content"-->
|
android:layout_below="@id/frame"
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
android:layout_alignParentBottom="true"
|
||||||
<!--android:layout_alignParentRight="true"-->
|
android:layout_toRightOf="@id/button_download"
|
||||||
<!--android:layout_below="@+id/button_refresh"-->
|
android:layout_toLeftOf="@+id/button_delete_local"
|
||||||
<!--android:visibility="invisible">-->
|
android:gravity="center"
|
||||||
<!--</ListView>-->
|
android:textSize="14sp"
|
||||||
|
android:text="0%"
|
||||||
|
/>
|
||||||
|
|
||||||
<!--<TextView-->
|
<Button
|
||||||
<!--android:id="@+id/upload_progress"-->
|
android:id="@id/button_delete_local"
|
||||||
<!--style="@style/ProgressStyle"-->
|
style="@style/ButtonStyle"
|
||||||
<!--android:layout_above="@id/frame"-->
|
android:layout_alignParentBottom="true"
|
||||||
<!--android:layout_below="@id/list_view"-->
|
android:layout_alignParentRight="true"
|
||||||
<!--android:layout_toLeftOf="@+id/button_delete_remote"-->
|
android:text="@string/delete_local_file"
|
||||||
<!--android:layout_toRightOf="@id/button_upload"-->
|
android:onClick="onClickHandler"
|
||||||
<!--android:enabled="false"-->
|
/>
|
||||||
<!--android:gravity="center"-->
|
|
||||||
<!--android:text="0%"-->
|
|
||||||
<!--android:textSize="14sp"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_delete_remote"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_above="@id/frame"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/delete_remote_file"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<FrameLayout-->
|
|
||||||
<!--android:id="@id/frame"-->
|
|
||||||
<!--android:layout_width="match_parent"-->
|
|
||||||
<!--android:layout_height="@dimen/frame_height"-->
|
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:layout_above="@+id/button_download"-->
|
|
||||||
<!-->-->
|
|
||||||
<!--</FrameLayout>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_download"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/download"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<TextView-->
|
|
||||||
<!--android:id="@+id/download_progress"-->
|
|
||||||
<!--style="@style/ProgressStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_below="@id/frame"-->
|
|
||||||
<!--android:layout_toLeftOf="@+id/button_delete_local"-->
|
|
||||||
<!--android:layout_toRightOf="@id/button_download"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:gravity="center"-->
|
|
||||||
<!--android:text="0%"-->
|
|
||||||
<!--android:textSize="14sp"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_delete_local"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/delete_local_file"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">ownCloud Sample Client</string>
|
<string name="app_name">ownCloud Sample Client</string>
|
||||||
<string name="refresh">Refresh</string>
|
<string name="refresh">Refresh</string>
|
||||||
<string name="check_server">Check server</string>
|
|
||||||
<string name="upload">Upload</string>
|
<string name="upload">Upload</string>
|
||||||
<string name="delete_remote_file">Delete remote file</string>
|
<string name="delete_remote_file">Delete remote file</string>
|
||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
*
|
|
||||||
* @author David González Verdugo
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,35 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.sampleclient;
|
package com.owncloud.android.lib.sampleclient;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.res.AssetManager;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
|
||||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
|
||||||
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
|
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
||||||
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
|
||||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
|
||||||
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
|
||||||
import com.owncloud.android.lib.resources.files.RemoteFile;
|
|
||||||
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
|
||||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -63,31 +32,36 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import okhttp3.Call;
|
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||||
import okhttp3.Callback;
|
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
||||||
import okhttp3.Credentials;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import okhttp3.Headers;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
import okhttp3.MediaType;
|
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
|
||||||
import okhttp3.OkHttpClient;
|
import com.owncloud.android.lib.resources.files.RemoteFile;
|
||||||
import okhttp3.Request;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import okhttp3.RequestBody;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import okhttp3.Response;
|
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
||||||
|
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
||||||
|
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
||||||
|
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||||
|
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener {
|
public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener {
|
||||||
|
|
||||||
private static String LOG_TAG = MainActivity.class.getCanonicalName();
|
private static String LOG_TAG = MainActivity.class.getCanonicalName();
|
||||||
|
|
||||||
private static final String NODE_VERSION = "version";
|
|
||||||
private static final String WEBDAV_PATH_4_0 = "/remote.php/webdav/";
|
|
||||||
private static final String NEW_WEBDAV_PATH = "/remote.php/dav/files/";
|
|
||||||
private static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
|
||||||
private static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
|
||||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
|
||||||
private static final String USER_AGENT_HEADER = "User-Agent";
|
|
||||||
private static final String CONTENT_TYPE_HEADER = "Content-Type";
|
|
||||||
private static final String USER_AGENT_VALUE = "Mozilla/5.0 (Android) ownCloud-android/2.7.0";
|
|
||||||
private static final String CONTENT_TYPE_VALUE = "multipart/form-data";
|
|
||||||
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
|
||||||
private OwnCloudClient mClient;
|
private OwnCloudClient mClient;
|
||||||
@ -96,10 +70,6 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
private View mFrame;
|
private View mFrame;
|
||||||
|
|
||||||
private OkHttpClient mOkHttpClient;
|
|
||||||
|
|
||||||
private String mCredentials;
|
|
||||||
|
|
||||||
/** Called when the activity is first created. */
|
/** Called when the activity is first created. */
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -118,7 +88,7 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
);
|
);
|
||||||
|
|
||||||
mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list);
|
mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list);
|
||||||
// ((ListView)findViewById(R.id.list_view)).setAdapter(mFilesAdapter);
|
((ListView)findViewById(R.id.list_view)).setAdapter(mFilesAdapter);
|
||||||
|
|
||||||
// TODO move to background thread or task
|
// TODO move to background thread or task
|
||||||
AssetManager assets = getAssets();
|
AssetManager assets = getAssets();
|
||||||
@ -141,13 +111,7 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
Log.e(LOG_TAG, getString(R.string.error_copying_sample_file), e);
|
Log.e(LOG_TAG, getString(R.string.error_copying_sample_file), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
((TextView) findViewById(R.id.server_address)).setText(getString(R.string.server_base_url));
|
mFrame = findViewById(R.id.frame);
|
||||||
|
|
||||||
mOkHttpClient = new OkHttpClient();
|
|
||||||
|
|
||||||
mCredentials = Credentials.basic(getString(R.string.username), getString(R.string.password));
|
|
||||||
|
|
||||||
// mFrame = findViewById(R.id.frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -163,264 +127,63 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
public void onClickHandler(View button) {
|
public void onClickHandler(View button) {
|
||||||
switch (button.getId()) {
|
switch (button.getId()) {
|
||||||
case R.id.button_check_server:
|
|
||||||
startCheck();
|
|
||||||
break;
|
|
||||||
case R.id.button_refresh:
|
case R.id.button_refresh:
|
||||||
startRefresh();
|
startRefresh();
|
||||||
break;
|
break;
|
||||||
case R.id.button_upload:
|
case R.id.button_upload:
|
||||||
startUpload();
|
startUpload();
|
||||||
break;
|
break;
|
||||||
case R.id.button_download:
|
|
||||||
startDownload();
|
|
||||||
break;
|
|
||||||
case R.id.button_delete_remote:
|
case R.id.button_delete_remote:
|
||||||
startRemoteDeletion();
|
startRemoteDeletion();
|
||||||
break;
|
break;
|
||||||
// case R.id.button_delete_local:
|
case R.id.button_download:
|
||||||
// startLocalDeletion();
|
startDownload();
|
||||||
// break;
|
break;
|
||||||
|
case R.id.button_delete_local:
|
||||||
|
startLocalDeletion();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startCheck() {
|
private void startRefresh() {
|
||||||
|
ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR);
|
||||||
if (!validServerAddress()) return;
|
refreshOperation.execute(mClient, this, mHandler);
|
||||||
|
}
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + "/status.php")
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
}
|
|
||||||
|
|
||||||
try { // Successful response
|
|
||||||
|
|
||||||
String jsonData = response.body().string();
|
|
||||||
|
|
||||||
JSONObject Jobject = new JSONObject(jsonData);
|
|
||||||
|
|
||||||
final String serverVersion = Jobject.get("version").toString();
|
|
||||||
|
|
||||||
showMessage("Server with version " + serverVersion + " detected");
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
Headers responseHeaders = response.headers();
|
|
||||||
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
|
||||||
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, final IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRefresh() {
|
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
|
||||||
|
|
||||||
// ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR);
|
|
||||||
// refreshOperation.execute(mClient, this, mHandler);
|
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username))
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.method("PROPFIND", null)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
final String propFindResult = response.body().string();
|
|
||||||
|
|
||||||
showMessage(propFindResult);
|
|
||||||
|
|
||||||
Headers responseHeaders = response.headers();
|
|
||||||
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
|
||||||
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startUpload() {
|
private void startUpload() {
|
||||||
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
String mimeType = getString(R.string.sample_file_mimetype);
|
String mimeType = getString(R.string.sample_file_mimetype);
|
||||||
|
|
||||||
MediaType mediaType = MediaType.parse(mimeType);
|
|
||||||
|
|
||||||
// Get the last modification date of the file from the file system
|
// Get the last modification date of the file from the file system
|
||||||
Long timeStampLong = fileToUpload.lastModified()/1000;
|
Long timeStampLong = fileToUpload.lastModified()/1000;
|
||||||
String timeStamp = timeStampLong.toString();
|
String timeStamp = timeStampLong.toString();
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType, timeStamp);
|
||||||
|
uploadOperation.addDatatransferProgressListener(this);
|
||||||
// UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType, timeStamp);
|
uploadOperation.execute(mClient, this, mHandler);
|
||||||
// uploadOperation.addDatatransferProgressListener(this);
|
|
||||||
// uploadOperation.execute(mClient, this, mHandler);
|
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
RequestBody requestBody = RequestBody.create(mediaType, fileToUpload);
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username) + remotePath)
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.addHeader(CONTENT_TYPE_HEADER, CONTENT_TYPE_VALUE)
|
|
||||||
.addHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length()))
|
|
||||||
.addHeader(OC_X_OC_MTIME_HEADER, timeStamp)
|
|
||||||
.put(requestBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful upload of " + fileToUpload.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startDownload() {
|
private void startRemoteDeletion() {
|
||||||
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
|
||||||
downFolder.mkdir();
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
|
||||||
|
|
||||||
// DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, downFolder.getAbsolutePath());
|
|
||||||
// downloadOperation.addDatatransferProgressListener(this);
|
|
||||||
// downloadOperation.execute(mClient, this, mHandler);
|
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username) + remotePath)
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful download of " + fileToUpload.getName() + " although local file " +
|
|
||||||
"won't be created in this stage");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRemoteDeletion() {
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
|
RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
|
||||||
|
removeOperation.execute(mClient, this, mHandler);
|
||||||
|
}
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
private void startDownload() {
|
||||||
// RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
|
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
||||||
// removeOperation.execute(mClient, this, mHandler);
|
downFolder.mkdir();
|
||||||
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
if (!validServerAddress()) return;
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
final Request request = new Request.Builder()
|
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, downFolder.getAbsolutePath());
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username) + remotePath)
|
downloadOperation.addDatatransferProgressListener(this);
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
downloadOperation.execute(mClient, this, mHandler);
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.delete()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful deletion of " + fileToUpload.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@ -430,8 +193,8 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
if (!downloadedFile.delete() && downloadedFile.exists()) {
|
if (!downloadedFile.delete() && downloadedFile.exists()) {
|
||||||
Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
// ((TextView) findViewById(R.id.download_progress)).setText("0%");
|
((TextView) findViewById(R.id.download_progress)).setText("0%");
|
||||||
// findViewById(R.id.frame).setBackgroundDrawable(null);
|
findViewById(R.id.frame).setBackgroundDrawable(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,10 +243,10 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) {
|
private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) {
|
||||||
startRefresh();
|
startRefresh();
|
||||||
// TextView progressView = (TextView) findViewById(R.id.upload_progress);
|
TextView progressView = (TextView) findViewById(R.id.upload_progress);
|
||||||
// if (progressView != null) {
|
if (progressView != null) {
|
||||||
// progressView.setText("0%");
|
progressView.setText("0%");
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@ -503,11 +266,11 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
TextView progressView = null;
|
TextView progressView = null;
|
||||||
// if (upload) {
|
if (upload) {
|
||||||
// progressView = (TextView) findViewById(R.id.upload_progress);
|
progressView = (TextView) findViewById(R.id.upload_progress);
|
||||||
// } else {
|
} else {
|
||||||
// progressView = (TextView) findViewById(R.id.download_progress);
|
progressView = (TextView) findViewById(R.id.download_progress);
|
||||||
// }
|
}
|
||||||
if (progressView != null) {
|
if (progressView != null) {
|
||||||
progressView.setText(Long.toString(percentage) + "%");
|
progressView.setText(Long.toString(percentage) + "%");
|
||||||
}
|
}
|
||||||
@ -515,32 +278,4 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validServerAddress() {
|
|
||||||
|
|
||||||
String serverAddress = ((TextView) findViewById(R.id.server_address)).getText().toString();
|
|
||||||
|
|
||||||
if (serverAddress.equals("") || (!serverAddress.contains("http://") && !serverAddress.contains("https://"))) {
|
|
||||||
showToastMessage("Introduce a proper server address with http/https");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMessage(final String message) {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
showToastMessage(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showToastMessage(String message) {
|
|
||||||
Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
|
|
||||||
|
|
||||||
toast.setGravity(Gravity.CENTER, 0, 0);
|
|
||||||
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation which execution involves one or several interactions with an ownCloud server.
|
* Operation which execution involves one or several interactions with an ownCloud server.
|
||||||
@ -77,6 +79,11 @@ public abstract class RemoteOperation implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private OwnCloudClient mClient = null;
|
private OwnCloudClient mClient = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object to interact with the remote server
|
||||||
|
*/
|
||||||
|
private OkHttpClient mHttpClient = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback object to notify about the execution of the remote operation
|
* Callback object to notify about the execution of the remote operation
|
||||||
*/
|
*/
|
||||||
@ -142,6 +149,25 @@ public abstract class RemoteOperation implements Runnable {
|
|||||||
return runOperation();
|
return runOperation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 RemoteOperationResult execute(OkHttpClient client, Context context) {
|
||||||
|
if (client == null)
|
||||||
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||||
|
"OwnCloudClient");
|
||||||
|
mHttpClient = client;
|
||||||
|
mContext = context;
|
||||||
|
|
||||||
|
return runOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously executes the remote operation
|
* Asynchronously executes the remote operation
|
||||||
|
212
src/com/owncloud/android/lib/refactor/Log_OC.java
Normal file
212
src/com/owncloud/android/lib/refactor/Log_OC.java
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
package com.owncloud.android.lib.refactor;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
|
||||||
|
public class Log_OC {
|
||||||
|
private static final String SIMPLE_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
|
||||||
|
private static final String LOG_FOLDER_NAME = "log";
|
||||||
|
private static final long MAX_FILE_SIZE = 1000000; // 1MB
|
||||||
|
|
||||||
|
private static String mOwncloudDataFolderLog = "owncloud_log";
|
||||||
|
|
||||||
|
private static File mLogFile;
|
||||||
|
private static File mFolder;
|
||||||
|
private static BufferedWriter mBuf;
|
||||||
|
|
||||||
|
private static String[] mLogFileNames = {"currentLog.txt", "olderLog.txt"};
|
||||||
|
|
||||||
|
private static boolean isMaxFileSizeReached = false;
|
||||||
|
private static boolean isEnabled = false;
|
||||||
|
|
||||||
|
public static void setLogDataFolder(String logFolder){
|
||||||
|
mOwncloudDataFolderLog = logFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void i(String TAG, String message){
|
||||||
|
Log.i(TAG, message);
|
||||||
|
appendLog(TAG+" : "+ message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void d(String TAG, String message){
|
||||||
|
Log.d(TAG, message);
|
||||||
|
appendLog(TAG + " : " + message);
|
||||||
|
}
|
||||||
|
public static void d(String TAG, String message, Exception e) {
|
||||||
|
Log.d(TAG, message, e);
|
||||||
|
appendLog(TAG + " : " + message + " Exception : "+ e.getStackTrace());
|
||||||
|
}
|
||||||
|
public static void e(String TAG, String message){
|
||||||
|
Log.e(TAG, message);
|
||||||
|
appendLog(TAG + " : " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void e(String TAG, String message, Throwable e) {
|
||||||
|
Log.e(TAG, message, e);
|
||||||
|
appendLog(TAG+" : " + message +" Exception : " + e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void v(String TAG, String message){
|
||||||
|
Log.v(TAG, message);
|
||||||
|
appendLog(TAG+" : "+ message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void w(String TAG, String message) {
|
||||||
|
Log.w(TAG, message);
|
||||||
|
appendLog(TAG+" : "+ message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void wtf(String TAG, String message) {
|
||||||
|
Log.wtf(TAG, message);
|
||||||
|
appendLog(TAG+" : "+ message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start doing logging
|
||||||
|
* @param storagePath : directory for keeping logs
|
||||||
|
*/
|
||||||
|
synchronized public static void startLogging(String storagePath) {
|
||||||
|
String logPath = storagePath + File.separator +
|
||||||
|
mOwncloudDataFolderLog + File.separator + LOG_FOLDER_NAME;
|
||||||
|
mFolder = new File(logPath);
|
||||||
|
mLogFile = new File(mFolder + File.separator + mLogFileNames[0]);
|
||||||
|
|
||||||
|
boolean isFileCreated = false;
|
||||||
|
|
||||||
|
if (!mFolder.exists()) {
|
||||||
|
mFolder.mkdirs();
|
||||||
|
isFileCreated = true;
|
||||||
|
Log.d("LOG_OC", "Log file created");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Create the current log file if does not exist
|
||||||
|
mLogFile.createNewFile();
|
||||||
|
mBuf = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||||
|
isEnabled = true;
|
||||||
|
|
||||||
|
if (isFileCreated) {
|
||||||
|
appendPhoneInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if(mBuf != null) {
|
||||||
|
try {
|
||||||
|
mBuf.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized public static void stopLogging() {
|
||||||
|
try {
|
||||||
|
if (mBuf != null)
|
||||||
|
mBuf.close();
|
||||||
|
isEnabled = false;
|
||||||
|
|
||||||
|
mLogFile = null;
|
||||||
|
mFolder = null;
|
||||||
|
mBuf = null;
|
||||||
|
isMaxFileSizeReached = false;
|
||||||
|
isEnabled = false;
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Because we are stopping logging, we only log to Android console.
|
||||||
|
Log.e("OC_Log", "Closing log file failed: ", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// This catch should never fire because we do null check on mBuf.
|
||||||
|
// But just for the sake of stability let's log this odd situation.
|
||||||
|
// Because we are stopping logging, we only log to Android console.
|
||||||
|
Log.e("OC_Log", "Stopping logging failed: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete history logging
|
||||||
|
*/
|
||||||
|
public static void deleteHistoryLogging() {
|
||||||
|
File folderLogs = new File(mFolder + File.separator);
|
||||||
|
if(folderLogs.isDirectory()){
|
||||||
|
String[] myFiles = folderLogs.list();
|
||||||
|
for (int i=0; i<myFiles.length; i++) {
|
||||||
|
File myFile = new File(folderLogs, myFiles[i]);
|
||||||
|
myFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the info of the device
|
||||||
|
*/
|
||||||
|
private static void appendPhoneInfo() {
|
||||||
|
appendLog("Model : " + android.os.Build.MODEL);
|
||||||
|
appendLog("Brand : " + android.os.Build.BRAND);
|
||||||
|
appendLog("Product : " + android.os.Build.PRODUCT);
|
||||||
|
appendLog("Device : " + android.os.Build.DEVICE);
|
||||||
|
appendLog("Version-Codename : " + android.os.Build.VERSION.CODENAME);
|
||||||
|
appendLog("Version-Release : " + android.os.Build.VERSION.RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append to the log file the info passed
|
||||||
|
* @param text : text for adding to the log file
|
||||||
|
*/
|
||||||
|
synchronized private static void appendLog(String text) {
|
||||||
|
|
||||||
|
if (isEnabled) {
|
||||||
|
|
||||||
|
if (isMaxFileSizeReached) {
|
||||||
|
|
||||||
|
// Move current log file info to another file (old logs)
|
||||||
|
File olderFile = new File(mFolder + File.separator + mLogFileNames[1]);
|
||||||
|
if (mLogFile.exists()) {
|
||||||
|
mLogFile.renameTo(olderFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a new file for current log info
|
||||||
|
mLogFile = new File(mFolder + File.separator + mLogFileNames[0]);
|
||||||
|
isMaxFileSizeReached = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String timeStamp = new SimpleDateFormat(SIMPLE_DATE_FORMAT).format(Calendar.getInstance().getTime());
|
||||||
|
|
||||||
|
try {
|
||||||
|
mBuf = new BufferedWriter(new FileWriter(mLogFile, true));
|
||||||
|
mBuf.newLine();
|
||||||
|
mBuf.write(timeStamp);
|
||||||
|
mBuf.newLine();
|
||||||
|
mBuf.write(text);
|
||||||
|
mBuf.newLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
mBuf.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if current log file size is bigger than the max file size defined
|
||||||
|
if (mLogFile.length() > MAX_FILE_SIZE) {
|
||||||
|
isMaxFileSizeReached = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getLogFileNames() {
|
||||||
|
return mLogFileNames;
|
||||||
|
}
|
||||||
|
}
|
50
src/com/owncloud/android/lib/refactor/OwnCloudContext.java
Normal file
50
src/com/owncloud/android/lib/refactor/OwnCloudContext.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package com.owncloud.android.lib.refactor;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
|
||||||
|
|
||||||
|
public class OwnCloudContext {
|
||||||
|
private static final String TAG = OwnCloudContext.class.toString();
|
||||||
|
|
||||||
|
public static final String WEBDAV_PATH_4_0 = "/remote.php/dav";
|
||||||
|
public static final String STATUS_PATH = "/status.php";
|
||||||
|
public static final String FILES_WEB_PATH = "/index.php/apps/files";
|
||||||
|
|
||||||
|
private static final int MAX_REDIRECTIONS_COUNT = 3;
|
||||||
|
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
||||||
|
private static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
|
||||||
|
private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true;
|
||||||
|
private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
||||||
|
|
||||||
|
private OwnCloudCredentials mCredentials = null;
|
||||||
|
private Uri mBaseUri;
|
||||||
|
|
||||||
|
public class Builder {
|
||||||
|
OwnCloudContext ocContext = new OwnCloudContext();
|
||||||
|
|
||||||
|
public Builder setCredentials(OwnCloudCredentials credentials) {
|
||||||
|
ocContext.mCredentials = credentials;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setBaseUri(Uri baseUri) {
|
||||||
|
ocContext.mBaseUri = baseUri;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OwnCloudContext build() {
|
||||||
|
return ocContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public OwnCloudCredentials getCredentials() {
|
||||||
|
return mCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri getBaseUri() {
|
||||||
|
return mBaseUri;
|
||||||
|
}
|
||||||
|
}
|
50
src/com/owncloud/android/lib/refactor/RemoteOperation.java
Normal file
50
src/com/owncloud/android/lib/refactor/RemoteOperation.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package com.owncloud.android.lib.refactor;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
public abstract class RemoteOperation {
|
||||||
|
private final OwnCloudContext mContext;
|
||||||
|
private static OkHttpClient httpClient = null;
|
||||||
|
|
||||||
|
protected RemoteOperation(OwnCloudContext context) {
|
||||||
|
mContext = context;
|
||||||
|
|
||||||
|
if(httpClient == null) {
|
||||||
|
httpClient = new OkHttpClient.Builder()
|
||||||
|
.followRedirects(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract RemoteOperationResult exec();
|
||||||
|
|
||||||
|
public OwnCloudContext getOCContext() {
|
||||||
|
return mContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OkHttpClient getClient() {
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request.Builder getRequestBuilder() {
|
||||||
|
Request.Builder builder = new Request.Builder();
|
||||||
|
|
||||||
|
for(Map.Entry<String, String> header
|
||||||
|
: mContext.getCredentials().getCredentialHeaders().entrySet()) {
|
||||||
|
builder.addHeader(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Remove this part once SAML is obsolet
|
||||||
|
final String credentialCookie = mContext.getCredentials().getCredentialCookie();
|
||||||
|
if(credentialCookie == null) {
|
||||||
|
builder.addHeader("Cookie", credentialCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
523
src/com/owncloud/android/lib/refactor/RemoteOperationResult.java
Normal file
523
src/com/owncloud/android/lib/refactor/RemoteOperationResult.java
Normal file
@ -0,0 +1,523 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountsException;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.utils.AccountUtils;
|
||||||
|
import com.owncloud.android.lib.refactor.exceptions.CertificateCombinedException;
|
||||||
|
import com.owncloud.android.lib.refactor.exceptions.OperationCancelledException;
|
||||||
|
import com.owncloud.android.lib.refactor.utils.ErrorMessageParser;
|
||||||
|
import com.owncloud.android.lib.refactor.utils.InvalidCharacterExceptionParser;
|
||||||
|
|
||||||
|
import org.apache.commons.httpclient.HttpStatus;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
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 java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.exception.DavException;
|
||||||
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of a remote operation required to an ownCloud server.
|
||||||
|
* <p/>
|
||||||
|
* 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 = 4968939884332372230L;
|
||||||
|
|
||||||
|
private static final String TAG = RemoteOperationResult.class.getSimpleName();
|
||||||
|
|
||||||
|
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,
|
||||||
|
SHARE_NOT_FOUND,
|
||||||
|
LOCAL_STORAGE_NOT_REMOVED,
|
||||||
|
FORBIDDEN,
|
||||||
|
SHARE_FORBIDDEN,
|
||||||
|
SPECIFIC_FORBIDDEN,
|
||||||
|
OK_REDIRECT_TO_NON_SECURE_CONNECTION,
|
||||||
|
INVALID_MOVE_INTO_DESCENDANT,
|
||||||
|
INVALID_COPY_INTO_DESCENDANT,
|
||||||
|
PARTIAL_MOVE_DONE,
|
||||||
|
PARTIAL_COPY_DONE,
|
||||||
|
SHARE_WRONG_PARAMETER,
|
||||||
|
WRONG_SERVER_RESPONSE,
|
||||||
|
INVALID_CHARACTER_DETECT_IN_SERVER,
|
||||||
|
DELAYED_FOR_WIFI,
|
||||||
|
LOCAL_FILE_NOT_FOUND,
|
||||||
|
SERVICE_UNAVAILABLE,
|
||||||
|
SPECIFIC_SERVICE_UNAVAILABLE,
|
||||||
|
SPECIFIC_UNSUPPORTED_MEDIA_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean mSuccess = false;
|
||||||
|
private int mHttpCode = -1;
|
||||||
|
private String mHttpPhrase = null;
|
||||||
|
private Exception mException = null;
|
||||||
|
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
|
||||||
|
private String mRedirectedLocation;
|
||||||
|
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
||||||
|
private String mLastPermanentLocation = null;
|
||||||
|
|
||||||
|
private ArrayList<Object> mData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor from result code.
|
||||||
|
*
|
||||||
|
* To be used when the caller takes the responsibility of interpreting the result of a {@link RemoteOperation}
|
||||||
|
*
|
||||||
|
* @param code {@link ResultCode} decided by the caller.
|
||||||
|
*/
|
||||||
|
public RemoteOperationResult(ResultCode code) {
|
||||||
|
mCode = code;
|
||||||
|
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL ||
|
||||||
|
code == ResultCode.OK_NO_SSL ||
|
||||||
|
code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
||||||
|
mData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor from exception.
|
||||||
|
*
|
||||||
|
* To be used when an exception prevented the end of the {@link RemoteOperation}.
|
||||||
|
*
|
||||||
|
* Determines a {@link ResultCode} depending on the type of the exception.
|
||||||
|
*
|
||||||
|
* @param e Exception that interrupted the {@link RemoteOperation}
|
||||||
|
*/
|
||||||
|
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 SocketTimeoutException) {
|
||||||
|
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 AccountUtils.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 if (e instanceof FileNotFoundException) {
|
||||||
|
mCode = ResultCode.LOCAL_FILE_NOT_FOUND;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mCode = ResultCode.UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor from separate elements of an HTTP or DAV response.
|
||||||
|
*
|
||||||
|
* To be used when the result needs to be interpreted from the response of an HTTP/DAV method.
|
||||||
|
*
|
||||||
|
* Determines a {@link ResultCode} from the already executed method received as a parameter. Generally,
|
||||||
|
* will depend on the HTTP code and HTTP response headers received. In some cases will inspect also the
|
||||||
|
* response body
|
||||||
|
*
|
||||||
|
* @param success
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public RemoteOperationResult(boolean success, Request request, Response response) throws IOException {
|
||||||
|
this(success, response.code(), HttpStatus.getStatusText(response.code()), response.headers());
|
||||||
|
|
||||||
|
if (mHttpCode == HttpStatus.SC_BAD_REQUEST) { // 400
|
||||||
|
|
||||||
|
String bodyResponse = response.body().string();
|
||||||
|
// do not get for other HTTP codes!; could not be available
|
||||||
|
|
||||||
|
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||||
|
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||||
|
InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
|
||||||
|
try {
|
||||||
|
if (xmlParser.parseXMLResponse(is)) {
|
||||||
|
mCode = ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||||
|
// mCode stays as set in this(success, httpCode, headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// before
|
||||||
|
switch (mHttpCode) {
|
||||||
|
case HttpStatus.SC_FORBIDDEN:
|
||||||
|
parseErrorMessageAndSetCode(request, response, ResultCode.SPECIFIC_FORBIDDEN);
|
||||||
|
break;
|
||||||
|
case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE:
|
||||||
|
parseErrorMessageAndSetCode(request, response, ResultCode.SPECIFIC_UNSUPPORTED_MEDIA_TYPE);
|
||||||
|
break;
|
||||||
|
case HttpStatus.SC_SERVICE_UNAVAILABLE:
|
||||||
|
parseErrorMessageAndSetCode(request, response, ResultCode.SPECIFIC_SERVICE_UNAVAILABLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the error message included in the body response, if any, and set the specific result
|
||||||
|
* code
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the error message included in the body response, if any, and set the specific result
|
||||||
|
* code
|
||||||
|
*
|
||||||
|
* @param request okHttp request
|
||||||
|
* @param response okHttp respnse
|
||||||
|
* @param resultCode our own custom result code
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void parseErrorMessageAndSetCode(Request request, Response response, ResultCode resultCode)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
String bodyResponse = response.body().string();
|
||||||
|
|
||||||
|
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||||
|
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||||
|
ErrorMessageParser xmlParser = new ErrorMessageParser();
|
||||||
|
try {
|
||||||
|
String errorMessage = xmlParser.parseXMLResponse(is);
|
||||||
|
if (errorMessage != "" && errorMessage != null) {
|
||||||
|
mCode = resultCode;
|
||||||
|
mHttpPhrase = errorMessage;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.w(TAG, "Error reading exception from server: " + e.getMessage());
|
||||||
|
// mCode stays as set in this(success, httpCode, headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public constructor from separate elements of an HTTP or DAV response.
|
||||||
|
*
|
||||||
|
* To be used when the result needs to be interpreted from HTTP response elements that could come from
|
||||||
|
* different requests (WARNING: black magic, try to avoid).
|
||||||
|
*
|
||||||
|
* Determines a {@link ResultCode} depending on the HTTP code and HTTP response headers received.
|
||||||
|
*
|
||||||
|
* @param success The operation was considered successful or not.
|
||||||
|
* @param httpCode HTTP status code returned by an HTTP/DAV method.
|
||||||
|
* @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method
|
||||||
|
* @param headers HTTP response header returned by an HTTP/DAV method
|
||||||
|
*/
|
||||||
|
public RemoteOperationResult(boolean success, int httpCode, String httpPhrase, Headers headers) {
|
||||||
|
this(success, httpCode, httpPhrase);
|
||||||
|
for (Map.Entry<String, List<String>> header : headers.toMultimap().entrySet()) {
|
||||||
|
if ("location".equals(header.getKey().toLowerCase())) {
|
||||||
|
mRedirectedLocation = header.getValue().get(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ("www-authenticate".equals(header.getKey().toLowerCase())) {
|
||||||
|
mAuthenticate.add(header.getValue().get(0).toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isIdPRedirection()) {
|
||||||
|
mCode = ResultCode.UNAUTHORIZED; // overrides default ResultCode.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor for results built interpreting a HTTP or DAV response.
|
||||||
|
*
|
||||||
|
* Determines a {@link ResultCode} depending of the type of the exception.
|
||||||
|
*
|
||||||
|
* @param success Operation was successful or not.
|
||||||
|
* @param httpCode HTTP status code returned by the HTTP/DAV method.
|
||||||
|
* @param httpPhrase HTTP status line phrase returned by the HTTP/DAV method
|
||||||
|
*/
|
||||||
|
private RemoteOperationResult(boolean success, int httpCode, String httpPhrase) {
|
||||||
|
mSuccess = success;
|
||||||
|
mHttpCode = httpCode;
|
||||||
|
mHttpPhrase = httpPhrase;
|
||||||
|
mCode = success
|
||||||
|
? ResultCode.OK
|
||||||
|
: getCodeFromStatus(httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultCode getCodeFromStatus(int status) {
|
||||||
|
switch (status) {
|
||||||
|
case HttpStatus.SC_UNAUTHORIZED: return ResultCode.UNAUTHORIZED;
|
||||||
|
case HttpStatus.SC_FORBIDDEN: return ResultCode.FORBIDDEN;
|
||||||
|
case HttpStatus.SC_NOT_FOUND: return ResultCode.FILE_NOT_FOUND;
|
||||||
|
case HttpStatus.SC_CONFLICT: return ResultCode.CONFLICT;
|
||||||
|
case HttpStatus.SC_INTERNAL_SERVER_ERROR: return ResultCode.INSTANCE_NOT_CONFIGURED;
|
||||||
|
case HttpStatus.SC_SERVICE_UNAVAILABLE: return ResultCode.SERVICE_UNAVAILABLE;
|
||||||
|
case HttpStatus.SC_INSUFFICIENT_STORAGE: return ResultCode.QUOTA_EXCEEDED;
|
||||||
|
default:
|
||||||
|
Log_OC.d(TAG,
|
||||||
|
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
||||||
|
mHttpCode + " " + mHttpPhrase
|
||||||
|
);
|
||||||
|
return ResultCode.UNHANDLED_HTTP_CODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(ArrayList<Object> files) {
|
||||||
|
mData = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Object> getData() {
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return mSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return mCode == ResultCode.CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHttpCode() {
|
||||||
|
return mHttpCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHttpPhrase() {
|
||||||
|
return mHttpPhrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultCode getCode() {
|
||||||
|
return mCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception getException() {
|
||||||
|
return mException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSslRecoverableException() {
|
||||||
|
return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRedirectToNonSecureConnection() {
|
||||||
|
return mCode == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
if(mException instanceof SocketException) return "Socket exception";
|
||||||
|
if(mException instanceof SocketTimeoutException) return "Socket timeout exception";
|
||||||
|
if(mException instanceof MalformedURLException) return "Malformed URL exception";
|
||||||
|
if(mException instanceof UnknownHostException) return "Unknown host exception";
|
||||||
|
if(mException instanceof CertificateCombinedException) {
|
||||||
|
if (((CertificateCombinedException) mException).isRecoverable())
|
||||||
|
return "SSL recoverable exception";
|
||||||
|
else
|
||||||
|
return "SSL exception";
|
||||||
|
|
||||||
|
}
|
||||||
|
if(mException instanceof SSLException) return "SSL exception";
|
||||||
|
if(mException instanceof DavException) return "Unexpected WebDAV exception";
|
||||||
|
if(mException instanceof HttpException) return "HTTP violation";
|
||||||
|
if(mException instanceof IOException) return "Unrecovered transport exception";
|
||||||
|
if(mException instanceof AccountUtils.AccountNotFoundException) {
|
||||||
|
Account failedAccount =
|
||||||
|
((AccountUtils.AccountNotFoundException) mException).getFailedAccount();
|
||||||
|
return mException.getMessage() + " (" +
|
||||||
|
(failedAccount != null ? failedAccount.name : "NULL") + ")";
|
||||||
|
|
||||||
|
}
|
||||||
|
if (mException instanceof AccountsException) return "Exception while using account";
|
||||||
|
if (mException instanceof JSONException) return "JSON exception";
|
||||||
|
|
||||||
|
return "Unexpected exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mCode == ResultCode.INSTANCE_NOT_CONFIGURED)
|
||||||
|
return "The ownCloud server is not configured!";
|
||||||
|
if(mCode == ResultCode.NO_NETWORK_CONNECTION) return "No network connection";
|
||||||
|
if(mCode == ResultCode.BAD_OC_VERSION)
|
||||||
|
return "No valid ownCloud version was found at the server";
|
||||||
|
if(mCode == ResultCode.LOCAL_STORAGE_FULL) return "Local storage full";
|
||||||
|
if(mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED)
|
||||||
|
return "Error while moving file to final directory";
|
||||||
|
if(mCode == ResultCode.ACCOUNT_NOT_NEW)
|
||||||
|
return "Account already existing when creating a new one";
|
||||||
|
if(mCode == ResultCode.INVALID_CHARACTER_IN_NAME)
|
||||||
|
return "The file name contains an forbidden character";
|
||||||
|
if(mCode == ResultCode.FILE_NOT_FOUND) return "Local file does not exist";
|
||||||
|
if(mCode == ResultCode.SYNC_CONFLICT) return "Synchronization conflict";
|
||||||
|
|
||||||
|
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")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is a non https connection
|
||||||
|
*
|
||||||
|
* @return boolean true/false
|
||||||
|
*/
|
||||||
|
public boolean isNonSecureRedirection() {
|
||||||
|
return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getAuthenticateHeaders() {
|
||||||
|
return mAuthenticate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastPermanentLocation() {
|
||||||
|
return mLastPermanentLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastPermanentLocation(String lastPermanentLocation) {
|
||||||
|
mLastPermanentLocation = lastPermanentLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public interface OwnCloudCredentials {
|
||||||
|
|
||||||
|
Map<String, String> getCredentialHeaders();
|
||||||
|
|
||||||
|
//TODO: Remove this once SAML is obsolet
|
||||||
|
default String getCredentialCookie() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getUsername();
|
||||||
|
String getAuthToken();
|
||||||
|
boolean authTokenCanBeRefreshed();
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.owncloud.android.lib.refactor.authentication.credentials;
|
||||||
|
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
public class OwnCloudAnonymousCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getCredentialHeaders() {
|
||||||
|
return new HashMap<>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthToken() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean authTokenCanBeRefreshed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.credentials;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.Authenticator;
|
||||||
|
import okhttp3.Credentials;
|
||||||
|
|
||||||
|
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
|
private String mUsername;
|
||||||
|
private String mPassword;
|
||||||
|
|
||||||
|
public OwnCloudBasicCredentials(String username, String password) {
|
||||||
|
mUsername = username != null ? username : "";
|
||||||
|
mPassword = password != null ? password : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getCredentialHeaders() {
|
||||||
|
HashMap<String, String> header = new HashMap<>(1);
|
||||||
|
header.put("Authorization", Credentials.basic(mUsername, mPassword));
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return mUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthToken() {
|
||||||
|
return mPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean authTokenCanBeRefreshed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.credentials;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.Authenticator;
|
||||||
|
|
||||||
|
public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
|
private String mUsername;
|
||||||
|
|
||||||
|
private String mAccessToken;
|
||||||
|
|
||||||
|
public OwnCloudBearerCredentials(String username, String accessToken) {
|
||||||
|
mUsername = username != null ? username : "";
|
||||||
|
mAccessToken = accessToken != null ? accessToken : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getCredentialHeaders() {
|
||||||
|
HashMap<String, String> header = new HashMap<>(1);
|
||||||
|
header.put("Authorization", "Bearer " + mAccessToken);
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
// not relevant for authentication, but relevant for informational purposes
|
||||||
|
return mUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthToken() {
|
||||||
|
return mAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean authTokenCanBeRefreshed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.credentials;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
|
||||||
|
import org.apache.commons.httpclient.Cookie;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
|
private final String mUsername;
|
||||||
|
private final String mSessionCookie;
|
||||||
|
private final Uri mBaseUrl;
|
||||||
|
|
||||||
|
public OwnCloudSamlSsoCredentials(String username, String sessionCookie, Uri baseUrl) {
|
||||||
|
mUsername = username != null ? username : "";
|
||||||
|
mSessionCookie = sessionCookie != null ? sessionCookie : "";
|
||||||
|
mBaseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCredentialCookie() {
|
||||||
|
|
||||||
|
String[] rawCookies = mSessionCookie.split(";");
|
||||||
|
StringBuilder processedCookies = new StringBuilder();
|
||||||
|
Cookie cookie = null;
|
||||||
|
for (final String rawCookie : rawCookies) {
|
||||||
|
int equalPos = rawCookie.indexOf('=');
|
||||||
|
if (equalPos >= 0) {
|
||||||
|
cookie = new Cookie();
|
||||||
|
cookie.setName(rawCookie.substring(0, equalPos));
|
||||||
|
cookie.setValue(rawCookie.substring(equalPos + 1));
|
||||||
|
cookie.setDomain(mBaseUrl.getHost()); // VERY IMPORTANT
|
||||||
|
cookie.setPath(mBaseUrl.getPath()); // VERY IMPORTANT
|
||||||
|
processedCookies.append(cookie.toExternalForm() + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processedCookies.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getCredentialHeaders() {
|
||||||
|
return new HashMap<>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
// not relevant for authentication, but relevant for informational purposes
|
||||||
|
return mUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthToken() {
|
||||||
|
return mSessionCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean authTokenCanBeRefreshed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,261 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
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 java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException {
|
||||||
|
BearerCredentials bearer;
|
||||||
|
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 {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
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 " + 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.
|
||||||
|
*/
|
||||||
|
@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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
import org.apache.commons.httpclient.util.LangUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
*/
|
||||||
|
public class BearerCredentials {
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
public class OAuth2ClientConfiguration {
|
||||||
|
|
||||||
|
private String mClientId;
|
||||||
|
|
||||||
|
private String mClientSecret;
|
||||||
|
|
||||||
|
private String mRedirectUri;
|
||||||
|
|
||||||
|
public OAuth2ClientConfiguration(String clientId, String clientSecret, String redirectUri) {
|
||||||
|
mClientId = (clientId == null) ? "" : clientId;
|
||||||
|
mClientSecret = (clientSecret == null) ? "" : clientSecret;
|
||||||
|
mRedirectUri = (redirectUri == null) ? "" : redirectUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientId() {
|
||||||
|
return mClientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientSecret() {
|
||||||
|
return mClientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRedirectUri() {
|
||||||
|
return mRedirectUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant values for OAuth 2 protocol.
|
||||||
|
*
|
||||||
|
* Includes required and optional parameter NAMES used in the 'authorization code' grant type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class OAuth2Constants {
|
||||||
|
|
||||||
|
/// Parameters to send to the Authorization Endpoint
|
||||||
|
public static final String KEY_RESPONSE_TYPE = "response_type";
|
||||||
|
public static final String KEY_REDIRECT_URI = "redirect_uri";
|
||||||
|
public static final String KEY_CLIENT_ID = "client_id";
|
||||||
|
public static final String KEY_SCOPE = "scope";
|
||||||
|
public static final String KEY_STATE = "state";
|
||||||
|
|
||||||
|
/// Additional parameters to send to the Token Endpoint
|
||||||
|
public static final String KEY_GRANT_TYPE = "grant_type";
|
||||||
|
public static final String KEY_CODE = "code";
|
||||||
|
|
||||||
|
// Used to get the Access Token using Refresh Token
|
||||||
|
public static final String OAUTH2_REFRESH_TOKEN_GRANT_TYPE = "refresh_token";
|
||||||
|
|
||||||
|
/// Parameters received in an OK response from the Token Endpoint
|
||||||
|
public static final String KEY_ACCESS_TOKEN = "access_token";
|
||||||
|
public static final String KEY_TOKEN_TYPE = "token_type";
|
||||||
|
public static final String KEY_EXPIRES_IN = "expires_in";
|
||||||
|
public static final String KEY_REFRESH_TOKEN = "refresh_token";
|
||||||
|
|
||||||
|
/// Parameters in an ERROR response
|
||||||
|
public static final String KEY_ERROR = "error";
|
||||||
|
public static final String KEY_ERROR_DESCRIPTION = "error_description";
|
||||||
|
public static final String KEY_ERROR_URI = "error_uri";
|
||||||
|
public static final String VALUE_ERROR_ACCESS_DENIED = "access_denied";
|
||||||
|
|
||||||
|
/// Extra not standard
|
||||||
|
public static final String KEY_USER_ID = "user_id";
|
||||||
|
|
||||||
|
/// Depends on oauth2 grant type
|
||||||
|
public static final String OAUTH2_RESPONSE_TYPE_CODE = "code";
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
public enum OAuth2GrantType {
|
||||||
|
AUTHORIZATION_CODE("authorization_code"),
|
||||||
|
IMPLICIT("implicit"),
|
||||||
|
PASSWORD("password"),
|
||||||
|
CLIENT_CREDENTIAL("client_credentials"),
|
||||||
|
REFRESH_TOKEN("refresh_token") // not a grant type conceptually, but used as such to refresh access tokens
|
||||||
|
;
|
||||||
|
|
||||||
|
private String mValue;
|
||||||
|
|
||||||
|
OAuth2GrantType(String value) {
|
||||||
|
mValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return mValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
public interface OAuth2Provider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link OAuth2RequestBuilder} implementation for this provider.
|
||||||
|
*
|
||||||
|
* @return {@link OAuth2RequestBuilder} implementation.
|
||||||
|
*/
|
||||||
|
OAuth2RequestBuilder getOperationBuilder();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set configuration of the client that will use this {@link OAuth2Provider}
|
||||||
|
* @param oAuth2ClientConfiguration Configuration of the client that will use this {@link OAuth2Provider}
|
||||||
|
*/
|
||||||
|
void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration of the client that is using this {@link OAuth2Provider}
|
||||||
|
* return Configuration of the client that is usinng this {@link OAuth2Provider}
|
||||||
|
*/
|
||||||
|
OAuth2ClientConfiguration getClientConfiguration();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set base URI to authorization server.
|
||||||
|
*
|
||||||
|
* @param authorizationServerUri Set base URL to authorization server.
|
||||||
|
*/
|
||||||
|
void setAuthorizationServerUri(String authorizationServerUri);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base URI to authorization server.
|
||||||
|
*
|
||||||
|
* @return Base URL to authorization server.
|
||||||
|
*/
|
||||||
|
String getAuthorizationServerUri();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OAuth2ProvidersRegistry {
|
||||||
|
|
||||||
|
private Map<String, OAuth2Provider> mProviders = new HashMap<>();
|
||||||
|
|
||||||
|
private OAuth2Provider mDefaultProvider = null;
|
||||||
|
|
||||||
|
private OAuth2ProvidersRegistry () {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
|
||||||
|
*/
|
||||||
|
private static class LazyHolder {
|
||||||
|
private static final OAuth2ProvidersRegistry INSTANCE = new OAuth2ProvidersRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton accesor.
|
||||||
|
*
|
||||||
|
* @return Singleton isntance of {@link OAuth2ProvidersRegistry}
|
||||||
|
*/
|
||||||
|
public static OAuth2ProvidersRegistry getInstance() {
|
||||||
|
return LazyHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an {@link OAuth2Provider} with the name passed as parameter.
|
||||||
|
*
|
||||||
|
* @param name Name to bind 'oAuthProvider' in the registry.
|
||||||
|
* @param oAuth2Provider An {@link OAuth2Provider} instance to keep in the registry.
|
||||||
|
* @throws IllegalArgumentException if 'name' or 'oAuthProvider' are null.
|
||||||
|
*/
|
||||||
|
public void registerProvider(String name, OAuth2Provider oAuth2Provider) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new IllegalArgumentException("Name must not be NULL");
|
||||||
|
}
|
||||||
|
if (oAuth2Provider == null) {
|
||||||
|
throw new IllegalArgumentException("oAuth2Provider must not be NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
mProviders.put(name, oAuth2Provider);
|
||||||
|
if (mProviders.size() == 1) {
|
||||||
|
mDefaultProvider = oAuth2Provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuth2Provider unregisterProvider(String name) {
|
||||||
|
OAuth2Provider unregisteredProvider = mProviders.remove(name);
|
||||||
|
if (mProviders.size() == 0) {
|
||||||
|
mDefaultProvider = null;
|
||||||
|
} else if (unregisteredProvider != null && unregisteredProvider == mDefaultProvider) {
|
||||||
|
mDefaultProvider = mProviders.values().iterator().next();
|
||||||
|
}
|
||||||
|
return unregisteredProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default {@link OAuth2Provider}.
|
||||||
|
*
|
||||||
|
* @return Default provider, or NULL if there is no provider.
|
||||||
|
*/
|
||||||
|
public OAuth2Provider getProvider() {
|
||||||
|
return mDefaultProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get {@link OAuth2Provider} registered with the name passed as parameter.
|
||||||
|
*
|
||||||
|
* @param name Name used to register the desired {@link OAuth2Provider}
|
||||||
|
* @return {@link OAuth2Provider} registered with the name 'name'
|
||||||
|
*/
|
||||||
|
public OAuth2Provider getProvider(String name) {
|
||||||
|
return mProviders.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link OAuth2Provider} registered with the name passed as parameter as the default provider
|
||||||
|
*
|
||||||
|
* @param name Name used to register the {@link OAuth2Provider} to set as default.
|
||||||
|
* @return {@link OAuth2Provider} set as default, or NULL if no provider was registered with 'name'.
|
||||||
|
*/
|
||||||
|
public OAuth2Provider setDefaultProvider(String name) {
|
||||||
|
OAuth2Provider toDefault = mProviders.get(name);
|
||||||
|
if (toDefault != null) {
|
||||||
|
mDefaultProvider = toDefault;
|
||||||
|
}
|
||||||
|
return toDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.Log_OC;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public class OAuth2QueryParser {
|
||||||
|
|
||||||
|
private static final String TAG = OAuth2QueryParser.class.getName();
|
||||||
|
|
||||||
|
private Map<String, String> mOAuth2ParsedAuthorizationResponse;
|
||||||
|
|
||||||
|
public OAuth2QueryParser() {
|
||||||
|
mOAuth2ParsedAuthorizationResponse = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> parse(String query) {
|
||||||
|
mOAuth2ParsedAuthorizationResponse.clear();
|
||||||
|
|
||||||
|
if (query != null) {
|
||||||
|
String[] pairs = query.split("&");
|
||||||
|
int i = 0;
|
||||||
|
String key = "";
|
||||||
|
String value;
|
||||||
|
while (pairs.length > i) {
|
||||||
|
int j = 0;
|
||||||
|
String[] part = pairs[i].split("=");
|
||||||
|
while (part.length > j) {
|
||||||
|
String p = part[j];
|
||||||
|
if (j == 0) {
|
||||||
|
key = p;
|
||||||
|
} else if (j == 1) {
|
||||||
|
value = p;
|
||||||
|
mOAuth2ParsedAuthorizationResponse.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log_OC.v(TAG, "[" + i + "," + j + "] = " + p);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mOAuth2ParsedAuthorizationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
|
||||||
|
public interface OAuth2RequestBuilder {
|
||||||
|
|
||||||
|
enum OAuthRequest {
|
||||||
|
GET_AUTHORIZATION_CODE, CREATE_ACCESS_TOKEN, REFRESH_ACCESS_TOKEN
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRequest(OAuthRequest operation);
|
||||||
|
|
||||||
|
void setGrantType(OAuth2GrantType grantType);
|
||||||
|
|
||||||
|
void setAuthorizationCode(String code);
|
||||||
|
|
||||||
|
void setRefreshToken(String refreshToken);
|
||||||
|
|
||||||
|
RemoteOperation buildOperation();
|
||||||
|
|
||||||
|
String buildUri();
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* ownCloud Android client application
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* 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.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class OAuth2ResponseParser {
|
||||||
|
|
||||||
|
public Map<String, String> parseAccessTokenResult(JSONObject tokenJson) throws JSONException {
|
||||||
|
Map<String, String> resultTokenMap = new HashMap<>();
|
||||||
|
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_ACCESS_TOKEN)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_ACCESS_TOKEN, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_ACCESS_TOKEN));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_TOKEN_TYPE)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_TOKEN_TYPE, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_TOKEN_TYPE));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_EXPIRES_IN)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_EXPIRES_IN, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_EXPIRES_IN));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_REFRESH_TOKEN)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_REFRESH_TOKEN, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_REFRESH_TOKEN));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_SCOPE)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_SCOPE, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_SCOPE));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_ERROR)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_ERROR, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_ERROR));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_ERROR_DESCRIPTION)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_ERROR_DESCRIPTION, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_ERROR_DESCRIPTION));
|
||||||
|
}
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_ERROR_URI)) {
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_ERROR_URI, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_ERROR_URI));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenJson.has(OAuth2Constants.KEY_USER_ID)) { // not standard
|
||||||
|
resultTokenMap.put(OAuth2Constants.KEY_USER_ID, tokenJson.
|
||||||
|
getString(OAuth2Constants.KEY_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultTokenMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.Log_OC;
|
||||||
|
|
||||||
|
public class OwnCloudOAuth2Provider implements OAuth2Provider {
|
||||||
|
|
||||||
|
public static final String NAME = OAuth2Provider.class.getName();
|
||||||
|
|
||||||
|
public static final String ACCESS_TOKEN_ENDPOINT_PATH = "index.php/apps/oauth2/api/v1/token";
|
||||||
|
private static final String AUTHORIZATION_CODE_ENDPOINT_PATH = "index.php/apps/oauth2/authorize";
|
||||||
|
|
||||||
|
private String mAuthorizationServerUrl = "";
|
||||||
|
private String mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||||
|
private String mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||||
|
|
||||||
|
private OAuth2ClientConfiguration mClientConfiguration;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth2RequestBuilder getOperationBuilder() {
|
||||||
|
return new OwnCloudOAuth2RequestBuilder(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setClientConfiguration(OAuth2ClientConfiguration oAuth2ClientConfiguration) {
|
||||||
|
mClientConfiguration = oAuth2ClientConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth2ClientConfiguration getClientConfiguration() {
|
||||||
|
return mClientConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAuthorizationServerUri(String authorizationServerUri) {
|
||||||
|
mAuthorizationServerUrl = authorizationServerUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthorizationServerUri() {
|
||||||
|
return mAuthorizationServerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessTokenEndpointPath() {
|
||||||
|
return mAccessTokenEndpointPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessTokenEndpointPath(String accessTokenEndpointPath) {
|
||||||
|
if (accessTokenEndpointPath == null || accessTokenEndpointPath.length() <= 0) {
|
||||||
|
Log_OC.w(NAME, "Setting invalid access token endpoint path, going on with default");
|
||||||
|
mAccessTokenEndpointPath = ACCESS_TOKEN_ENDPOINT_PATH;
|
||||||
|
} else {
|
||||||
|
mAccessTokenEndpointPath = accessTokenEndpointPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthorizationCodeEndpointPath() {
|
||||||
|
return mAuthorizationCodeEndpointPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorizationCodeEndpointPath(String authorizationCodeEndpointPath) {
|
||||||
|
if (authorizationCodeEndpointPath == null || authorizationCodeEndpointPath.length() <= 0) {
|
||||||
|
Log_OC.w(NAME, "Setting invalid authorization code endpoint path, going on with default");
|
||||||
|
mAuthorizationCodeEndpointPath = AUTHORIZATION_CODE_ENDPOINT_PATH;
|
||||||
|
} else {
|
||||||
|
mAuthorizationCodeEndpointPath = authorizationCodeEndpointPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.OwnCloudContext;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.operations.OAuth2GetAccessTokenOperation;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.operations.OAuth2RefreshAccessTokenOperation;
|
||||||
|
|
||||||
|
public class OwnCloudOAuth2RequestBuilder implements OAuth2RequestBuilder {
|
||||||
|
|
||||||
|
private OwnCloudContext ocContext;
|
||||||
|
private OwnCloudOAuth2Provider mOAuth2Provider;
|
||||||
|
|
||||||
|
private OAuthRequest mRequest;
|
||||||
|
private OAuth2GrantType mGrantType = OAuth2GrantType.AUTHORIZATION_CODE;
|
||||||
|
private String mCode;
|
||||||
|
private String mRefreshToken;
|
||||||
|
|
||||||
|
public OwnCloudOAuth2RequestBuilder(OwnCloudOAuth2Provider ownCloudOAuth2Provider) {
|
||||||
|
mOAuth2Provider = ownCloudOAuth2Provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRequest(OAuthRequest request) {
|
||||||
|
mRequest = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGrantType(OAuth2GrantType grantType) {
|
||||||
|
mGrantType = grantType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAuthorizationCode(String code) {
|
||||||
|
mCode = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRefreshToken(String refreshToken) {
|
||||||
|
mRefreshToken = refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOcContext(OwnCloudContext ocContext) {
|
||||||
|
this.ocContext = ocContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteOperation buildOperation() {
|
||||||
|
if (mGrantType != OAuth2GrantType.AUTHORIZATION_CODE &&
|
||||||
|
mGrantType != OAuth2GrantType.REFRESH_TOKEN) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported grant type. Only " +
|
||||||
|
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " and " +
|
||||||
|
OAuth2GrantType.REFRESH_TOKEN + " are supported");
|
||||||
|
}
|
||||||
|
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||||
|
|
||||||
|
switch(mRequest) {
|
||||||
|
case CREATE_ACCESS_TOKEN:
|
||||||
|
return new OAuth2GetAccessTokenOperation(
|
||||||
|
ocContext,
|
||||||
|
mGrantType.getValue(),
|
||||||
|
mCode,
|
||||||
|
clientConfiguration.getClientId(),
|
||||||
|
clientConfiguration.getClientSecret(),
|
||||||
|
clientConfiguration.getRedirectUri(),
|
||||||
|
mOAuth2Provider.getAccessTokenEndpointPath());
|
||||||
|
|
||||||
|
case REFRESH_ACCESS_TOKEN:
|
||||||
|
return new OAuth2RefreshAccessTokenOperation(
|
||||||
|
ocContext,
|
||||||
|
clientConfiguration.getClientId(),
|
||||||
|
clientConfiguration.getClientSecret(),
|
||||||
|
mRefreshToken,
|
||||||
|
mOAuth2Provider.getAccessTokenEndpointPath());
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unsupported request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String buildUri() {
|
||||||
|
if (OAuth2GrantType.AUTHORIZATION_CODE != mGrantType) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported grant type. Only " +
|
||||||
|
OAuth2GrantType.AUTHORIZATION_CODE.getValue() + " is supported by this provider"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
OAuth2ClientConfiguration clientConfiguration = mOAuth2Provider.getClientConfiguration();
|
||||||
|
Uri uri;
|
||||||
|
Uri.Builder uriBuilder;
|
||||||
|
switch(mRequest) {
|
||||||
|
case GET_AUTHORIZATION_CODE:
|
||||||
|
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||||
|
uriBuilder = uri.buildUpon();
|
||||||
|
uriBuilder.appendEncodedPath(mOAuth2Provider.getAuthorizationCodeEndpointPath());
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE);
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri());
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId());
|
||||||
|
|
||||||
|
uri = uriBuilder.build();
|
||||||
|
return uri.toString();
|
||||||
|
|
||||||
|
case CREATE_ACCESS_TOKEN:
|
||||||
|
uri = Uri.parse(mOAuth2Provider.getAuthorizationServerUri());
|
||||||
|
uriBuilder = uri.buildUpon();
|
||||||
|
uriBuilder.appendEncodedPath(mOAuth2Provider.getAccessTokenEndpointPath());
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_RESPONSE_TYPE, OAuth2Constants.OAUTH2_RESPONSE_TYPE_CODE);
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_REDIRECT_URI, clientConfiguration.getRedirectUri());
|
||||||
|
uriBuilder.appendQueryParameter(
|
||||||
|
OAuth2Constants.KEY_CLIENT_ID, clientConfiguration.getClientId());
|
||||||
|
|
||||||
|
uri = uriBuilder.build();
|
||||||
|
return uri.toString();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Unsupported request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.authentication.oauth.operations;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.OwnCloudContext;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperationResult;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OAuth2Constants;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OAuth2ResponseParser;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OwnCloudOAuth2Provider;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
|
||||||
|
public class OAuth2GetAccessTokenOperation extends RemoteOperation {
|
||||||
|
|
||||||
|
private final String mGrantType;
|
||||||
|
private final String mCode;
|
||||||
|
private final String mClientId;
|
||||||
|
private final String mClientSecret;
|
||||||
|
private final String mRedirectUri;
|
||||||
|
private final String mAccessTokenEndpointPath;
|
||||||
|
|
||||||
|
private final OAuth2ResponseParser mResponseParser;
|
||||||
|
|
||||||
|
|
||||||
|
public OAuth2GetAccessTokenOperation(
|
||||||
|
OwnCloudContext context,
|
||||||
|
String grantType,
|
||||||
|
String code,
|
||||||
|
String clientId,
|
||||||
|
String secretId,
|
||||||
|
String redirectUri,
|
||||||
|
String accessTokenEndpointPath) {
|
||||||
|
super(context);
|
||||||
|
mClientId = clientId;
|
||||||
|
mClientSecret = secretId;
|
||||||
|
mRedirectUri = redirectUri;
|
||||||
|
mGrantType = grantType;
|
||||||
|
mCode = code;
|
||||||
|
|
||||||
|
mAccessTokenEndpointPath =
|
||||||
|
accessTokenEndpointPath != null
|
||||||
|
? accessTokenEndpointPath
|
||||||
|
: OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH;
|
||||||
|
|
||||||
|
mResponseParser = new OAuth2ResponseParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteOperationResult exec() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
final Uri uri = getOCContext()
|
||||||
|
.getBaseUri()
|
||||||
|
.buildUpon()
|
||||||
|
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final RequestBody requestBody = new MultipartBody.Builder()
|
||||||
|
.setType(MultipartBody.FORM)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE, mGrantType)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_CODE, mCode)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final Request request = getRequestBuilder()
|
||||||
|
.url(uri.toString())
|
||||||
|
.method("POST", requestBody)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final Response response = getClient()
|
||||||
|
.newCall(request)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final String responseData = response.body().string();
|
||||||
|
if (responseData != null && responseData.length() > 0) {
|
||||||
|
JSONObject tokenJson = new JSONObject(responseData);
|
||||||
|
Map<String, String> accessTokenResult =
|
||||||
|
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||||
|
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||||
|
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||||
|
return new RemoteOperationResult(RemoteOperationResult.ResultCode.OAUTH2_ERROR);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final RemoteOperationResult result = new RemoteOperationResult(true, request, response);
|
||||||
|
ArrayList<Object> data = new ArrayList<>();
|
||||||
|
data.add(accessTokenResult);
|
||||||
|
result.setData(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return new RemoteOperationResult(false, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new RemoteOperationResult(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* ownCloud Android client application
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* 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.lib.refactor.authentication.oauth.operations;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.OwnCloudContext;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperationResult;
|
||||||
|
import com.owncloud.android.lib.refactor.Log_OC;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.credentials.OwnCloudBasicCredentials;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.OwnCloudCredentials;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OAuth2Constants;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OAuth2GrantType;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OAuth2ResponseParser;
|
||||||
|
import com.owncloud.android.lib.refactor.authentication.oauth.OwnCloudOAuth2Provider;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation {
|
||||||
|
|
||||||
|
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
|
||||||
|
|
||||||
|
private String mClientId;
|
||||||
|
private String mClientSecret;
|
||||||
|
private String mRefreshToken;
|
||||||
|
|
||||||
|
private final String mAccessTokenEndpointPath;
|
||||||
|
|
||||||
|
private final OAuth2ResponseParser mResponseParser;
|
||||||
|
|
||||||
|
public OAuth2RefreshAccessTokenOperation(
|
||||||
|
OwnCloudContext ocContext,
|
||||||
|
String clientId,
|
||||||
|
String secretId,
|
||||||
|
String refreshToken,
|
||||||
|
String accessTokenEndpointPath
|
||||||
|
) {
|
||||||
|
super(ocContext);
|
||||||
|
|
||||||
|
mClientId = clientId;
|
||||||
|
mClientSecret = secretId;
|
||||||
|
mRefreshToken = refreshToken;
|
||||||
|
|
||||||
|
mAccessTokenEndpointPath =
|
||||||
|
accessTokenEndpointPath != null ?
|
||||||
|
accessTokenEndpointPath :
|
||||||
|
OwnCloudOAuth2Provider.ACCESS_TOKEN_ENDPOINT_PATH
|
||||||
|
;
|
||||||
|
|
||||||
|
mResponseParser = new OAuth2ResponseParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteOperationResult exec() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
final RequestBody requestBody = new MultipartBody.Builder()
|
||||||
|
.setType(MultipartBody.FORM)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE,
|
||||||
|
OAuth2GrantType.REFRESH_TOKEN.getValue())
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final Request request = getRequestBuilder()
|
||||||
|
.url(getOCContext().getBaseUri().buildUpon()
|
||||||
|
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||||
|
.build()
|
||||||
|
.toString())
|
||||||
|
.method("POST", requestBody)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(
|
||||||
|
mClientId,
|
||||||
|
mClientSecret
|
||||||
|
);
|
||||||
|
|
||||||
|
final Response response = getClient().newCall(request).execute();
|
||||||
|
final String responseData = response.body().string();
|
||||||
|
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + responseData);
|
||||||
|
|
||||||
|
if (responseData != null && responseData.length() > 0) {
|
||||||
|
JSONObject tokenJson = new JSONObject(responseData);
|
||||||
|
Map<String, String> accessTokenResult =
|
||||||
|
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||||
|
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||||
|
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||||
|
return new RemoteOperationResult(RemoteOperationResult.ResultCode.OAUTH2_ERROR);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final RemoteOperationResult result = new RemoteOperationResult(true, request, response);
|
||||||
|
ArrayList<Object> data = new ArrayList<>();
|
||||||
|
data.add(accessTokenResult);
|
||||||
|
result.setData(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return new RemoteOperationResult(false, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new RemoteOperationResult(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.exceptions;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.network.AdvancedSslSocketFactory;
|
||||||
|
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.exceptions;
|
||||||
|
|
||||||
|
public class OperationCancelledException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated serial version - to avoid Java warning
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -6350981497740424983L;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.owncloud.android.lib.refactor.operations;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.refactor.OwnCloudContext;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperation;
|
||||||
|
import com.owncloud.android.lib.refactor.RemoteOperationResult;
|
||||||
|
|
||||||
|
public class PropfindOperation extends RemoteOperation {
|
||||||
|
|
||||||
|
public PropfindOperation(OwnCloudContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RemoteOperationResult exec() {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
321
src/com/owncloud/android/lib/refactor/utils/AccountUtils.java
Normal file
321
src/com/owncloud/android/lib/refactor/utils/AccountUtils.java
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.lib.refactor.utils;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.accounts.AccountsException;
|
||||||
|
import android.accounts.AuthenticatorException;
|
||||||
|
import android.accounts.OperationCanceledException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
|
||||||
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import org.apache.commons.httpclient.Cookie;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class AccountUtils {
|
||||||
|
|
||||||
|
private static final String TAG = AccountUtils.class.getSimpleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs full url to host and webdav resource basing on host version
|
||||||
|
*
|
||||||
|
* @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
|
||||||
|
* @param account A stored ownCloud {@link Account}
|
||||||
|
* @return Full URL to WebDAV endpoint in the server corresponding to 'account'.
|
||||||
|
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager
|
||||||
|
*/
|
||||||
|
public static String getWebDavUrlForAccount(Context context, Account account)
|
||||||
|
throws AccountNotFoundException {
|
||||||
|
|
||||||
|
return getBaseUrlForAccount(context, account) + OwnCloudClient.WEBDAV_PATH_4_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts url server from the account
|
||||||
|
*
|
||||||
|
* @param context Valid Android {@link Context}, needed to access the {@link AccountManager}
|
||||||
|
* @param account A stored ownCloud {@link Account}
|
||||||
|
* @return Full URL to the server corresponding to 'account', ending in the base path
|
||||||
|
* common to all API endpoints.
|
||||||
|
* @throws AccountNotFoundException When 'account' is unknown for the AccountManager
|
||||||
|
*/
|
||||||
|
public static String getBaseUrlForAccount(Context context, Account account)
|
||||||
|
throws AccountNotFoundException {
|
||||||
|
AccountManager ama = AccountManager.get(context.getApplicationContext());
|
||||||
|
String baseurl = ama.getUserData(account, Constants.KEY_OC_BASE_URL);
|
||||||
|
|
||||||
|
if (baseurl == null)
|
||||||
|
throw new AccountNotFoundException(account, "Account not found", null);
|
||||||
|
|
||||||
|
return baseurl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the username corresponding to an OC account.
|
||||||
|
*
|
||||||
|
* @param account An OC account
|
||||||
|
* @return Username for the given account, extracted from the account.name
|
||||||
|
*/
|
||||||
|
public static String getUsernameForAccount(Account account) {
|
||||||
|
String username = null;
|
||||||
|
try {
|
||||||
|
username = account.name.substring(0, account.name.lastIndexOf('@'));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.e(TAG, "Couldn't get a username for the given account", e);
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the stored server version corresponding to an OC account.
|
||||||
|
*
|
||||||
|
* @param account An OC account
|
||||||
|
* @param context Application context
|
||||||
|
* @return Version of the OC server, according to last check
|
||||||
|
*/
|
||||||
|
public static OwnCloudVersion getServerVersionForAccount(Account account, Context context) {
|
||||||
|
AccountManager ama = AccountManager.get(context);
|
||||||
|
OwnCloudVersion version = null;
|
||||||
|
try {
|
||||||
|
String versionString = ama.getUserData(account, Constants.KEY_OC_VERSION);
|
||||||
|
version = new OwnCloudVersion(versionString);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.e(TAG, "Couldn't get a the server version for an account", e);
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
* @throws AuthenticatorException
|
||||||
|
* @throws OperationCanceledException
|
||||||
|
*/
|
||||||
|
public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account)
|
||||||
|
throws OperationCanceledException, AuthenticatorException, IOException {
|
||||||
|
|
||||||
|
OwnCloudCredentials credentials = null;
|
||||||
|
AccountManager am = AccountManager.get(context);
|
||||||
|
|
||||||
|
String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
||||||
|
boolean isOauth2 = supportsOAuth2 != null && supportsOAuth2.equals("TRUE");
|
||||||
|
|
||||||
|
String supportsSamlSSo = am.getUserData(account,
|
||||||
|
AccountUtils.Constants.KEY_SUPPORTS_SAML_WEB_SSO);
|
||||||
|
|
||||||
|
boolean isSamlSso = supportsSamlSSo != null && supportsSamlSSo.equals("TRUE");
|
||||||
|
|
||||||
|
String username = AccountUtils.getUsernameForAccount(account);
|
||||||
|
OwnCloudVersion version = new OwnCloudVersion(am.getUserData(account, Constants.KEY_OC_VERSION));
|
||||||
|
|
||||||
|
if (isOauth2) {
|
||||||
|
String accessToken = am.blockingGetAuthToken(
|
||||||
|
account,
|
||||||
|
AccountTypeUtils.getAuthTokenTypeAccessToken(account.type),
|
||||||
|
false);
|
||||||
|
|
||||||
|
credentials = OwnCloudCredentialsFactory.newBearerCredentials(username, accessToken);
|
||||||
|
|
||||||
|
} else if (isSamlSso) {
|
||||||
|
String accessToken = am.blockingGetAuthToken(
|
||||||
|
account,
|
||||||
|
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(account.type),
|
||||||
|
false);
|
||||||
|
|
||||||
|
credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(username, accessToken);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String password = am.blockingGetAuthToken(
|
||||||
|
account,
|
||||||
|
AccountTypeUtils.getAuthTokenTypePass(account.type),
|
||||||
|
false);
|
||||||
|
|
||||||
|
credentials = OwnCloudCredentialsFactory.newBasicCredentials(
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
version.isPreemptiveAuthenticationPreferred()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentials;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String buildAccountNameOld(Uri serverBaseUrl, String username) {
|
||||||
|
if (serverBaseUrl.getScheme() == null) {
|
||||||
|
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
||||||
|
}
|
||||||
|
String accountName = username + "@" + serverBaseUrl.getHost();
|
||||||
|
if (serverBaseUrl.getPort() >= 0) {
|
||||||
|
accountName += ":" + serverBaseUrl.getPort();
|
||||||
|
}
|
||||||
|
return accountName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildAccountName(Uri serverBaseUrl, String username) {
|
||||||
|
if (serverBaseUrl.getScheme() == null) {
|
||||||
|
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove http:// or https://
|
||||||
|
String url = serverBaseUrl.toString();
|
||||||
|
if (url.contains("://")) {
|
||||||
|
url = url.substring(serverBaseUrl.toString().indexOf("://") + 3);
|
||||||
|
}
|
||||||
|
String accountName = username + "@" + url;
|
||||||
|
|
||||||
|
return accountName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
||||||
|
|
||||||
|
// Account Manager
|
||||||
|
AccountManager ac = AccountManager.get(context.getApplicationContext());
|
||||||
|
|
||||||
|
if (client != null) {
|
||||||
|
String cookiesString = client.getCookiesString();
|
||||||
|
if (!"".equals(cookiesString)) {
|
||||||
|
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
|
||||||
|
// Log_OC.d(TAG, "Saving Cookies: "+ cookiesString );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the client cookies persisted in an account stored in the system AccountManager.
|
||||||
|
*
|
||||||
|
* @param account Stored account.
|
||||||
|
* @param client Client to restore cookies in.
|
||||||
|
* @param context Android context used to access the system AccountManager.
|
||||||
|
*/
|
||||||
|
public static void restoreCookies(Account account, OwnCloudClient client, Context context) {
|
||||||
|
if (account == null) {
|
||||||
|
Log_OC.d(TAG, "Cannot restore cookie for null account");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log_OC.d(TAG, "Restoring cookies for " + account.name);
|
||||||
|
|
||||||
|
// Account Manager
|
||||||
|
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||||
|
|
||||||
|
Uri serverUri = (client.getBaseUri() != null) ? client.getBaseUri() : client.getWebdavUri();
|
||||||
|
|
||||||
|
String cookiesString = am.getUserData(account, Constants.KEY_COOKIES);
|
||||||
|
if (cookiesString != null) {
|
||||||
|
String[] cookies = cookiesString.split(";");
|
||||||
|
if (cookies.length > 0) {
|
||||||
|
for (int i = 0; i < cookies.length; i++) {
|
||||||
|
Cookie cookie = new Cookie();
|
||||||
|
int equalPos = cookies[i].indexOf('=');
|
||||||
|
cookie.setName(cookies[i].substring(0, equalPos));
|
||||||
|
cookie.setValue(cookies[i].substring(equalPos + 1));
|
||||||
|
cookie.setDomain(serverUri.getHost()); // VERY IMPORTANT
|
||||||
|
cookie.setPath(serverUri.getPath()); // VERY IMPORTANT
|
||||||
|
|
||||||
|
client.getState().addCookie(cookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Constants {
|
||||||
|
/**
|
||||||
|
* Version should be 3 numbers separated by dot so it can be parsed by
|
||||||
|
* {@link OwnCloudVersion}
|
||||||
|
*/
|
||||||
|
public static final String KEY_OC_VERSION = "oc_version";
|
||||||
|
/**
|
||||||
|
* Base url should point to owncloud installation without trailing / ie:
|
||||||
|
* http://server/path or https://owncloud.server
|
||||||
|
*/
|
||||||
|
public static final String KEY_OC_BASE_URL = "oc_base_url";
|
||||||
|
/**
|
||||||
|
* Flag signaling if the ownCloud server can be accessed with OAuth2 access tokens.
|
||||||
|
*/
|
||||||
|
public static final String KEY_SUPPORTS_OAUTH2 = "oc_supports_oauth2";
|
||||||
|
/**
|
||||||
|
* Flag signaling if the ownCloud server can be accessed with session cookies from SAML-based web single-sign-on.
|
||||||
|
*/
|
||||||
|
public static final String KEY_SUPPORTS_SAML_WEB_SSO = "oc_supports_saml_web_sso";
|
||||||
|
/**
|
||||||
|
* OC account cookies
|
||||||
|
*/
|
||||||
|
public static final String KEY_COOKIES = "oc_account_cookies";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OC account version
|
||||||
|
*/
|
||||||
|
public static final String KEY_OC_ACCOUNT_VERSION = "oc_account_version";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User's display name
|
||||||
|
*/
|
||||||
|
public static final String KEY_DISPLAY_NAME = "oc_display_name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 refresh token
|
||||||
|
**/
|
||||||
|
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2017 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.owncloud.android.lib.refactor.utils;
|
||||||
|
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for server exceptions
|
||||||
|
* @author davidgonzalez
|
||||||
|
*/
|
||||||
|
public class ErrorMessageParser {
|
||||||
|
// No namespaces
|
||||||
|
private static final String ns = null;
|
||||||
|
|
||||||
|
// Nodes for XML Parser
|
||||||
|
private static final String NODE_ERROR = "d:error";
|
||||||
|
private static final String NODE_MESSAGE = "s:message";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse exception response
|
||||||
|
* @param is
|
||||||
|
* @return errorMessage for an exception
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String parseXMLResponse(InputStream is) throws XmlPullParserException,
|
||||||
|
IOException {
|
||||||
|
String errorMessage = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// XMLPullParser
|
||||||
|
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||||
|
factory.setNamespaceAware(true);
|
||||||
|
|
||||||
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||||
|
parser.setInput(is, null);
|
||||||
|
parser.nextTag();
|
||||||
|
errorMessage = readError(parser);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse OCS node
|
||||||
|
* @param parser
|
||||||
|
* @return reason for exception
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private String readError (XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
String errorMessage = "";
|
||||||
|
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR);
|
||||||
|
while (parser.next() != XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = parser.getName();
|
||||||
|
// read NODE_MESSAGE
|
||||||
|
if (name.equalsIgnoreCase(NODE_MESSAGE)) {
|
||||||
|
errorMessage = readText(parser);
|
||||||
|
} else {
|
||||||
|
skip(parser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip tags in parser procedure
|
||||||
|
* @param parser
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
int depth = 1;
|
||||||
|
while (depth != 0) {
|
||||||
|
switch (parser.next()) {
|
||||||
|
case XmlPullParser.END_TAG:
|
||||||
|
depth--;
|
||||||
|
break;
|
||||||
|
case XmlPullParser.START_TAG:
|
||||||
|
depth++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the text from a node
|
||||||
|
* @param parser
|
||||||
|
* @return Text of the node
|
||||||
|
* @throws IOException
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
*/
|
||||||
|
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||||
|
String result = "";
|
||||||
|
if (parser.next() == XmlPullParser.TEXT) {
|
||||||
|
result = parser.getText();
|
||||||
|
parser.nextTag();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2016 ownCloud GmbH.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.owncloud.android.lib.refactor.utils;
|
||||||
|
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for Invalid Character server exception
|
||||||
|
* @author masensio
|
||||||
|
*/
|
||||||
|
public class InvalidCharacterExceptionParser {
|
||||||
|
|
||||||
|
private static final String EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath";
|
||||||
|
private static final String EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException";
|
||||||
|
|
||||||
|
// No namespaces
|
||||||
|
private static final String ns = null;
|
||||||
|
|
||||||
|
// Nodes for XML Parser
|
||||||
|
private static final String NODE_ERROR = "d:error";
|
||||||
|
private static final String NODE_EXCEPTION = "s:exception";
|
||||||
|
/**
|
||||||
|
* Parse is as an Invalid Path Exception
|
||||||
|
* @param is
|
||||||
|
* @return if The exception is an Invalid Char Exception
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public boolean parseXMLResponse(InputStream is) throws XmlPullParserException,
|
||||||
|
IOException {
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// XMLPullParser
|
||||||
|
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
|
||||||
|
factory.setNamespaceAware(true);
|
||||||
|
|
||||||
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
|
||||||
|
parser.setInput(is, null);
|
||||||
|
parser.nextTag();
|
||||||
|
result = readError(parser);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse OCS node
|
||||||
|
* @param parser
|
||||||
|
* @return List of ShareRemoteFiles
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private boolean readError (XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
String exception = "";
|
||||||
|
parser.require(XmlPullParser.START_TAG, ns , NODE_ERROR);
|
||||||
|
while (parser.next() != XmlPullParser.END_TAG) {
|
||||||
|
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = parser.getName();
|
||||||
|
// read NODE_EXCEPTION
|
||||||
|
if (name.equalsIgnoreCase(NODE_EXCEPTION)) {
|
||||||
|
exception = readText(parser);
|
||||||
|
} else {
|
||||||
|
skip(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return exception.equalsIgnoreCase(EXCEPTION_STRING) ||
|
||||||
|
exception.equalsIgnoreCase(EXCEPTION_UPLOAD_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip tags in parser procedure
|
||||||
|
* @param parser
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
if (parser.getEventType() != XmlPullParser.START_TAG) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
int depth = 1;
|
||||||
|
while (depth != 0) {
|
||||||
|
switch (parser.next()) {
|
||||||
|
case XmlPullParser.END_TAG:
|
||||||
|
depth--;
|
||||||
|
break;
|
||||||
|
case XmlPullParser.START_TAG:
|
||||||
|
depth++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the text from a node
|
||||||
|
* @param parser
|
||||||
|
* @return Text of the node
|
||||||
|
* @throws IOException
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
*/
|
||||||
|
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||||
|
String result = "";
|
||||||
|
if (parser.next() == XmlPullParser.TEXT) {
|
||||||
|
result = parser.getText();
|
||||||
|
parser.nextTag();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -38,6 +38,8 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.DavResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the read of remote file or folder in the ownCloud server.
|
* Remote operation performing the read of remote file or folder in the ownCloud server.
|
||||||
*
|
*
|
||||||
@ -72,6 +74,7 @@ public class ReadRemoteFolderOperation extends RemoteOperation {
|
|||||||
PropFindMethod query = null;
|
PropFindMethod query = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// remote request
|
// remote request
|
||||||
query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath),
|
query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath),
|
||||||
WebdavUtils.getAllPropSet(), // PropFind Properties
|
WebdavUtils.getAllPropSet(), // PropFind Properties
|
||||||
|
@ -43,4 +43,8 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user