mirror of
				https://github.com/owncloud/android-library.git
				synced 2025-10-31 18:37:17 +00:00 
			
		
		
		
	add dav4droid support part1
This commit is contained in:
		
							parent
							
								
									9ab1b40682
								
							
						
					
					
						commit
						cd3d20db07
					
				
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -30,4 +30,7 @@ tests/test_cases/local.properties | ||||
| proguard-project.txt | ||||
| sample_client/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 { | ||||
|         google() | ||||
|         jcenter() | ||||
|         maven { url 'https://jitpack.io' } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|     api 'org.apache.jackrabbit:jackrabbit-webdav:2.12.4' | ||||
|     api 'com.squareup.okhttp3:okhttp:3.10.0' | ||||
|     api 'com.gitlab.derSchabi:dav4android:dev2' | ||||
| } | ||||
| 
 | ||||
| android { | ||||
| @ -52,4 +54,8 @@ android { | ||||
|     lintOptions { | ||||
|         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" | ||||
|           package="com.owncloud.android.lib.sampleclient" | ||||
|           android:versionCode="1" | ||||
|           android:versionName="1.0"> | ||||
| 
 | ||||
|     <uses-permission android:name="android.permission.INTERNET"/> | ||||
|       package="com.owncloud.android.lib.sampleclient" | ||||
|       android:versionCode="1" | ||||
|       android:versionName="1.0"> | ||||
|     <uses-permission android:name="android.permission.INTERNET" /> | ||||
|     <uses-sdk | ||||
|         android:minSdkVersion="14" | ||||
|         android:targetSdkVersion="26"/> | ||||
|     <application | ||||
|         android:icon="@drawable/ic_launcher" | ||||
|         android:label="@string/app_name" | ||||
|         android:theme="@android:style/Theme.Light.NoTitleBar"> | ||||
|         <activity | ||||
|             android:name="MainActivity" | ||||
|             android:configChanges="orientation|keyboardHidden" | ||||
|             android:label="@string/app_name" | ||||
|             android:screenOrientation="portrait" | ||||
|             > | ||||
|     <application android:label="@string/app_name" android:icon="@drawable/ic_launcher"> | ||||
|         <activity 	android:name="MainActivity" | ||||
|                   	android:label="@string/app_name" | ||||
| 					android:screenOrientation="portrait" | ||||
|    					android:configChanges="orientation|keyboardHidden" | ||||
|                   > | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN"/> | ||||
|                 <category android:name="android.intent.category.LAUNCHER"/> | ||||
|                 <action android:name="android.intent.action.MAIN" /> | ||||
|                 <category android:name="android.intent.category.LAUNCHER" /> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
|     </application> | ||||
|  | ||||
| @ -42,4 +42,8 @@ android { | ||||
|     packagingOptions { | ||||
|         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" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="match_parent" | ||||
|     android:layout_width="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 | ||||
|         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_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_below="@id/server_address" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:onClick="onClickHandler" | ||||
|         android:text="@string/refresh"/> | ||||
|         > | ||||
|     </ListView> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/button_upload" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         style="@style/ButtonStyle" | ||||
|         android:layout_alignParentLeft="true" | ||||
|         android:layout_below="@id/button_refresh" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:layout_above="@+id/frame" | ||||
|         android:text="@string/upload" | ||||
|         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 | ||||
|         android:id="@+id/button_download" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_alignParentLeft="true" | ||||
|         android:layout_below="@id/button_upload" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:id="@id/button_delete_remote" | ||||
|         style="@style/ButtonStyle" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:layout_above="@id/frame" | ||||
|         android:text="@string/delete_remote_file" | ||||
|         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 | ||||
|         android:id="@+id/button_delete_remote" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:id="@id/button_download" | ||||
|         style="@style/ButtonStyle" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:layout_alignParentLeft="true" | ||||
|         android:layout_below="@id/button_download" | ||||
|         android:layout_marginTop="10dp" | ||||
|         android:text="@string/download" | ||||
|         android:onClick="onClickHandler" | ||||
|         android:text="@string/delete_remote_file"/> | ||||
|         /> | ||||
| 
 | ||||
|     <!--<ListView--> | ||||
|     <!--android:id="@+id/list_view"--> | ||||
|     <!--android:layout_width="match_parent"--> | ||||
|     <!--android:layout_height="wrap_content"--> | ||||
|     <!--android:layout_alignParentLeft="true"--> | ||||
|     <!--android:layout_alignParentRight="true"--> | ||||
|     <!--android:layout_below="@+id/button_refresh"--> | ||||
|     <!--android:visibility="invisible">--> | ||||
|     <!--</ListView>--> | ||||
|     <TextView | ||||
|         android:id="@+id/download_progress" | ||||
|         style="@style/ProgressStyle" | ||||
|         android:layout_below="@id/frame" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:layout_toRightOf="@id/button_download" | ||||
|         android:layout_toLeftOf="@+id/button_delete_local" | ||||
|         android:gravity="center" | ||||
|         android:textSize="14sp" | ||||
|         android:text="0%" | ||||
|         /> | ||||
| 
 | ||||
|     <!--<TextView--> | ||||
|     <!--android:id="@+id/upload_progress"--> | ||||
|     <!--style="@style/ProgressStyle"--> | ||||
|     <!--android:layout_above="@id/frame"--> | ||||
|     <!--android:layout_below="@id/list_view"--> | ||||
|     <!--android:layout_toLeftOf="@+id/button_delete_remote"--> | ||||
|     <!--android:layout_toRightOf="@id/button_upload"--> | ||||
|     <!--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"/>--> | ||||
|     <Button | ||||
|         android:id="@id/button_delete_local" | ||||
|         style="@style/ButtonStyle" | ||||
|         android:layout_alignParentBottom="true" | ||||
|         android:layout_alignParentRight="true" | ||||
|         android:text="@string/delete_local_file" | ||||
|         android:onClick="onClickHandler" | ||||
|         /> | ||||
| 
 | ||||
| </RelativeLayout> | ||||
| 
 | ||||
|  | ||||
| @ -26,7 +26,6 @@ | ||||
| <resources> | ||||
|     <string name="app_name">ownCloud Sample Client</string> | ||||
|     <string name="refresh">Refresh</string> | ||||
|     <string name="check_server">Check server</string> | ||||
|     <string name="upload">Upload</string> | ||||
|     <string name="delete_remote_file">Delete remote file</string> | ||||
|     <string name="download">Download</string> | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| /* ownCloud Android Library is available under MIT license | ||||
|  *   Copyright (C) 2018 ownCloud GmbH. | ||||
|  * | ||||
|  *   @author David González Verdugo | ||||
|  *   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 | ||||
| @ -26,35 +24,6 @@ | ||||
| 
 | ||||
| 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.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| @ -63,30 +32,35 @@ import java.util.ArrayList; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import okhttp3.Call; | ||||
| import okhttp3.Callback; | ||||
| import okhttp3.Credentials; | ||||
| import okhttp3.Headers; | ||||
| import okhttp3.MediaType; | ||||
| import okhttp3.OkHttpClient; | ||||
| import okhttp3.Request; | ||||
| import okhttp3.RequestBody; | ||||
| import okhttp3.Response; | ||||
| import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; | ||||
| import com.owncloud.android.lib.common.OwnCloudClientFactory; | ||||
| import com.owncloud.android.lib.common.OwnCloudClient; | ||||
| import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory; | ||||
| import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; | ||||
| import com.owncloud.android.lib.resources.files.RemoteFile; | ||||
| 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.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 { | ||||
| 	 | ||||
| 	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; | ||||
| 	 | ||||
| @ -95,10 +69,6 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
| 	private FilesArrayAdapter mFilesAdapter; | ||||
| 	 | ||||
| 	private View mFrame; | ||||
| 
 | ||||
| 	private OkHttpClient mOkHttpClient; | ||||
| 
 | ||||
| 	private String mCredentials; | ||||
| 	 | ||||
|     /** Called when the activity is first created. */ | ||||
|     @Override | ||||
| @ -118,7 +88,7 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
| 		); | ||||
|     	 | ||||
|     	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 | ||||
|     	AssetManager assets = getAssets(); | ||||
| @ -140,14 +110,8 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
| 			Toast.makeText(this, R.string.error_copying_sample_file, Toast.LENGTH_SHORT).show(); | ||||
| 			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)); | ||||
| 
 | ||||
| 		mOkHttpClient = new OkHttpClient(); | ||||
| 
 | ||||
| 		mCredentials = Credentials.basic(getString(R.string.username), getString(R.string.password)); | ||||
| 		 | ||||
| //		mFrame = findViewById(R.id.frame); | ||||
| 		mFrame = findViewById(R.id.frame); | ||||
|     } | ||||
|      | ||||
|      | ||||
| @ -163,264 +127,63 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
|      | ||||
|     public void onClickHandler(View button) { | ||||
|     	switch (button.getId())	{ | ||||
| 			case R.id.button_check_server: | ||||
| 				startCheck(); | ||||
| 				break; | ||||
| 	    	case R.id.button_refresh: | ||||
| 	    		startRefresh(); | ||||
| 	    		break; | ||||
| 	    	case R.id.button_upload: | ||||
| 	    		startUpload(); | ||||
| 	    		break; | ||||
| 			case R.id.button_download: | ||||
| 	    		startDownload(); | ||||
| 	    		break; | ||||
| 	    	case R.id.button_delete_remote: | ||||
| 	    		startRemoteDeletion(); | ||||
| 	    		break; | ||||
| //	    	case R.id.button_delete_local: | ||||
| //	    		startLocalDeletion(); | ||||
| //	    		break; | ||||
| 	    	case R.id.button_download: | ||||
| 	    		startDownload(); | ||||
| 	    		break; | ||||
| 	    	case R.id.button_delete_local: | ||||
| 	    		startLocalDeletion(); | ||||
| 	    		break; | ||||
| 			default: | ||||
| 	    		Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show(); | ||||
|     	} | ||||
|     } | ||||
| 
 | ||||
|     private void startCheck() { | ||||
| 
 | ||||
| 		if (!validServerAddress()) return; | ||||
| 
 | ||||
| 		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 startRefresh() { | ||||
|     	ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR); | ||||
|     	refreshOperation.execute(mClient, this, mHandler); | ||||
|     } | ||||
|      | ||||
|     private void startUpload() { | ||||
| 
 | ||||
|     	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 mimeType = getString(R.string.sample_file_mimetype); | ||||
| 
 | ||||
| 		MediaType mediaType = MediaType.parse(mimeType); | ||||
| 
 | ||||
| 		// Get the last modification date of the file from the file system | ||||
| 		Long timeStampLong = fileToUpload.lastModified()/1000; | ||||
| 		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); | ||||
| //    	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()); | ||||
| 			} | ||||
| 		}); | ||||
|     	UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType, timeStamp); | ||||
|     	uploadOperation.addDatatransferProgressListener(this); | ||||
|     	uploadOperation.execute(mClient, this, mHandler); | ||||
|     } | ||||
| 
 | ||||
| 	private void startDownload() { | ||||
| 		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() { | ||||
|     private void startRemoteDeletion() { | ||||
|     	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(); | ||||
|     	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 | ||||
| //    	RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath); | ||||
| //    	removeOperation.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) | ||||
| 				.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()); | ||||
| 			} | ||||
| 		}); | ||||
|     private void startDownload() { | ||||
|     	File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path)); | ||||
|     	downFolder.mkdir(); | ||||
|     	File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); | ||||
|     	File fileToUpload = upFolder.listFiles()[0]; | ||||
|     	String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); | ||||
|     	DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, downFolder.getAbsolutePath()); | ||||
|     	downloadOperation.addDatatransferProgressListener(this); | ||||
|     	downloadOperation.execute(mClient, this, mHandler); | ||||
|     } | ||||
|      | ||||
|     @SuppressWarnings("deprecation") | ||||
| @ -430,8 +193,8 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
|     	if (!downloadedFile.delete() && downloadedFile.exists()) { | ||||
|     		Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show(); | ||||
|     	} else { | ||||
| //    		((TextView) findViewById(R.id.download_progress)).setText("0%"); | ||||
| //    		findViewById(R.id.frame).setBackgroundDrawable(null); | ||||
|     		((TextView) findViewById(R.id.download_progress)).setText("0%"); | ||||
|     		findViewById(R.id.frame).setBackgroundDrawable(null); | ||||
|     	} | ||||
|     } | ||||
| 
 | ||||
| @ -480,10 +243,10 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
| 
 | ||||
| 	private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) { | ||||
| 		startRefresh(); | ||||
| //		TextView progressView = (TextView) findViewById(R.id.upload_progress); | ||||
| //		if (progressView != null) { | ||||
| //			progressView.setText("0%"); | ||||
| //		} | ||||
| 		TextView progressView = (TextView) findViewById(R.id.upload_progress); | ||||
| 		if (progressView != null) { | ||||
| 			progressView.setText("0%"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	@SuppressWarnings("deprecation") | ||||
| @ -503,11 +266,11 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, | ||||
|             @Override | ||||
|             public void run() { | ||||
| 				TextView progressView = null; | ||||
| //				if (upload) { | ||||
| //					progressView = (TextView) findViewById(R.id.upload_progress); | ||||
| //				} else { | ||||
| //					progressView = (TextView) findViewById(R.id.download_progress); | ||||
| //				} | ||||
| 				if (upload) { | ||||
| 					progressView = (TextView) findViewById(R.id.upload_progress); | ||||
| 				} else { | ||||
| 					progressView = (TextView) findViewById(R.id.download_progress); | ||||
| 				} | ||||
| 				if (progressView != null) { | ||||
| 	    			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 okhttp3.OkHttpClient; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * 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; | ||||
| 
 | ||||
|     /** | ||||
|      * Object to interact with the remote server | ||||
|      */ | ||||
|     private OkHttpClient mHttpClient = null; | ||||
| 
 | ||||
|     /** | ||||
|      * Callback object to notify about the execution of the remote operation | ||||
|      */ | ||||
| @ -142,6 +149,25 @@ public abstract class RemoteOperation implements Runnable { | ||||
|         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 | ||||
|  | ||||
							
								
								
									
										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.utils.Log_OC; | ||||
| 
 | ||||
| import at.bitfire.dav4android.DavResource; | ||||
| 
 | ||||
| /** | ||||
|  * 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; | ||||
| 
 | ||||
|         try { | ||||
| 
 | ||||
|             // remote request | ||||
|             query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath), | ||||
|                 WebdavUtils.getAllPropSet(),    // PropFind Properties | ||||
|  | ||||
| @ -43,4 +43,8 @@ android { | ||||
|     packagingOptions { | ||||
|         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