mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-08 00:16:09 +00:00
Merge pull request #192 from owncloud/replace_network_library
Replace network library
This commit is contained in:
commit
2fdf724eab
@ -14,12 +14,14 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'org.apache.jackrabbit:jackrabbit-webdav:2.12.4'
|
|
||||||
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.51"
|
||||||
|
implementation 'com.gitlab.ownclouders:dav4android:oc_support'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -52,4 +54,8 @@ android {
|
|||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources/>
|
|
@ -34,8 +34,7 @@
|
|||||||
android:targetSdkVersion="26"/>
|
android:targetSdkVersion="26"/>
|
||||||
<application
|
<application
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name">
|
||||||
android:theme="@android:style/Theme.Light.NoTitleBar">
|
|
||||||
<activity
|
<activity
|
||||||
android:name="MainActivity"
|
android:name="MainActivity"
|
||||||
android:configChanges="orientation|keyboardHidden"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
@ -48,4 +47,4 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
@ -42,4 +42,8 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,150 +24,99 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
>
|
>
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/server_address"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_toLeftOf="@+id/button_check_server"
|
|
||||||
android:layout_toStartOf="@+id/button_check_server"
|
|
||||||
android:ems="10"
|
|
||||||
android:hint="Server address (with http or https)"
|
|
||||||
android:inputType="textPersonName"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_check_server"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignBaseline="@+id/server_address"
|
|
||||||
android:layout_alignBottom="@+id/server_address"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:onClick="onClickHandler"
|
|
||||||
android:text="@string/check_server"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_refresh"
|
android:id="@+id/button_refresh"
|
||||||
|
style="@style/ButtonStyle"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:text="@string/refresh"
|
||||||
|
android:onClick="onClickHandler"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/list_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_below="@+id/button_refresh"
|
||||||
|
android:layout_above="@+id/button_upload"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_below="@id/server_address"
|
>
|
||||||
android:layout_marginTop="10dp"
|
</ListView>
|
||||||
android:onClick="onClickHandler"
|
|
||||||
android:text="@string/refresh"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_upload"
|
android:id="@+id/button_upload"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_below="@id/button_refresh"
|
android:layout_above="@+id/frame"
|
||||||
android:layout_marginTop="10dp"
|
android:text="@string/upload"
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/upload"/>
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/upload_progress"
|
||||||
|
style="@style/ProgressStyle"
|
||||||
|
android:layout_below="@id/list_view"
|
||||||
|
android:layout_above="@id/frame"
|
||||||
|
android:layout_toRightOf="@id/button_upload"
|
||||||
|
android:layout_toLeftOf="@+id/button_delete_remote"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="0%"
|
||||||
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_download"
|
android:id="@id/button_delete_remote"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_above="@id/frame"
|
||||||
android:layout_below="@id/button_upload"
|
android:text="@string/delete_remote_file"
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/download"/>
|
/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@id/frame"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/frame_height"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_above="@+id/button_download"
|
||||||
|
>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_delete_remote"
|
android:id="@id/button_download"
|
||||||
android:layout_width="match_parent"
|
style="@style/ButtonStyle"
|
||||||
android:layout_height="wrap_content"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_below="@id/button_download"
|
android:text="@string/download"
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:onClick="onClickHandler"
|
android:onClick="onClickHandler"
|
||||||
android:text="@string/delete_remote_file"/>
|
/>
|
||||||
|
|
||||||
<!--<ListView-->
|
<TextView
|
||||||
<!--android:id="@+id/list_view"-->
|
android:id="@+id/download_progress"
|
||||||
<!--android:layout_width="match_parent"-->
|
style="@style/ProgressStyle"
|
||||||
<!--android:layout_height="wrap_content"-->
|
android:layout_below="@id/frame"
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
android:layout_alignParentBottom="true"
|
||||||
<!--android:layout_alignParentRight="true"-->
|
android:layout_toRightOf="@id/button_download"
|
||||||
<!--android:layout_below="@+id/button_refresh"-->
|
android:layout_toLeftOf="@+id/button_delete_local"
|
||||||
<!--android:visibility="invisible">-->
|
android:gravity="center"
|
||||||
<!--</ListView>-->
|
android:textSize="14sp"
|
||||||
|
android:text="0%"
|
||||||
|
/>
|
||||||
|
|
||||||
<!--<TextView-->
|
<Button
|
||||||
<!--android:id="@+id/upload_progress"-->
|
android:id="@id/button_delete_local"
|
||||||
<!--style="@style/ProgressStyle"-->
|
style="@style/ButtonStyle"
|
||||||
<!--android:layout_above="@id/frame"-->
|
android:layout_alignParentBottom="true"
|
||||||
<!--android:layout_below="@id/list_view"-->
|
android:layout_alignParentRight="true"
|
||||||
<!--android:layout_toLeftOf="@+id/button_delete_remote"-->
|
android:text="@string/delete_local_file"
|
||||||
<!--android:layout_toRightOf="@id/button_upload"-->
|
android:onClick="onClickHandler"
|
||||||
<!--android:enabled="false"-->
|
/>
|
||||||
<!--android:gravity="center"-->
|
|
||||||
<!--android:text="0%"-->
|
|
||||||
<!--android:textSize="14sp"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_delete_remote"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_above="@id/frame"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/delete_remote_file"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<FrameLayout-->
|
|
||||||
<!--android:id="@id/frame"-->
|
|
||||||
<!--android:layout_width="match_parent"-->
|
|
||||||
<!--android:layout_height="@dimen/frame_height"-->
|
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:layout_above="@+id/button_download"-->
|
|
||||||
<!-->-->
|
|
||||||
<!--</FrameLayout>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_download"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_alignParentLeft="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/download"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<TextView-->
|
|
||||||
<!--android:id="@+id/download_progress"-->
|
|
||||||
<!--style="@style/ProgressStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_below="@id/frame"-->
|
|
||||||
<!--android:layout_toLeftOf="@+id/button_delete_local"-->
|
|
||||||
<!--android:layout_toRightOf="@id/button_download"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:gravity="center"-->
|
|
||||||
<!--android:text="0%"-->
|
|
||||||
<!--android:textSize="14sp"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
<!--<Button-->
|
|
||||||
<!--android:id="@id/button_delete_local"-->
|
|
||||||
<!--style="@style/ButtonStyle"-->
|
|
||||||
<!--android:layout_alignParentBottom="true"-->
|
|
||||||
<!--android:layout_alignParentRight="true"-->
|
|
||||||
<!--android:enabled="false"-->
|
|
||||||
<!--android:onClick="onClickHandler"-->
|
|
||||||
<!--android:text="@string/delete_local_file"-->
|
|
||||||
<!--android:visibility="invisible"/>-->
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
@ -1,31 +1,30 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- ownCloud Android Library is available under MIT license
|
<!-- ownCloud Android Library is available under MIT license
|
||||||
Copyright (C) 2016 ownCloud GmbH.
|
Copyright (C) 2018 ownCloud GmbH.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<string name="server_base_url"></string>
|
<string name="server_base_url"></string>
|
||||||
<string name="username"></string>
|
<string name="username"></string>
|
||||||
<string name="password"></string>
|
<string name="password"></string>
|
||||||
<string name ="user_agent">Mozilla/5.0 (Android) ownCloud sample </string>
|
<string name ="user_agent">Mozilla/5.0 (Android) ownCloud sample </string>
|
||||||
</resources>
|
</resources>
|
@ -26,7 +26,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">ownCloud Sample Client</string>
|
<string name="app_name">ownCloud Sample Client</string>
|
||||||
<string name="refresh">Refresh</string>
|
<string name="refresh">Refresh</string>
|
||||||
<string name="check_server">Check server</string>
|
|
||||||
<string name="upload">Upload</string>
|
<string name="upload">Upload</string>
|
||||||
<string name="delete_remote_file">Delete remote file</string>
|
<string name="delete_remote_file">Delete remote file</string>
|
||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
|
||||||
* @author David González Verdugo
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,25 +24,30 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.sampleclient;
|
package com.owncloud.android.lib.sampleclient;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
||||||
|
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||||
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
|
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.files.FileUtils;
|
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||||
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
||||||
@ -52,9 +55,6 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
|
|||||||
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -63,42 +63,16 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import okhttp3.Call;
|
import static android.content.ContentValues.TAG;
|
||||||
import okhttp3.Callback;
|
|
||||||
import okhttp3.Credentials;
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener {
|
public class MainActivity extends Activity implements OnRemoteOperationListener, OnDatatransferProgressListener {
|
||||||
|
|
||||||
private static String LOG_TAG = MainActivity.class.getCanonicalName();
|
private static String LOG_TAG = MainActivity.class.getCanonicalName();
|
||||||
|
|
||||||
private static final String NODE_VERSION = "version";
|
|
||||||
private static final String WEBDAV_PATH_4_0 = "/remote.php/webdav/";
|
|
||||||
private static final String NEW_WEBDAV_PATH = "/remote.php/dav/files/";
|
|
||||||
private static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
|
||||||
private static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
|
||||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
|
||||||
private static final String USER_AGENT_HEADER = "User-Agent";
|
|
||||||
private static final String CONTENT_TYPE_HEADER = "Content-Type";
|
|
||||||
private static final String USER_AGENT_VALUE = "Mozilla/5.0 (Android) ownCloud-android/2.7.0";
|
|
||||||
private static final String CONTENT_TYPE_VALUE = "multipart/form-data";
|
|
||||||
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
private OwnCloudClient mClient;
|
||||||
private OwnCloudClient mClient;
|
|
||||||
|
|
||||||
private FilesArrayAdapter mFilesAdapter;
|
private FilesArrayAdapter mFilesAdapter;
|
||||||
|
|
||||||
private View mFrame;
|
private View mFrame;
|
||||||
|
|
||||||
private OkHttpClient mOkHttpClient;
|
|
||||||
|
|
||||||
private String mCredentials;
|
|
||||||
|
|
||||||
/** Called when the activity is first created. */
|
/** Called when the activity is first created. */
|
||||||
@Override
|
@Override
|
||||||
@ -108,17 +82,20 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
|
|
||||||
Uri serverUri = Uri.parse(getString(R.string.server_base_url));
|
final Uri serverUri = Uri.parse(getString(R.string.server_base_url));
|
||||||
|
|
||||||
|
OwnCloudClientManagerFactory.setUserAgent(getUserAgent());
|
||||||
mClient = OwnCloudClientFactory.createOwnCloudClient(serverUri, this, true);
|
mClient = OwnCloudClientFactory.createOwnCloudClient(serverUri, this, true);
|
||||||
mClient.setCredentials(
|
|
||||||
OwnCloudCredentialsFactory.newBasicCredentials(
|
mClient.setCredentials(
|
||||||
getString(R.string.username),
|
OwnCloudCredentialsFactory.newBasicCredentials(
|
||||||
getString(R.string.password)
|
getString(R.string.username),
|
||||||
|
getString(R.string.password)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list);
|
mFilesAdapter = new FilesArrayAdapter(this, R.layout.file_in_list);
|
||||||
// ((ListView)findViewById(R.id.list_view)).setAdapter(mFilesAdapter);
|
((ListView)findViewById(R.id.list_view)).setAdapter(mFilesAdapter);
|
||||||
|
|
||||||
// TODO move to background thread or task
|
// TODO move to background thread or task
|
||||||
AssetManager assets = getAssets();
|
AssetManager assets = getAssets();
|
||||||
@ -140,14 +117,8 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
Toast.makeText(this, R.string.error_copying_sample_file, Toast.LENGTH_SHORT).show();
|
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);
|
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,275 +134,77 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
public void onClickHandler(View button) {
|
public void onClickHandler(View button) {
|
||||||
switch (button.getId()) {
|
switch (button.getId()) {
|
||||||
case R.id.button_check_server:
|
|
||||||
startCheck();
|
|
||||||
break;
|
|
||||||
case R.id.button_refresh:
|
case R.id.button_refresh:
|
||||||
startRefresh();
|
startRefresh();
|
||||||
break;
|
break;
|
||||||
case R.id.button_upload:
|
case R.id.button_upload:
|
||||||
startUpload();
|
startUpload();
|
||||||
break;
|
break;
|
||||||
case R.id.button_download:
|
|
||||||
startDownload();
|
|
||||||
break;
|
|
||||||
case R.id.button_delete_remote:
|
case R.id.button_delete_remote:
|
||||||
startRemoteDeletion();
|
startRemoteDeletion();
|
||||||
break;
|
break;
|
||||||
// case R.id.button_delete_local:
|
case R.id.button_download:
|
||||||
// startLocalDeletion();
|
startDownload();
|
||||||
// break;
|
break;
|
||||||
|
case R.id.button_delete_local:
|
||||||
|
startLocalDeletion();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.youre_doing_it_wrong, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startCheck() {
|
private void startRefresh() {
|
||||||
|
ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR);
|
||||||
if (!validServerAddress()) return;
|
refreshOperation.execute(mClient, this, mHandler);
|
||||||
|
}
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + "/status.php")
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
}
|
|
||||||
|
|
||||||
try { // Successful response
|
|
||||||
|
|
||||||
String jsonData = response.body().string();
|
|
||||||
|
|
||||||
JSONObject Jobject = new JSONObject(jsonData);
|
|
||||||
|
|
||||||
final String serverVersion = Jobject.get("version").toString();
|
|
||||||
|
|
||||||
showMessage("Server with version " + serverVersion + " detected");
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
Headers responseHeaders = response.headers();
|
|
||||||
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
|
||||||
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, final IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRefresh() {
|
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
|
||||||
|
|
||||||
// ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(FileUtils.PATH_SEPARATOR);
|
|
||||||
// refreshOperation.execute(mClient, this, mHandler);
|
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username))
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.method("PROPFIND", null)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
final String propFindResult = response.body().string();
|
|
||||||
|
|
||||||
showMessage(propFindResult);
|
|
||||||
|
|
||||||
Headers responseHeaders = response.headers();
|
|
||||||
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
|
|
||||||
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startUpload() {
|
private void startUpload() {
|
||||||
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
String mimeType = getString(R.string.sample_file_mimetype);
|
String mimeType = getString(R.string.sample_file_mimetype);
|
||||||
|
|
||||||
MediaType mediaType = MediaType.parse(mimeType);
|
|
||||||
|
|
||||||
// Get the last modification date of the file from the file system
|
// Get the last modification date of the file from the file system
|
||||||
Long timeStampLong = fileToUpload.lastModified()/1000;
|
Long timeStampLong = fileToUpload.lastModified()/1000;
|
||||||
String timeStamp = timeStampLong.toString();
|
String timeStamp = timeStampLong.toString();
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(),
|
||||||
|
remotePath, mimeType, timeStamp);
|
||||||
// UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType, timeStamp);
|
uploadOperation.addDatatransferProgressListener(this);
|
||||||
// uploadOperation.addDatatransferProgressListener(this);
|
uploadOperation.execute(mClient, this, mHandler);
|
||||||
// uploadOperation.execute(mClient, this, mHandler);
|
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
RequestBody requestBody = RequestBody.create(mediaType, fileToUpload);
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username) + remotePath)
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.addHeader(CONTENT_TYPE_HEADER, CONTENT_TYPE_VALUE)
|
|
||||||
.addHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length()))
|
|
||||||
.addHeader(OC_X_OC_MTIME_HEADER, timeStamp)
|
|
||||||
.put(requestBody)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful upload of " + fileToUpload.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startDownload() {
|
private void startRemoteDeletion() {
|
||||||
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
|
||||||
downFolder.mkdir();
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
|
|
||||||
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
// DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath, downFolder.getAbsolutePath());
|
private void startDownload() {
|
||||||
// downloadOperation.addDatatransferProgressListener(this);
|
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
||||||
// downloadOperation.execute(mClient, this, mHandler);
|
downFolder.mkdir();
|
||||||
|
|
||||||
if (!validServerAddress()) return;
|
|
||||||
|
|
||||||
final Request request = new Request.Builder()
|
|
||||||
.url(getString(R.string.server_base_url) + NEW_WEBDAV_PATH + getString(R.string.username) + remotePath)
|
|
||||||
.addHeader(AUTHORIZATION_HEADER, mCredentials)
|
|
||||||
.addHeader(USER_AGENT_HEADER, USER_AGENT_VALUE)
|
|
||||||
.get()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful download of " + fileToUpload.getName() + " although local file " +
|
|
||||||
"won't be created in this stage");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startRemoteDeletion() {
|
|
||||||
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path));
|
||||||
final File fileToUpload = upFolder.listFiles()[0];
|
File fileToUpload = upFolder.listFiles()[0];
|
||||||
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName();
|
||||||
|
|
||||||
// Let's first use OKHttp with the new endpoint without depending on our library operations
|
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remotePath,
|
||||||
// RemoveRemoteFileOperation removeOperation = new RemoveRemoteFileOperation(remotePath);
|
downFolder.getAbsolutePath());
|
||||||
// removeOperation.execute(mClient, this, mHandler);
|
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)
|
|
||||||
.delete()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mOkHttpClient.newCall(request).enqueue(new Callback() {
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, final Response response) throws IOException {
|
|
||||||
|
|
||||||
if (!response.isSuccessful()) {
|
|
||||||
|
|
||||||
showMessage("Response not successful with code: " + response.code());
|
|
||||||
|
|
||||||
throw new IOException("Unexpected code " + response);
|
|
||||||
|
|
||||||
} else { // Successful response
|
|
||||||
|
|
||||||
showMessage("Successful deletion of " + fileToUpload.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
showMessage("Something was wrong: " + e.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private void startLocalDeletion() {
|
private void startLocalDeletion() {
|
||||||
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
||||||
File downloadedFile = downFolder.listFiles()[0];
|
File downloadedFile = downFolder.listFiles()[0];
|
||||||
if (!downloadedFile.delete() && downloadedFile.exists()) {
|
if (!downloadedFile.delete() && downloadedFile.exists()) {
|
||||||
Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.error_deleting_local_file, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
// ((TextView) findViewById(R.id.download_progress)).setText("0%");
|
((TextView) findViewById(R.id.download_progress)).setText("0%");
|
||||||
// findViewById(R.id.frame).setBackgroundDrawable(null);
|
findViewById(R.id.frame).setBackgroundDrawable(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,14 +217,14 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
} else if (operation instanceof ReadRemoteFolderOperation) {
|
} else if (operation instanceof ReadRemoteFolderOperation) {
|
||||||
onSuccessfulRefresh((ReadRemoteFolderOperation)operation, result);
|
onSuccessfulRefresh((ReadRemoteFolderOperation)operation, result);
|
||||||
|
|
||||||
} else if (operation instanceof UploadRemoteFileOperation ) {
|
} else if (operation instanceof com.owncloud.android.lib.resources.files.UploadRemoteFileOperation) {
|
||||||
onSuccessfulUpload((UploadRemoteFileOperation)operation, result);
|
onSuccessfulUpload((com.owncloud.android.lib.resources.files.UploadRemoteFileOperation)operation, result);
|
||||||
|
|
||||||
} else if (operation instanceof RemoveRemoteFileOperation ) {
|
} else if (operation instanceof RemoveRemoteFileOperation ) {
|
||||||
onSuccessfulRemoteDeletion((RemoveRemoteFileOperation)operation, result);
|
onSuccessfulRemoteDeletion((RemoveRemoteFileOperation)operation, result);
|
||||||
|
|
||||||
} else if (operation instanceof DownloadRemoteFileOperation ) {
|
} else if (operation instanceof DownloadRemoteFileOperation ) {
|
||||||
onSuccessfulDownload((DownloadRemoteFileOperation)operation, result);
|
onSuccessfulDownload();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.todo_operation_finished_in_success, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.todo_operation_finished_in_success, Toast.LENGTH_SHORT).show();
|
||||||
@ -460,9 +233,9 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
|
|
||||||
private void onSuccessfulRefresh(ReadRemoteFolderOperation operation, RemoteOperationResult result) {
|
private void onSuccessfulRefresh(ReadRemoteFolderOperation operation, RemoteOperationResult result) {
|
||||||
mFilesAdapter.clear();
|
mFilesAdapter.clear();
|
||||||
List<RemoteFile> files = new ArrayList<RemoteFile>();
|
List<RemoteFile> files = new ArrayList<>();
|
||||||
for(Object obj: result.getData()) {
|
for(RemoteFile remoteFile: (List<RemoteFile>) result.getData()) {
|
||||||
files.add((RemoteFile) obj);
|
files.add(remoteFile);
|
||||||
}
|
}
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
Iterator<RemoteFile> it = files.iterator();
|
Iterator<RemoteFile> it = files.iterator();
|
||||||
@ -474,20 +247,19 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
mFilesAdapter.notifyDataSetChanged();
|
mFilesAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSuccessfulUpload(UploadRemoteFileOperation operation, RemoteOperationResult result) {
|
private void onSuccessfulUpload(com.owncloud.android.lib.resources.files.UploadRemoteFileOperation operation, RemoteOperationResult result) {
|
||||||
startRefresh();
|
startRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) {
|
private void onSuccessfulRemoteDeletion(RemoveRemoteFileOperation operation, RemoteOperationResult result) {
|
||||||
startRefresh();
|
startRefresh();
|
||||||
// TextView progressView = (TextView) findViewById(R.id.upload_progress);
|
TextView progressView = (TextView) findViewById(R.id.upload_progress);
|
||||||
// if (progressView != null) {
|
if (progressView != null) {
|
||||||
// progressView.setText("0%");
|
progressView.setText("0%");
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
private void onSuccessfulDownload() {
|
||||||
private void onSuccessfulDownload(DownloadRemoteFileOperation operation, RemoteOperationResult result) {
|
|
||||||
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
File downFolder = new File(getCacheDir(), getString(R.string.download_folder_path));
|
||||||
File downloadedFile = downFolder.listFiles()[0];
|
File downloadedFile = downFolder.listFiles()[0];
|
||||||
BitmapDrawable bDraw = new BitmapDrawable(getResources(), downloadedFile.getAbsolutePath());
|
BitmapDrawable bDraw = new BitmapDrawable(getResources(), downloadedFile.getAbsolutePath());
|
||||||
@ -503,11 +275,11 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
TextView progressView = null;
|
TextView progressView = null;
|
||||||
// if (upload) {
|
if (upload) {
|
||||||
// progressView = (TextView) findViewById(R.id.upload_progress);
|
progressView = findViewById(R.id.upload_progress);
|
||||||
// } else {
|
} else {
|
||||||
// progressView = (TextView) findViewById(R.id.download_progress);
|
progressView = findViewById(R.id.download_progress);
|
||||||
// }
|
}
|
||||||
if (progressView != null) {
|
if (progressView != null) {
|
||||||
progressView.setText(Long.toString(percentage) + "%");
|
progressView.setText(Long.toString(percentage) + "%");
|
||||||
}
|
}
|
||||||
@ -515,32 +287,24 @@ public class MainActivity extends Activity implements OnRemoteOperationListener,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validServerAddress() {
|
// user agent
|
||||||
|
@SuppressLint("StringFormatInvalid")
|
||||||
|
private String getUserAgent() {
|
||||||
|
String appString = getResources().getString(R.string.user_agent);
|
||||||
|
String packageName = getPackageName();
|
||||||
|
String version = "";
|
||||||
|
|
||||||
String serverAddress = ((TextView) findViewById(R.id.server_address)).getText().toString();
|
PackageInfo pInfo;
|
||||||
|
try {
|
||||||
if (serverAddress.equals("") || (!serverAddress.contains("http://") && !serverAddress.contains("https://"))) {
|
pInfo = getPackageManager().getPackageInfo(packageName, 0);
|
||||||
showToastMessage("Introduce a proper server address with http/https");
|
if (pInfo != null) {
|
||||||
return false;
|
version = pInfo.versionName;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMessage(final String message) {
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
showToastMessage(message);
|
|
||||||
}
|
}
|
||||||
});
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log_OC.e(TAG, "Trying to get packageName", e.getCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mozilla/5.0 (Android) ownCloud-android/1.7.0
|
||||||
|
return String.format(appString, version);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private void showToastMessage(String message) {
|
|
||||||
Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
|
|
||||||
|
|
||||||
toast.setGravity(Gravity.CENTER, 0, 0);
|
|
||||||
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,3 @@
|
|||||||
include ':'
|
include ':'
|
||||||
include ':sample_client'
|
include ':sample_client'
|
||||||
include ':test_client'
|
include ':test_client'
|
@ -56,11 +56,8 @@ public class DynamicSessionManager implements OwnCloudClientManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAllClients(Context context, String accountType)
|
public void saveAllClients(Context context, String accountType) {
|
||||||
throws AccountUtils.AccountNotFoundException,
|
|
||||||
AuthenticatorException, IOException, OperationCanceledException {
|
|
||||||
mSimpleFactoryManager.saveAllClients(context, accountType);
|
mSimpleFactoryManager.saveAllClients(context, accountType);
|
||||||
mSingleSessionManager.saveAllClients(context, accountType);
|
mSingleSessionManager.saveAllClients(context, accountType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -116,9 +116,8 @@ public class OwnCloudAccount {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws OperationCanceledException
|
* @throws OperationCanceledException
|
||||||
*/
|
*/
|
||||||
public void loadCredentials(Context context)
|
public void loadCredentials(Context context) throws AuthenticatorException,
|
||||||
throws AccountNotFoundException, AuthenticatorException,
|
IOException, OperationCanceledException {
|
||||||
IOException, OperationCanceledException {
|
|
||||||
|
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
throw new IllegalArgumentException("Parameter 'context' cannot be null");
|
throw new IllegalArgumentException("Parameter 'context' cannot be null");
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2017 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
* Copyright (C) 2012 Bartek Przybylski
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -25,64 +25,51 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common;
|
package com.owncloud.android.lib.common;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Cookie;
|
|
||||||
import org.apache.commons.httpclient.Header;
|
|
||||||
import org.apache.commons.httpclient.HostConfiguration;
|
|
||||||
import org.apache.commons.httpclient.HttpClient;
|
|
||||||
import org.apache.commons.httpclient.HttpConnectionManager;
|
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
|
||||||
import org.apache.commons.httpclient.HttpMethodBase;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.HttpVersion;
|
|
||||||
import org.apache.commons.httpclient.URI;
|
|
||||||
import org.apache.commons.httpclient.URIException;
|
|
||||||
import org.apache.commons.httpclient.cookie.CookiePolicy;
|
|
||||||
import org.apache.commons.httpclient.params.HttpMethodParams;
|
|
||||||
import org.apache.commons.httpclient.params.HttpParams;
|
|
||||||
|
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.accounts.AccountsException;
|
import android.accounts.AccountsException;
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials;
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
import com.owncloud.android.lib.common.network.RedirectionPath;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
import com.owncloud.android.lib.common.utils.RandomUtils;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID;
|
||||||
|
|
||||||
public class OwnCloudClient extends HttpClient {
|
public class OwnCloudClient extends HttpClient {
|
||||||
|
|
||||||
public static final String WEBDAV_PATH_4_0 = "/remote.php/webdav";
|
public static final String NEW_WEBDAV_FILES_PATH_4_0 = "/remote.php/dav/files/";
|
||||||
|
public static final String NEW_WEBDAV_UPLOADS_PATH_4_0 = "/remote.php/dav/uploads/";
|
||||||
public static final String STATUS_PATH = "/status.php";
|
public static final String STATUS_PATH = "/status.php";
|
||||||
public static final String FILES_WEB_PATH = "/index.php/apps/files";
|
public static final String FILES_WEB_PATH = "/index.php/apps/files";
|
||||||
|
|
||||||
private static final String TAG = OwnCloudClient.class.getSimpleName();
|
private static final String TAG = OwnCloudClient.class.getSimpleName();
|
||||||
private static final int MAX_REDIRECTIONS_COUNT = 3;
|
private static final int MAX_REDIRECTIONS_COUNT = 3;
|
||||||
private static final int MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS = 1;
|
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 static final String PARAM_PROTOCOL_VERSION = "http.protocol.version";
|
||||||
|
|
||||||
private static byte[] sExhaustBuffer = new byte[1024];
|
private static byte[] sExhaustBuffer = new byte[1024];
|
||||||
|
|
||||||
private static int sIntanceCounter = 0;
|
private static int sIntanceCounter = 0;
|
||||||
private boolean mFollowRedirects = true;
|
|
||||||
private OwnCloudCredentials mCredentials = null;
|
private OwnCloudCredentials mCredentials = null;
|
||||||
private int mInstanceNumber = 0;
|
private int mInstanceNumber = 0;
|
||||||
|
|
||||||
private Uri mBaseUri;
|
private Uri mBaseUri;
|
||||||
|
|
||||||
private OwnCloudVersion mVersion = null;
|
private OwnCloudVersion mVersion = null;
|
||||||
|
|
||||||
/// next too attributes are a very ugly dependency, added to grant silent retry of OAuth token when needed ;
|
|
||||||
/// see #shouldInvalidateCredentials and #invalidateCredentials for more details
|
|
||||||
private Context mContext;
|
|
||||||
private OwnCloudAccount mAccount;
|
private OwnCloudAccount mAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,20 +78,11 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
*/
|
*/
|
||||||
private OwnCloudClientManager mOwnCloudClientManager = null;
|
private OwnCloudClientManager mOwnCloudClientManager = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* When 'true', the method {@link #executeMethod(HttpMethod)} tries to silently refresh credentials
|
|
||||||
* if fails due to lack of authorization, if credentials support authorization refresh.
|
|
||||||
*/
|
|
||||||
private boolean mSilentRefreshOfAccountCredentials = true;
|
|
||||||
|
|
||||||
private String mRedirectedLocation;
|
private String mRedirectedLocation;
|
||||||
|
private boolean mFollowRedirects;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public OwnCloudClient(Uri baseUri, HttpConnectionManager connectionMgr) {
|
|
||||||
super(connectionMgr);
|
|
||||||
|
|
||||||
|
public OwnCloudClient(Uri baseUri) {
|
||||||
if (baseUri == null) {
|
if (baseUri == null) {
|
||||||
throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
|
throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
|
||||||
}
|
}
|
||||||
@ -113,45 +91,10 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
mInstanceNumber = sIntanceCounter++;
|
mInstanceNumber = sIntanceCounter++;
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
|
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");
|
||||||
|
|
||||||
String userAgent = OwnCloudClientManagerFactory.getUserAgent();
|
|
||||||
getParams().setParameter(HttpMethodParams.USER_AGENT, userAgent);
|
|
||||||
getParams().setParameter(
|
|
||||||
PARAM_PROTOCOL_VERSION,
|
|
||||||
HttpVersion.HTTP_1_1
|
|
||||||
);
|
|
||||||
|
|
||||||
getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
|
|
||||||
getParams().setParameter(
|
|
||||||
PARAM_SINGLE_COOKIE_HEADER, // to avoid problems with some web servers
|
|
||||||
PARAM_SINGLE_COOKIE_HEADER_VALUE
|
|
||||||
);
|
|
||||||
|
|
||||||
applyProxySettings();
|
|
||||||
|
|
||||||
clearCredentials();
|
clearCredentials();
|
||||||
|
clearCookies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void applyProxySettings() {
|
|
||||||
String proxyHost = System.getProperty("http.proxyHost");
|
|
||||||
String proxyPortSt = System.getProperty("http.proxyPort");
|
|
||||||
int proxyPort = 0;
|
|
||||||
try {
|
|
||||||
if (proxyPortSt != null && proxyPortSt.length() > 0) {
|
|
||||||
proxyPort = Integer.parseInt(proxyPortSt);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log_OC.w(TAG, "Proxy port could not be read, keeping default value " + proxyPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proxyHost != null && proxyHost.length() > 0) {
|
|
||||||
HostConfiguration hostCfg = getHostConfiguration();
|
|
||||||
hostCfg.setProxy(proxyHost, proxyPort);
|
|
||||||
Log_OC.d(TAG, "Proxy settings: " + proxyHost + ":" + proxyPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setCredentials(OwnCloudCredentials credentials) {
|
public void setCredentials(OwnCloudCredentials credentials) {
|
||||||
if (credentials != null) {
|
if (credentials != null) {
|
||||||
mCredentials = credentials;
|
mCredentials = credentials;
|
||||||
@ -168,74 +111,28 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
mCredentials.applyTo(this);
|
mCredentials.applyTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void applyCredentials() {
|
||||||
* Requests the received method with the received timeout (milliseconds).
|
mCredentials.applyTo(this);
|
||||||
*
|
|
||||||
* Executes the method through the inherited HttpClient.executedMethod(method).
|
|
||||||
*
|
|
||||||
* Sets the socket and connection timeouts only for the method received.
|
|
||||||
*
|
|
||||||
* The timeouts are both in milliseconds; 0 means 'infinite';
|
|
||||||
* < 0 means 'do not change the default'
|
|
||||||
*
|
|
||||||
* @param method HTTP method request.
|
|
||||||
* @param readTimeout Timeout to set for data reception
|
|
||||||
* @param connectionTimeout Timeout to set for connection establishment
|
|
||||||
*/
|
|
||||||
public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws IOException {
|
|
||||||
|
|
||||||
int oldSoTimeout = getParams().getSoTimeout();
|
|
||||||
int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
|
|
||||||
try {
|
|
||||||
if (readTimeout >= 0) {
|
|
||||||
method.getParams().setSoTimeout(readTimeout); // this should be enough...
|
|
||||||
getParams().setSoTimeout(readTimeout); // ... but HTTPS needs this
|
|
||||||
}
|
|
||||||
if (connectionTimeout >= 0) {
|
|
||||||
getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);
|
|
||||||
}
|
|
||||||
return executeMethod(method);
|
|
||||||
} finally {
|
|
||||||
getParams().setSoTimeout(oldSoTimeout);
|
|
||||||
getHttpConnectionManager().getParams().setConnectionTimeout(oldConnectionTimeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int executeHttpMethod (HttpBaseMethod method) throws Exception {
|
||||||
/**
|
|
||||||
* Requests the received method.
|
|
||||||
*
|
|
||||||
* Executes the method through the inherited HttpClient.executedMethod(method).
|
|
||||||
*
|
|
||||||
* @param method HTTP method request.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int executeMethod(HttpMethod method) throws IOException {
|
|
||||||
|
|
||||||
boolean repeatWithFreshCredentials;
|
boolean repeatWithFreshCredentials;
|
||||||
int repeatCounter = 0;
|
int repeatCounter = 0;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Update User Agent
|
// Clean previous request id. This is a bit hacky but is the only way to add request headers in WebDAV
|
||||||
HttpParams params = method.getParams();
|
// methods by using Dav4Android
|
||||||
String userAgent = OwnCloudClientManagerFactory.getUserAgent();
|
deleteHeaderForAllRequests(OC_X_REQUEST_ID);
|
||||||
params.setParameter(HttpMethodParams.USER_AGENT, userAgent);
|
|
||||||
|
|
||||||
preventCrashDueToInvalidPort(method);
|
// Header to allow tracing requests in apache and ownCloud logs
|
||||||
|
addHeaderForAllRequests(OC_X_REQUEST_ID,
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "REQUEST " +
|
RandomUtils.generateRandomString(RandomUtils.generateRandomInteger(20, 200)));
|
||||||
method.getName() + " " + method.getPath());
|
|
||||||
|
|
||||||
//logCookiesAtRequest(method.getRequestHeaders(), "before");
|
|
||||||
//logCookiesAtState("before");
|
|
||||||
method.setFollowRedirects(false);
|
|
||||||
|
|
||||||
status = super.executeMethod(method);
|
|
||||||
|
|
||||||
|
status = method.execute();
|
||||||
checkFirstRedirection(method);
|
checkFirstRedirection(method);
|
||||||
|
if(mFollowRedirects && !isIdPRedirection()) {
|
||||||
if (mFollowRedirects) {
|
|
||||||
status = followRedirection(method).getLastStatus();
|
status = followRedirection(method).getLastStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,109 +140,90 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
if (repeatWithFreshCredentials) {
|
if (repeatWithFreshCredentials) {
|
||||||
repeatCounter++;
|
repeatCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (repeatWithFreshCredentials);
|
} while (repeatWithFreshCredentials);
|
||||||
|
|
||||||
//logCookiesAtRequest(method.getRequestHeaders(), "after");
|
|
||||||
//logCookiesAtState("after");
|
|
||||||
//logSetCookiesAtResponse(method.getResponseHeaders());
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkFirstRedirection(HttpMethod method) {
|
private void checkFirstRedirection(HttpBaseMethod method) {
|
||||||
Header[] httpHeaders = method.getResponseHeaders();
|
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||||
|
if(location != null && !location.isEmpty()) {
|
||||||
|
mRedirectedLocation = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Header httpHeader : httpHeaders) {
|
private int executeRedirectedHttpMethod (HttpBaseMethod method) throws Exception {
|
||||||
|
boolean repeatWithFreshCredentials;
|
||||||
|
int repeatCounter = 0;
|
||||||
|
int status;
|
||||||
|
|
||||||
if ("location".equals(httpHeader.getName().toLowerCase())) {
|
do {
|
||||||
mRedirectedLocation = httpHeader.getValue();
|
status = method.execute();
|
||||||
break;
|
|
||||||
|
repeatWithFreshCredentials = checkUnauthorizedAccess(status, repeatCounter);
|
||||||
|
if (repeatWithFreshCredentials) {
|
||||||
|
repeatCounter++;
|
||||||
}
|
}
|
||||||
}
|
} while (repeatWithFreshCredentials);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public RedirectionPath followRedirection(HttpBaseMethod method) throws Exception {
|
||||||
* Fix for https://github.com/owncloud/android/issues/1847#issuecomment-267558274
|
|
||||||
*
|
|
||||||
* The problem: default SocketFactory in HTTPClient 3.x for HTTP connections creates a separate thread
|
|
||||||
* to create the socket. When a port out of TCP bounds is passed, an exception is thrown in that
|
|
||||||
* separate thread, and our original thread is not able to catch it. This is not happenning with HTTPS
|
|
||||||
* connections because we had to define our own socket factory,
|
|
||||||
* {@link com.owncloud.android.lib.common.network.AdvancedSslSocketFactory}, and it does not mess with
|
|
||||||
* threads.
|
|
||||||
*
|
|
||||||
* The solution: validate the input (the port number) ourselves before let the work to HTTPClient 3.x.
|
|
||||||
*
|
|
||||||
* @param method HTTP method to run.
|
|
||||||
* @throws IllegalArgumentException If 'method' targets an invalid port in an HTTP URI.
|
|
||||||
* @throws URIException If the URI to the target server cannot be built.
|
|
||||||
*/
|
|
||||||
private void preventCrashDueToInvalidPort(HttpMethod method) throws URIException {
|
|
||||||
int port = method.getURI().getPort();
|
|
||||||
String scheme = method.getURI().getScheme().toLowerCase();
|
|
||||||
if ("http".equals(scheme) && port > 0xFFFF) {
|
|
||||||
// < 0 is not tested because -1 is used when no port number is specified in the URL;
|
|
||||||
// no problem, the network library will convert that in the default HTTP port
|
|
||||||
throw new IllegalArgumentException("Invalid port number " + port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public RedirectionPath followRedirection(HttpMethod method) throws IOException {
|
|
||||||
int redirectionsCount = 0;
|
int redirectionsCount = 0;
|
||||||
int status = method.getStatusCode();
|
int status = method.getStatusCode();
|
||||||
RedirectionPath result = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT);
|
RedirectionPath redirectionPath = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT);
|
||||||
|
|
||||||
while (redirectionsCount < MAX_REDIRECTIONS_COUNT &&
|
while (redirectionsCount < MAX_REDIRECTIONS_COUNT &&
|
||||||
(status == HttpStatus.SC_MOVED_PERMANENTLY ||
|
(status == HttpConstants.HTTP_MOVED_PERMANENTLY ||
|
||||||
status == HttpStatus.SC_MOVED_TEMPORARILY ||
|
status == HttpConstants.HTTP_MOVED_TEMPORARILY ||
|
||||||
status == HttpStatus.SC_TEMPORARY_REDIRECT)
|
status == HttpConstants.HTTP_TEMPORARY_REDIRECT)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null
|
||||||
|
? method.getResponseHeader(HttpConstants.LOCATION_HEADER)
|
||||||
|
: method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER);
|
||||||
|
|
||||||
Header location = method.getResponseHeader("Location");
|
|
||||||
if (location == null) {
|
|
||||||
location = method.getResponseHeader("location");
|
|
||||||
}
|
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
String locationStr = location.getValue();
|
|
||||||
|
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||||
"Location to redirect: " + locationStr);
|
"Location to redirect: " + location);
|
||||||
|
|
||||||
result.addLocation(locationStr);
|
redirectionPath.addLocation(location);
|
||||||
|
|
||||||
// Release the connection to avoid reach the max number of connections per host
|
// Release the connection to avoid reach the max number of connections per host
|
||||||
// due to it will be set a different url
|
// due to it will be set a different url
|
||||||
exhaustResponse(method.getResponseBodyAsStream());
|
exhaustResponse(method.getResponseBodyAsStream());
|
||||||
method.releaseConnection();
|
|
||||||
|
|
||||||
method.setURI(new URI(locationStr, true));
|
method.setUrl(HttpUrl.parse(location));
|
||||||
Header destination = method.getRequestHeader("Destination");
|
final String destination = method.getRequestHeader("Destination") != null
|
||||||
if (destination == null) {
|
? method.getRequestHeader("Destination")
|
||||||
destination = method.getRequestHeader("destination");
|
: method.getRequestHeader("destination");
|
||||||
}
|
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
int suffixIndex = locationStr.lastIndexOf(WEBDAV_PATH_4_0);
|
final int suffixIndex = location.lastIndexOf(getNewFilesWebDavUri().toString());
|
||||||
String redirectionBase = locationStr.substring(0, suffixIndex);
|
final String redirectionBase = location.substring(0, suffixIndex);
|
||||||
|
final String destinationPath = destination.substring(mBaseUri.toString().length());
|
||||||
|
|
||||||
String destinationStr = destination.getValue();
|
method.setRequestHeader("destination", redirectionBase + destinationPath);
|
||||||
String destinationPath = destinationStr.substring(mBaseUri.toString().length());
|
|
||||||
String redirectedDestination = redirectionBase + destinationPath;
|
|
||||||
|
|
||||||
destination.setValue(redirectedDestination);
|
|
||||||
method.setRequestHeader(destination);
|
|
||||||
}
|
}
|
||||||
status = super.executeMethod(method);
|
try {
|
||||||
result.addStatus(status);
|
status = executeRedirectedHttpMethod(method);
|
||||||
|
} catch (HttpException e) {
|
||||||
|
if(e.getMessage().contains(Integer.toString(HttpConstants.HTTP_MOVED_TEMPORARILY))) {
|
||||||
|
status = HttpConstants.HTTP_MOVED_TEMPORARILY;
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redirectionPath.addStatus(status);
|
||||||
redirectionsCount++;
|
redirectionsCount++;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No location to redirect!");
|
Log_OC.d(TAG + " #" + mInstanceNumber, "No location to redirect!");
|
||||||
status = HttpStatus.SC_NOT_FOUND;
|
status = HttpConstants.HTTP_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return redirectionPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -361,26 +239,21 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
|
|
||||||
} catch (IOException io) {
|
} catch (IOException io) {
|
||||||
Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response;" +
|
Log_OC.e(TAG, "Unexpected exception while exhausting not interesting HTTP response;" +
|
||||||
" will be IGNORED", io);
|
" will be IGNORED", io);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Uri getNewFilesWebDavUri() {
|
||||||
* Sets the connection and wait-for-data timeouts to be applied by default to the methods
|
return mCredentials instanceof OwnCloudAnonymousCredentials
|
||||||
* performed by this client.
|
? Uri.parse(mBaseUri + NEW_WEBDAV_FILES_PATH_4_0)
|
||||||
*/
|
: Uri.parse(mBaseUri + NEW_WEBDAV_FILES_PATH_4_0 + mCredentials.getUsername());
|
||||||
public void setDefaultTimeouts(int defaultDataTimeout, int defaultConnectionTimeout) {
|
|
||||||
if (defaultDataTimeout >= 0) {
|
|
||||||
getParams().setSoTimeout(defaultDataTimeout);
|
|
||||||
}
|
|
||||||
if (defaultConnectionTimeout >= 0) {
|
|
||||||
getHttpConnectionManager().getParams().setConnectionTimeout(defaultConnectionTimeout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri getWebdavUri() {
|
public Uri getNewUploadsWebDavUri() {
|
||||||
return Uri.parse(mBaseUri + WEBDAV_PATH_4_0);
|
return mCredentials instanceof OwnCloudAnonymousCredentials
|
||||||
|
? Uri.parse(mBaseUri + NEW_WEBDAV_UPLOADS_PATH_4_0)
|
||||||
|
: Uri.parse(mBaseUri + NEW_WEBDAV_UPLOADS_PATH_4_0 + mCredentials.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -405,52 +278,32 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
return mCredentials;
|
return mCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFollowRedirects(boolean followRedirects) {
|
private void logCookie(Cookie cookie) {
|
||||||
mFollowRedirects = followRedirects;
|
Log_OC.d(TAG, "Cookie name: " + cookie.name());
|
||||||
|
Log_OC.d(TAG, " value: " + cookie.value());
|
||||||
|
Log_OC.d(TAG, " domain: " + cookie.domain());
|
||||||
|
Log_OC.d(TAG, " path: " + cookie.path());
|
||||||
|
Log_OC.d(TAG, " expiryDate: " + cookie.expiresAt());
|
||||||
|
Log_OC.d(TAG, " secure: " + cookie.secure());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getFollowRedirects() {
|
private void logCookiesAtRequest(Headers headers, String when) {
|
||||||
return mFollowRedirects;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logCookiesAtRequest(Header[] headers, String when) {
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (final String cookieHeader : headers.toMultimap().get("cookie")) {
|
||||||
if (headers[i].getName().toLowerCase().equals("cookie")) {
|
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
"Cookies at request (" + when + ") (" + counter++ + "): "
|
||||||
"Cookies at request (" + when + ") (" + counter++ + "): " +
|
+ cookieHeader);
|
||||||
headers[i].getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (counter == 0) {
|
if (counter == 0) {
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No cookie at request before");
|
Log_OC.d(TAG + " #" + mInstanceNumber, "No cookie at request before");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logCookiesAtState(String string) {
|
private void logSetCookiesAtResponse(Headers headers) {
|
||||||
Cookie[] cookies = getState().getCookies();
|
|
||||||
if (cookies.length == 0) {
|
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No cookie at STATE before");
|
|
||||||
} else {
|
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "Cookies at STATE (before)");
|
|
||||||
for (int i = 0; i < cookies.length; i++) {
|
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, " (" + i + "):" +
|
|
||||||
"\n name: " + cookies[i].getName() +
|
|
||||||
"\n value: " + cookies[i].getValue() +
|
|
||||||
"\n domain: " + cookies[i].getDomain() +
|
|
||||||
"\n path: " + cookies[i].getPath()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logSetCookiesAtResponse(Header[] headers) {
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (int i = 0; i < headers.length; i++) {
|
for (final String cookieHeader : headers.toMultimap().get("set-cookie")) {
|
||||||
if (headers[i].getName().toLowerCase().equals("set-cookie")) {
|
Log_OC.d(TAG + " #" + mInstanceNumber,
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber,
|
"Set-Cookie (" + counter++ + "): " + cookieHeader);
|
||||||
"Set-Cookie (" + counter++ + "): " + headers[i].getValue());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (counter == 0) {
|
if (counter == 0) {
|
||||||
Log_OC.d(TAG + " #" + mInstanceNumber, "No set-cookie");
|
Log_OC.d(TAG + " #" + mInstanceNumber, "No set-cookie");
|
||||||
@ -458,39 +311,25 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getCookiesString() {
|
public String getCookiesString() {
|
||||||
Cookie[] cookies = getState().getCookies();
|
|
||||||
String cookiesString = "";
|
String cookiesString = "";
|
||||||
for (Cookie cookie : cookies) {
|
List<Cookie> cookieList = getCookiesFromUrl(HttpUrl.parse(mBaseUri.toString()));
|
||||||
cookiesString = cookiesString + cookie.toString() + ";";
|
|
||||||
|
|
||||||
// logCookie(cookie);
|
if (cookieList != null) {
|
||||||
|
for (Cookie cookie : cookieList) {
|
||||||
|
cookiesString += cookie.toString() + ";";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cookiesString;
|
return cookiesString;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getConnectionTimeout() {
|
public void setCookiesForCurrentAccount(List<Cookie> cookies) {
|
||||||
return getHttpConnectionManager().getParams().getConnectionTimeout();
|
getOkHttpClient().cookieJar().saveFromResponse(
|
||||||
|
HttpUrl.parse(getAccount().getBaseUri().toString()),
|
||||||
|
cookies
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDataTimeout() {
|
|
||||||
return getParams().getSoTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logCookie(Cookie cookie) {
|
|
||||||
Log_OC.d(TAG, "Cookie name: " + cookie.getName());
|
|
||||||
Log_OC.d(TAG, " value: " + cookie.getValue());
|
|
||||||
Log_OC.d(TAG, " domain: " + cookie.getDomain());
|
|
||||||
Log_OC.d(TAG, " path: " + cookie.getPath());
|
|
||||||
Log_OC.d(TAG, " version: " + cookie.getVersion());
|
|
||||||
Log_OC.d(TAG, " expiryDate: " +
|
|
||||||
(cookie.getExpiryDate() != null ? cookie.getExpiryDate().toString() : "--"));
|
|
||||||
Log_OC.d(TAG, " comment: " + cookie.getComment());
|
|
||||||
Log_OC.d(TAG, " secure: " + cookie.getSecure());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setOwnCloudVersion(OwnCloudVersion version) {
|
public void setOwnCloudVersion(OwnCloudVersion version) {
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
}
|
}
|
||||||
@ -499,14 +338,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
return mVersion;
|
return mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(Context context) {
|
|
||||||
this.mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context getContext() {
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAccount(OwnCloudAccount account) {
|
public void setAccount(OwnCloudAccount account) {
|
||||||
this.mAccount = account;
|
this.mAccount = account;
|
||||||
}
|
}
|
||||||
@ -515,18 +346,6 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
return mAccount;
|
return mAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables silent refresh of credentials, if supported by credentials themselves.
|
|
||||||
*/
|
|
||||||
public void setSilentRefreshOfAccountCredentials(boolean silentRefreshOfAccountCredentials) {
|
|
||||||
mSilentRefreshOfAccountCredentials = silentRefreshOfAccountCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getSilentRefreshOfAccountCredentials() {
|
|
||||||
return mSilentRefreshOfAccountCredentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the status code of an execution and decides if should be repeated with fresh credentials.
|
* Checks the status code of an execution and decides if should be repeated with fresh credentials.
|
||||||
*
|
*
|
||||||
@ -546,19 +365,19 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
|
|
||||||
if (invalidated) {
|
if (invalidated) {
|
||||||
if (getCredentials().authTokenCanBeRefreshed() &&
|
if (getCredentials().authTokenCanBeRefreshed() &&
|
||||||
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
repeatCounter < MAX_REPEAT_COUNT_WITH_FRESH_CREDENTIALS) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mAccount.loadCredentials(mContext);
|
mAccount.loadCredentials(getContext());
|
||||||
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
// if mAccount.getCredentials().length() == 0 --> refresh failed
|
||||||
setCredentials(mAccount.getCredentials());
|
setCredentials(mAccount.getCredentials());
|
||||||
credentialsWereRefreshed = true;
|
credentialsWereRefreshed = true;
|
||||||
|
|
||||||
} catch (AccountsException | IOException e) {
|
} catch (AccountsException | IOException e) {
|
||||||
Log_OC.e(
|
Log_OC.e(
|
||||||
TAG,
|
TAG,
|
||||||
"Error while trying to refresh auth token for " + mAccount.getSavedAccount().name,
|
"Error while trying to refresh auth token for " + mAccount.getSavedAccount().name,
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,7 +388,7 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
mOwnCloudClientManager.removeClientFor(mAccount);
|
mOwnCloudClientManager.removeClientFor(mAccount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else: execute will finish with status 401
|
// else: onExecute will finish with status 401
|
||||||
}
|
}
|
||||||
|
|
||||||
return credentialsWereRefreshed;
|
return credentialsWereRefreshed;
|
||||||
@ -586,13 +405,13 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
*/
|
*/
|
||||||
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
private boolean shouldInvalidateAccountCredentials(int httpStatusCode) {
|
||||||
|
|
||||||
boolean should = (httpStatusCode == HttpStatus.SC_UNAUTHORIZED || isIdPRedirection()); // invalid credentials
|
boolean should = (httpStatusCode == HttpConstants.HTTP_UNAUTHORIZED || isIdPRedirection()); // invalid credentials
|
||||||
|
|
||||||
should &= (mCredentials != null && // real credentials
|
should &= (mCredentials != null && // real credentials
|
||||||
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
!(mCredentials instanceof OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials));
|
||||||
|
|
||||||
// test if have all the needed to effectively invalidate ...
|
// test if have all the needed to effectively invalidate ...
|
||||||
should &= (mAccount != null && mAccount.getSavedAccount() != null && mContext != null);
|
should &= (mAccount != null && mAccount.getSavedAccount() != null && getContext() != null);
|
||||||
|
|
||||||
return should;
|
return should;
|
||||||
}
|
}
|
||||||
@ -606,10 +425,10 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
* @return 'True' if invalidation was successful, 'false' otherwise.
|
* @return 'True' if invalidation was successful, 'false' otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean invalidateAccountCredentials() {
|
private boolean invalidateAccountCredentials() {
|
||||||
AccountManager am = AccountManager.get(mContext);
|
AccountManager am = AccountManager.get(getContext());
|
||||||
am.invalidateAuthToken(
|
am.invalidateAuthToken(
|
||||||
mAccount.getSavedAccount().type,
|
mAccount.getSavedAccount().type,
|
||||||
mCredentials.getAuthToken()
|
mCredentials.getAuthToken()
|
||||||
);
|
);
|
||||||
am.clearPassword(mAccount.getSavedAccount()); // being strict, only needed for Basic Auth credentials
|
am.clearPassword(mAccount.getSavedAccount()); // being strict, only needed for Basic Auth credentials
|
||||||
return true;
|
return true;
|
||||||
@ -632,4 +451,12 @@ public class OwnCloudClient extends HttpClient {
|
|||||||
(mRedirectedLocation.toUpperCase().contains("SAML") ||
|
(mRedirectedLocation.toUpperCase().contains("SAML") ||
|
||||||
mRedirectedLocation.toLowerCase().contains("wayf")));
|
mRedirectedLocation.toLowerCase().contains("wayf")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public boolean followRedirects() {
|
||||||
|
return mFollowRedirects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowRedirects(boolean followRedirects) {
|
||||||
|
this.mFollowRedirects = followRedirects;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,9 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common;
|
package com.owncloud.android.lib.common;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.accounts.AccountManagerFuture;
|
import android.accounts.AccountManagerFuture;
|
||||||
@ -40,21 +37,14 @@ import android.os.Bundle;
|
|||||||
import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
|
import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
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 com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class OwnCloudClientFactory {
|
public class OwnCloudClientFactory {
|
||||||
|
|
||||||
final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
|
final private static String TAG = OwnCloudClientFactory.class.getSimpleName();
|
||||||
|
|
||||||
/** Default timeout for waiting data from the server */
|
|
||||||
public static final int DEFAULT_DATA_TIMEOUT = 60000;
|
|
||||||
|
|
||||||
/** Default timeout for establishing a connection */
|
|
||||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a OwnCloudClient setup for an ownCloud account
|
* Creates a OwnCloudClient setup for an ownCloud account
|
||||||
@ -122,9 +112,6 @@ public class OwnCloudClientFactory {
|
|||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//String password = am.getPassword(account);
|
|
||||||
//String password = am.blockingGetAuthToken(account, MainApp.getAuthTokenTypePass(),
|
|
||||||
// false);
|
|
||||||
AccountManagerFuture<Bundle> future = am.getAuthToken(
|
AccountManagerFuture<Bundle> future = am.getAuthToken(
|
||||||
account,
|
account,
|
||||||
AccountTypeUtils.getAuthTokenTypePass(account.type),
|
AccountTypeUtils.getAuthTokenTypePass(account.type),
|
||||||
@ -162,24 +149,12 @@ public class OwnCloudClientFactory {
|
|||||||
*/
|
*/
|
||||||
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
public static OwnCloudClient createOwnCloudClient(Uri uri, Context context,
|
||||||
boolean followRedirects) {
|
boolean followRedirects) {
|
||||||
try {
|
OwnCloudClient client = new OwnCloudClient(uri);
|
||||||
NetworkUtils.registerAdvancedSslContext(true, context);
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
Log_OC.e(TAG, "Advanced SSL Context could not be loaded. Default SSL management in" +
|
|
||||||
" the system will be used for HTTPS connections", e);
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log_OC.e(TAG, "The local server truststore could not be read. Default SSL management" +
|
|
||||||
" in the system will be used for HTTPS connections", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager());
|
|
||||||
client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
|
|
||||||
client.setFollowRedirects(followRedirects);
|
client.setFollowRedirects(followRedirects);
|
||||||
|
|
||||||
client.setContext(context);
|
client.setContext(context);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -32,24 +32,23 @@ import android.content.Context;
|
|||||||
|
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager to create and reuse OwnCloudClient instances to access remote OC servers.
|
* Manager to create and reuse OwnCloudClient instances to access remote OC servers.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author Christian Schabesberger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface OwnCloudClientManager {
|
public interface OwnCloudClientManager {
|
||||||
|
|
||||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
|
OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws AccountNotFoundException,
|
||||||
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException,
|
OperationCanceledException, AuthenticatorException,
|
||||||
IOException;
|
IOException;
|
||||||
|
|
||||||
public OwnCloudClient removeClientFor(OwnCloudAccount account);
|
OwnCloudClient removeClientFor(OwnCloudAccount account);
|
||||||
|
|
||||||
public void saveAllClients(Context context, String accountType)
|
void saveAllClients(Context context, String accountType)
|
||||||
throws AccountNotFoundException, AuthenticatorException,
|
throws AccountNotFoundException, AuthenticatorException,
|
||||||
IOException, OperationCanceledException;
|
IOException, OperationCanceledException;
|
||||||
|
}
|
||||||
}
|
|
@ -100,5 +100,4 @@ public class OwnCloudClientManagerFactory {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -40,9 +40,8 @@ public class SimpleFactoryManager implements OwnCloudClientManager {
|
|||||||
private static final String TAG = SimpleFactoryManager.class.getSimpleName();
|
private static final String TAG = SimpleFactoryManager.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
|
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws
|
||||||
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException,
|
OperationCanceledException, AuthenticatorException, IOException {
|
||||||
IOException {
|
|
||||||
|
|
||||||
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
|
Log_OC.d(TAG, "getClientFor(OwnCloudAccount ... : ");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,14 +24,8 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common;
|
package com.owncloud.android.lib.common;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.cookie.CookiePolicy;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
import android.accounts.AuthenticatorException;
|
import android.accounts.AuthenticatorException;
|
||||||
import android.accounts.OperationCanceledException;
|
import android.accounts.OperationCanceledException;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -39,17 +33,23 @@ import android.net.Uri;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
import com.owncloud.android.lib.common.authentication.OwnCloudSamlSsoCredentials;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link OwnCloudClientManager}
|
* Implementation of {@link OwnCloudClientManager}
|
||||||
* <p>
|
*
|
||||||
* TODO check multithreading safety
|
* TODO check multithreading safety
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SingleSessionManager implements OwnCloudClientManager {
|
public class SingleSessionManager implements OwnCloudClientManager {
|
||||||
@ -57,16 +57,15 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
private static final String TAG = SingleSessionManager.class.getSimpleName();
|
private static final String TAG = SingleSessionManager.class.getSimpleName();
|
||||||
|
|
||||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername =
|
private ConcurrentMap<String, OwnCloudClient> mClientsWithKnownUsername =
|
||||||
new ConcurrentHashMap<String, OwnCloudClient>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername =
|
private ConcurrentMap<String, OwnCloudClient> mClientsWithUnknownUsername =
|
||||||
new ConcurrentHashMap<String, OwnCloudClient>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context)
|
public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) throws OperationCanceledException,
|
||||||
throws AccountNotFoundException, OperationCanceledException, AuthenticatorException,
|
AuthenticatorException, IOException {
|
||||||
IOException {
|
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
Log_OC.d(TAG, "getClientFor starting ");
|
Log_OC.d(TAG, "getClientFor starting ");
|
||||||
@ -80,8 +79,7 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
String sessionName = account.getCredentials() == null ? "" :
|
String sessionName = account.getCredentials() == null ? "" :
|
||||||
AccountUtils.buildAccountName(
|
AccountUtils.buildAccountName(
|
||||||
account.getBaseUri(),
|
account.getBaseUri(),
|
||||||
account.getCredentials().getAuthToken()
|
account.getCredentials().getAuthToken());
|
||||||
);
|
|
||||||
|
|
||||||
if (accountName != null) {
|
if (accountName != null) {
|
||||||
client = mClientsWithKnownUsername.get(accountName);
|
client = mClientsWithKnownUsername.get(accountName);
|
||||||
@ -115,16 +113,17 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
account.getBaseUri(),
|
account.getBaseUri(),
|
||||||
context.getApplicationContext(),
|
context.getApplicationContext(),
|
||||||
true); // TODO remove dependency on OwnCloudClientFactory
|
true); // TODO remove dependency on OwnCloudClientFactory
|
||||||
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
|
|
||||||
client.setAccount(account);
|
client.setAccount(account);
|
||||||
client.setContext(context);
|
client.setContext(context);
|
||||||
client.setOwnCloudClientManager(this);
|
client.setOwnCloudClientManager(this);
|
||||||
|
|
||||||
// enable cookie tracking
|
|
||||||
AccountUtils.restoreCookies(account.getSavedAccount(), client, context);
|
|
||||||
|
|
||||||
account.loadCredentials(context);
|
account.loadCredentials(context);
|
||||||
client.setCredentials(account.getCredentials());
|
client.setCredentials(account.getCredentials());
|
||||||
|
|
||||||
|
if (client.getCredentials() instanceof OwnCloudSamlSsoCredentials) {
|
||||||
|
client.disableAutomaticCookiesHandling();
|
||||||
|
}
|
||||||
|
|
||||||
if (accountName != null) {
|
if (accountName != null) {
|
||||||
mClientsWithKnownUsername.put(accountName, client);
|
mClientsWithKnownUsername.put(accountName, client);
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
@ -141,7 +140,9 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
if (!reusingKnown && Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (!reusingKnown && Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
Log_OC.v(TAG, "reusing client for session " + sessionName);
|
||||||
}
|
}
|
||||||
keepCredentialsUpdated(account, client);
|
|
||||||
|
keepCredentialsUpdated(client);
|
||||||
|
keepCookiesUpdated(context, account, client);
|
||||||
keepUriUpdated(account, client);
|
keepUriUpdated(account, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +155,6 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
public OwnCloudClient removeClientFor(OwnCloudAccount account) {
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
Log_OC.d(TAG, "removeClientFor starting ");
|
Log_OC.d(TAG, "removeClientFor starting ");
|
||||||
}
|
}
|
||||||
@ -185,14 +185,11 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
Log_OC.d(TAG, "removeClientFor finishing ");
|
Log_OC.d(TAG, "removeClientFor finishing ");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAllClients(Context context, String accountType)
|
public void saveAllClients(Context context, String accountType) {
|
||||||
throws AccountNotFoundException, AuthenticatorException, IOException,
|
|
||||||
OperationCanceledException {
|
|
||||||
|
|
||||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||||
Log_OC.d(TAG, "Saving sessions... ");
|
Log_OC.d(TAG, "Saving sessions... ");
|
||||||
@ -215,14 +212,19 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void keepCredentialsUpdated(OwnCloudClient reusedClient) {
|
||||||
|
reusedClient.applyCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
private void keepCredentialsUpdated(OwnCloudAccount account, OwnCloudClient reusedClient) {
|
private void keepCookiesUpdated(Context context, OwnCloudAccount account, OwnCloudClient reusedClient) {
|
||||||
OwnCloudCredentials recentCredentials = account.getCredentials();
|
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||||
if (recentCredentials != null && !recentCredentials.getAuthToken().equals(
|
if (am != null && account.getSavedAccount() != null) {
|
||||||
reusedClient.getCredentials().getAuthToken())) {
|
String recentCookies = am.getUserData(account.getSavedAccount(), AccountUtils.Constants.KEY_COOKIES);
|
||||||
reusedClient.setCredentials(recentCredentials);
|
String previousCookies = reusedClient.getCookiesString();
|
||||||
|
if (recentCookies != null && previousCookies != "" && !recentCookies.equals(previousCookies)) {
|
||||||
|
AccountUtils.restoreCookies(account.getSavedAccount(), reusedClient, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is just a patch; we need to distinguish accounts in the same host but
|
// this method is just a patch; we need to distinguish accounts in the same host but
|
||||||
@ -232,8 +234,5 @@ public class SingleSessionManager implements OwnCloudClientManager {
|
|||||||
if (!recentUri.equals(reusedClient.getBaseUri())) {
|
if (!recentUri.equals(reusedClient.getBaseUri())) {
|
||||||
reusedClient.setBaseUri(recentUri);
|
reusedClient.setBaseUri(recentUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2017 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
* Copyright (C) 2012 Bartek Przybylski
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -25,11 +25,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.accounts;
|
package com.owncloud.android.lib.common.accounts;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Cookie;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.accounts.AccountsException;
|
import android.accounts.AccountsException;
|
||||||
@ -38,15 +33,19 @@ import android.accounts.OperationCanceledException;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudAccount;
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
|
||||||
public class AccountUtils {
|
public class AccountUtils {
|
||||||
|
|
||||||
private static final String TAG = AccountUtils.class.getSimpleName();
|
private static final String TAG = AccountUtils.class.getSimpleName();
|
||||||
@ -61,11 +60,23 @@ public class AccountUtils {
|
|||||||
*/
|
*/
|
||||||
public static String getWebDavUrlForAccount(Context context, Account account)
|
public static String getWebDavUrlForAccount(Context context, Account account)
|
||||||
throws AccountNotFoundException {
|
throws AccountNotFoundException {
|
||||||
|
String webDavUrlForAccount = "";
|
||||||
|
|
||||||
return getBaseUrlForAccount(context, account) + OwnCloudClient.WEBDAV_PATH_4_0;
|
try {
|
||||||
|
OwnCloudCredentials ownCloudCredentials = getCredentialsForAccount(context, account);
|
||||||
|
webDavUrlForAccount = getBaseUrlForAccount(context, account) + OwnCloudClient.NEW_WEBDAV_FILES_PATH_4_0
|
||||||
|
+ ownCloudCredentials.getUsername();
|
||||||
|
} catch (OperationCanceledException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (AuthenticatorException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return webDavUrlForAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts url server from the account
|
* Extracts url server from the account
|
||||||
*
|
*
|
||||||
@ -86,7 +97,6 @@ public class AccountUtils {
|
|||||||
return baseurl;
|
return baseurl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the username corresponding to an OC account.
|
* Get the username corresponding to an OC account.
|
||||||
*
|
*
|
||||||
@ -132,7 +142,7 @@ public class AccountUtils {
|
|||||||
public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account)
|
public static OwnCloudCredentials getCredentialsForAccount(Context context, Account account)
|
||||||
throws OperationCanceledException, AuthenticatorException, IOException {
|
throws OperationCanceledException, AuthenticatorException, IOException {
|
||||||
|
|
||||||
OwnCloudCredentials credentials = null;
|
OwnCloudCredentials credentials;
|
||||||
AccountManager am = AccountManager.get(context);
|
AccountManager am = AccountManager.get(context);
|
||||||
|
|
||||||
String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
String supportsOAuth2 = am.getUserData(account, AccountUtils.Constants.KEY_SUPPORTS_OAUTH2);
|
||||||
@ -176,10 +186,8 @@ public class AccountUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return credentials;
|
return credentials;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String buildAccountNameOld(Uri serverBaseUrl, String username) {
|
public static String buildAccountNameOld(Uri serverBaseUrl, String username) {
|
||||||
if (serverBaseUrl.getScheme() == null) {
|
if (serverBaseUrl.getScheme() == null) {
|
||||||
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
serverBaseUrl = Uri.parse("https://" + serverBaseUrl.toString());
|
||||||
@ -207,7 +215,6 @@ public class AccountUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
public static void saveClient(OwnCloudClient client, Account savedAccount, Context context) {
|
||||||
|
|
||||||
// Account Manager
|
// Account Manager
|
||||||
AccountManager ac = AccountManager.get(context.getApplicationContext());
|
AccountManager ac = AccountManager.get(context.getApplicationContext());
|
||||||
|
|
||||||
@ -215,13 +222,11 @@ public class AccountUtils {
|
|||||||
String cookiesString = client.getCookiesString();
|
String cookiesString = client.getCookiesString();
|
||||||
if (!"".equals(cookiesString)) {
|
if (!"".equals(cookiesString)) {
|
||||||
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
|
ac.setUserData(savedAccount, Constants.KEY_COOKIES, cookiesString);
|
||||||
// Log_OC.d(TAG, "Saving Cookies: "+ cookiesString );
|
Log_OC.d(TAG, "Saving Cookies: "+ cookiesString );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore the client cookies persisted in an account stored in the system AccountManager.
|
* Restore the client cookies persisted in an account stored in the system AccountManager.
|
||||||
*
|
*
|
||||||
@ -239,23 +244,28 @@ public class AccountUtils {
|
|||||||
// Account Manager
|
// Account Manager
|
||||||
AccountManager am = AccountManager.get(context.getApplicationContext());
|
AccountManager am = AccountManager.get(context.getApplicationContext());
|
||||||
|
|
||||||
Uri serverUri = (client.getBaseUri() != null) ? client.getBaseUri() : client.getWebdavUri();
|
Uri serverUri = (client.getBaseUri() != null) ? client.getBaseUri() : client.getNewFilesWebDavUri();
|
||||||
|
|
||||||
String cookiesString = am.getUserData(account, Constants.KEY_COOKIES);
|
String cookiesString = am.getUserData(account, Constants.KEY_COOKIES);
|
||||||
if (cookiesString != null) {
|
if (cookiesString != null) {
|
||||||
String[] cookies = cookiesString.split(";");
|
String[] rawCookies = cookiesString.split(";");
|
||||||
if (cookies.length > 0) {
|
List<Cookie> cookieList = new ArrayList<>(rawCookies.length);
|
||||||
for (int i = 0; i < cookies.length; i++) {
|
for(String rawCookie : rawCookies) {
|
||||||
Cookie cookie = new Cookie();
|
rawCookie = rawCookie.replace(" ", "");
|
||||||
int equalPos = cookies[i].indexOf('=');
|
final int equalPos = rawCookie.indexOf('=');
|
||||||
cookie.setName(cookies[i].substring(0, equalPos));
|
if (equalPos == -1) continue;
|
||||||
cookie.setValue(cookies[i].substring(equalPos + 1));
|
cookieList.add(new Cookie.Builder()
|
||||||
cookie.setDomain(serverUri.getHost()); // VERY IMPORTANT
|
.name(rawCookie.substring(0, equalPos))
|
||||||
cookie.setPath(serverUri.getPath()); // VERY IMPORTANT
|
.value(rawCookie.substring(equalPos + 1))
|
||||||
|
.domain(serverUri.getHost())
|
||||||
client.getState().addCookie(cookie);
|
.path(
|
||||||
}
|
serverUri.getPath().equals("")
|
||||||
|
? FileUtils.PATH_SEPARATOR
|
||||||
|
: serverUri.getPath()
|
||||||
|
)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
client.setCookiesForCurrentAccount(cookieList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,7 +289,6 @@ public class AccountUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Constants {
|
public static class Constants {
|
||||||
/**
|
/**
|
||||||
* Version should be 3 numbers separated by dot so it can be parsed by
|
* Version should be 3 numbers separated by dot so it can be parsed by
|
||||||
@ -320,5 +329,4 @@ public class AccountUtils {
|
|||||||
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
public static final String KEY_OAUTH2_REFRESH_TOKEN = "oc_oauth2_refresh_token";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,48 +24,36 @@
|
|||||||
package com.owncloud.android.lib.common.authentication;
|
package com.owncloud.android.lib.common.authentication;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import okhttp3.Credentials;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthPolicy;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthScope;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthState;
|
|
||||||
import org.apache.commons.httpclient.auth.BasicScheme;
|
|
||||||
|
|
||||||
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
|
private static final String TAG = OwnCloudCredentials.class.getSimpleName();
|
||||||
|
|
||||||
private String mUsername;
|
private String mUsername;
|
||||||
private String mPassword;
|
private String mPassword;
|
||||||
private boolean mAuthenticationPreemptive;
|
|
||||||
|
|
||||||
public OwnCloudBasicCredentials(String username, String password) {
|
public OwnCloudBasicCredentials(String username, String password) {
|
||||||
mUsername = username != null ? username : "";
|
mUsername = username != null ? username : "";
|
||||||
mPassword = password != null ? password : "";
|
mPassword = password != null ? password : "";
|
||||||
mAuthenticationPreemptive = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) {
|
public OwnCloudBasicCredentials(String username, String password, boolean preemptiveMode) {
|
||||||
mUsername = username != null ? username : "";
|
mUsername = username != null ? username : "";
|
||||||
mPassword = password != null ? password : "";
|
mPassword = password != null ? password : "";
|
||||||
mAuthenticationPreemptive = preemptiveMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTo(OwnCloudClient client) {
|
public void applyTo(OwnCloudClient client) {
|
||||||
AuthPolicy.registerAuthScheme(AuthState.PREEMPTIVE_AUTH_SCHEME, BasicScheme.class);
|
// Clear previous basic credentials
|
||||||
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||||
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||||
|
|
||||||
List<String> authPrefs = new ArrayList<String>(1);
|
HttpClient.addHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER,
|
||||||
authPrefs.add(AuthPolicy.BASIC);
|
Credentials.basic(mUsername, mPassword));
|
||||||
client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
|
|
||||||
|
|
||||||
client.getParams().setAuthenticationPreemptive(mAuthenticationPreemptive);
|
|
||||||
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
|
|
||||||
client.getState().setCredentials(
|
|
||||||
AuthScope.ANY,
|
|
||||||
new UsernamePasswordCredentials(mUsername, mPassword)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,5 +75,4 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials {
|
|||||||
public boolean authTokenCanBeRefreshed() {
|
public boolean authTokenCanBeRefreshed() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,16 +23,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.owncloud.android.lib.common.authentication;
|
package com.owncloud.android.lib.common.authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.auth.AuthPolicy;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthScope;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthState;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.authentication.oauth.BearerAuthScheme;
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
import com.owncloud.android.lib.common.authentication.oauth.BearerCredentials;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
@ -46,19 +39,12 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTo(OwnCloudClient client) {
|
public void applyTo(OwnCloudClient client) {
|
||||||
AuthPolicy.registerAuthScheme(BearerAuthScheme.AUTH_POLICY, BearerAuthScheme.class);
|
// Clear previous credentials
|
||||||
AuthPolicy.registerAuthScheme(AuthState.PREEMPTIVE_AUTH_SCHEME, BearerAuthScheme.class);
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||||
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||||
|
|
||||||
List<String> authPrefs = new ArrayList<>(1);
|
HttpClient.addHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER,
|
||||||
authPrefs.add(BearerAuthScheme.AUTH_POLICY);
|
HttpConstants.BEARER_AUTHORIZATION_KEY + mAccessToken);
|
||||||
client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
|
|
||||||
|
|
||||||
client.getParams().setAuthenticationPreemptive(true); // true enforces BASIC AUTH ; library is stupid
|
|
||||||
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
|
|
||||||
client.getState().setCredentials(
|
|
||||||
AuthScope.ANY,
|
|
||||||
new BearerCredentials(mAccessToken)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -81,5 +67,4 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials {
|
|||||||
public boolean authTokenCanBeRefreshed() {
|
public boolean authTokenCanBeRefreshed() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -25,6 +25,8 @@
|
|||||||
package com.owncloud.android.lib.common.authentication;
|
package com.owncloud.android.lib.common.authentication;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
public class OwnCloudCredentialsFactory {
|
public class OwnCloudCredentialsFactory {
|
||||||
|
|
||||||
@ -64,8 +66,9 @@ public class OwnCloudCredentialsFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTo(OwnCloudClient client) {
|
public void applyTo(OwnCloudClient client) {
|
||||||
client.getState().clearCredentials();
|
// Clear previous basic credentials
|
||||||
client.getState().clearCookies();
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||||
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,5 +92,4 @@ public class OwnCloudCredentialsFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -23,12 +23,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.owncloud.android.lib.common.authentication;
|
package com.owncloud.android.lib.common.authentication;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Cookie;
|
|
||||||
import org.apache.commons.httpclient.cookie.CookiePolicy;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
||||||
|
|
||||||
@ -42,28 +39,12 @@ public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyTo(OwnCloudClient client) {
|
public void applyTo(OwnCloudClient client) {
|
||||||
client.getParams().setAuthenticationPreemptive(false);
|
// Clear previous credentials
|
||||||
client.getParams().setCredentialCharset(OwnCloudCredentialsFactory.CREDENTIAL_CHARSET);
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.AUTHORIZATION_HEADER);
|
||||||
client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
|
HttpClient.deleteHeaderForAllRequests(HttpConstants.COOKIE_HEADER);
|
||||||
|
|
||||||
|
HttpClient.addHeaderForAllRequests(HttpConstants.COOKIE_HEADER, mSessionCookie);
|
||||||
client.setFollowRedirects(false);
|
client.setFollowRedirects(false);
|
||||||
|
|
||||||
Uri serverUri = client.getBaseUri();
|
|
||||||
|
|
||||||
String[] cookies = mSessionCookie.split(";");
|
|
||||||
if (cookies.length > 0) {
|
|
||||||
Cookie cookie = null;
|
|
||||||
for (int i = 0; i < cookies.length; i++) {
|
|
||||||
int equalPos = cookies[i].indexOf('=');
|
|
||||||
if (equalPos >= 0) {
|
|
||||||
cookie = new Cookie();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -86,5 +67,4 @@ public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials {
|
|||||||
public boolean authTokenCanBeRefreshed() {
|
public boolean authTokenCanBeRefreshed() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,262 +0,0 @@
|
|||||||
/* 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.common.authentication.oauth;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Credentials;
|
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthChallengeParser;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthScheme;
|
|
||||||
import org.apache.commons.httpclient.auth.AuthenticationException;
|
|
||||||
import org.apache.commons.httpclient.auth.InvalidCredentialsException;
|
|
||||||
import org.apache.commons.httpclient.auth.MalformedChallengeException;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,16 +24,14 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.authentication.oauth;
|
package com.owncloud.android.lib.common.authentication.oauth;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Credentials;
|
|
||||||
import org.apache.commons.httpclient.util.LangUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bearer token {@link Credentials}
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
|
* @author Christian Schabesberger
|
||||||
*/
|
*/
|
||||||
public class BearerCredentials implements Credentials {
|
public class BearerCredentials {
|
||||||
|
|
||||||
|
public static final int HASH_SEED = 17;
|
||||||
|
public static final int HASH_OFFSET = 37;
|
||||||
|
|
||||||
private String mAccessToken;
|
private String mAccessToken;
|
||||||
|
|
||||||
@ -76,9 +74,7 @@ public class BearerCredentials implements Credentials {
|
|||||||
* @return The hash code of the access token
|
* @return The hash code of the access token
|
||||||
*/
|
*/
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = LangUtils.HASH_SEED;
|
return HASH_SEED * HASH_OFFSET + mAccessToken.hashCode();
|
||||||
hash = LangUtils.hashCode(hash, mAccessToken);
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,12 +89,10 @@ public class BearerCredentials implements Credentials {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (this.getClass().equals(o.getClass())) {
|
if (this.getClass().equals(o.getClass())) {
|
||||||
BearerCredentials that = (BearerCredentials) o;
|
BearerCredentials that = (BearerCredentials) o;
|
||||||
if (LangUtils.equals(mAccessToken, that.mAccessToken)) {
|
if (mAccessToken.equals(that.mAccessToken)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* Copyright (C) 2017 ownCloud GmbH.
|
* @author Christian Schabesberger
|
||||||
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -31,21 +32,21 @@ import android.net.Uri;
|
|||||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.NameValuePair;
|
|
||||||
import org.apache.commons.httpclient.methods.PostMethod;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
|
||||||
public class OAuth2GetAccessTokenOperation extends RemoteOperation {
|
|
||||||
|
public class OAuth2GetAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||||
|
|
||||||
private String mGrantType;
|
private String mGrantType;
|
||||||
private String mCode;
|
private String mCode;
|
||||||
@ -82,29 +83,33 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<Map<String, String>> result = null;
|
||||||
PostMethod postMethod = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
NameValuePair[] nameValuePairs = new NameValuePair[4];
|
|
||||||
nameValuePairs[0] = new NameValuePair(OAuth2Constants.KEY_GRANT_TYPE, mGrantType);
|
final RequestBody requestBody = new MultipartBody.Builder()
|
||||||
nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CODE, mCode);
|
.setType(MultipartBody.FORM)
|
||||||
nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri);
|
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE, mGrantType)
|
||||||
nameValuePairs[3] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
|
.addFormDataPart(OAuth2Constants.KEY_CODE, mCode)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_REDIRECT_URI, mRedirectUri)
|
||||||
|
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||||
|
.build();
|
||||||
|
|
||||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||||
|
|
||||||
postMethod = new PostMethod(uriBuilder.build().toString());
|
final PostMethod postMethod = new PostMethod(new URL(
|
||||||
postMethod.setRequestBody(nameValuePairs);
|
client.getBaseUri().buildUpon()
|
||||||
|
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||||
|
.build()
|
||||||
|
.toString()));
|
||||||
|
|
||||||
OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(
|
postMethod.setRequestBody(requestBody);
|
||||||
mClientId,
|
|
||||||
mClientSecret
|
OwnCloudCredentials oauthCredentials =
|
||||||
);
|
new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||||
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||||
|
client.executeHttpMethod(postMethod);
|
||||||
client.executeMethod(postMethod);
|
|
||||||
switchClientCredentials(oldCredentials);
|
switchClientCredentials(oldCredentials);
|
||||||
|
|
||||||
String response = postMethod.getResponseBodyAsString();
|
String response = postMethod.getResponseBodyAsString();
|
||||||
@ -114,28 +119,22 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation {
|
|||||||
mResponseParser.parseAccessTokenResult(tokenJson);
|
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||||
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
if (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||||
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null) {
|
||||||
result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
|
result = new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(true, postMethod);
|
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||||
ArrayList<Object> data = new ArrayList<>();
|
result.setData(accessTokenResult);
|
||||||
data.add(accessTokenResult);
|
|
||||||
result.setData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, postMethod);
|
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||||
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (postMethod != null)
|
|
||||||
postMethod.releaseConnection(); // let the connection available for other methods
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,5 +143,4 @@ public class OAuth2GetAccessTokenOperation extends RemoteOperation {
|
|||||||
getClient().setCredentials(newCredentials);
|
getClient().setCredentials(newCredentials);
|
||||||
return previousCredentials;
|
return previousCredentials;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -2,8 +2,9 @@
|
|||||||
* ownCloud Android client application
|
* ownCloud Android client application
|
||||||
*
|
*
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
|
* @author Christian Schabesberger
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2,
|
* it under the terms of the GNU General Public License version 2,
|
||||||
@ -26,19 +27,22 @@ import android.net.Uri;
|
|||||||
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudBasicCredentials;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.NameValuePair;
|
|
||||||
import org.apache.commons.httpclient.methods.PostMethod;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.net.URL;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation {
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||||
|
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
|
||||||
|
public class OAuth2RefreshAccessTokenOperation extends RemoteOperation<Map<String, String>> {
|
||||||
|
|
||||||
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
|
private static final String TAG = OAuth2RefreshAccessTokenOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -71,70 +75,55 @@ public class OAuth2RefreshAccessTokenOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<Map<String, String>> run(OwnCloudClient client) {
|
||||||
|
|
||||||
RemoteOperationResult result = null;
|
|
||||||
PostMethod postMethod = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
NameValuePair[] nameValuePairs = new NameValuePair[3];
|
final RequestBody requestBody = new MultipartBody.Builder()
|
||||||
nameValuePairs[0] = new NameValuePair(
|
.setType(MultipartBody.FORM)
|
||||||
OAuth2Constants.KEY_GRANT_TYPE,
|
.addFormDataPart(OAuth2Constants.KEY_GRANT_TYPE,
|
||||||
OAuth2GrantType.REFRESH_TOKEN.getValue() // always for this operation
|
OAuth2GrantType.REFRESH_TOKEN.getValue())
|
||||||
);
|
.addFormDataPart(OAuth2Constants.KEY_CLIENT_ID, mClientId)
|
||||||
nameValuePairs[1] = new NameValuePair(OAuth2Constants.KEY_CLIENT_ID, mClientId);
|
.addFormDataPart(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken)
|
||||||
nameValuePairs[2] = new NameValuePair(OAuth2Constants.KEY_REFRESH_TOKEN, mRefreshToken);
|
.build();
|
||||||
|
|
||||||
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
Uri.Builder uriBuilder = client.getBaseUri().buildUpon();
|
||||||
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
uriBuilder.appendEncodedPath(mAccessTokenEndpointPath);
|
||||||
|
|
||||||
postMethod = new PostMethod(uriBuilder.build().toString());
|
final PostMethod postMethod = new PostMethod(new URL(
|
||||||
postMethod.setRequestBody(nameValuePairs);
|
client.getBaseUri().buildUpon()
|
||||||
|
.appendEncodedPath(mAccessTokenEndpointPath)
|
||||||
|
.build()
|
||||||
|
.toString()));
|
||||||
|
postMethod.setRequestBody(requestBody);
|
||||||
|
|
||||||
OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(
|
final OwnCloudCredentials oauthCredentials = new OwnCloudBasicCredentials(mClientId, mClientSecret);
|
||||||
mClientId,
|
|
||||||
mClientSecret
|
|
||||||
);
|
|
||||||
|
|
||||||
OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
|
||||||
|
|
||||||
client.executeMethod(postMethod);
|
|
||||||
|
|
||||||
|
final OwnCloudCredentials oldCredentials = switchClientCredentials(oauthCredentials);
|
||||||
|
client.executeHttpMethod(postMethod);
|
||||||
switchClientCredentials(oldCredentials);
|
switchClientCredentials(oldCredentials);
|
||||||
|
|
||||||
String response = postMethod.getResponseBodyAsString();
|
final String responseData = postMethod.getResponseBodyAsString();
|
||||||
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + response);
|
Log_OC.d(TAG, "OAUTH2: raw response from POST TOKEN: " + responseData);
|
||||||
|
|
||||||
if (response != null && response.length() > 0) {
|
if (responseData != null && responseData.length() > 0) {
|
||||||
JSONObject tokenJson = new JSONObject(response);
|
final 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) {
|
|
||||||
result = new RemoteOperationResult(ResultCode.OAUTH2_ERROR);
|
|
||||||
|
|
||||||
} else {
|
final Map<String, String> accessTokenResult =
|
||||||
result = new RemoteOperationResult(true, postMethod);
|
mResponseParser.parseAccessTokenResult(tokenJson);
|
||||||
ArrayList<Object> data = new ArrayList<>();
|
|
||||||
data.add(accessTokenResult);
|
|
||||||
result.setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final RemoteOperationResult<Map<String, String>> result = new RemoteOperationResult<>(ResultCode.OK);
|
||||||
|
result.setData(accessTokenResult);
|
||||||
|
return (accessTokenResult.get(OAuth2Constants.KEY_ERROR) != null ||
|
||||||
|
accessTokenResult.get(OAuth2Constants.KEY_ACCESS_TOKEN) == null)
|
||||||
|
? new RemoteOperationResult<>(ResultCode.OAUTH2_ERROR)
|
||||||
|
: result;
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, postMethod);
|
return new RemoteOperationResult<>(postMethod);
|
||||||
client.exhaustResponse(postMethod.getResponseBodyAsStream());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
return new RemoteOperationResult<>(e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (postMethod != null) {
|
|
||||||
postMethod.releaseConnection(); // let the connection available for other methods
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
private OwnCloudCredentials switchClientCredentials(OwnCloudCredentials newCredentials) {
|
||||||
@ -142,5 +131,4 @@ public class OAuth2RefreshAccessTokenOperation extends RemoteOperation {
|
|||||||
getClient().setCredentials(newCredentials);
|
getClient().setCredentials(newCredentials);
|
||||||
return previousCredentials;
|
return previousCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
172
src/com/owncloud/android/lib/common/http/HttpClient.java
Normal file
172
src/com/owncloud/android/lib/common/http/HttpClient.java
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
||||||
|
import com.owncloud.android.lib.common.http.interceptors.HttpInterceptor;
|
||||||
|
import com.owncloud.android.lib.common.http.interceptors.RequestHeaderInterceptor;
|
||||||
|
import com.owncloud.android.lib.common.network.AdvancedX509TrustManager;
|
||||||
|
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
import okhttp3.CookieJar;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client used to perform network operations
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class HttpClient {
|
||||||
|
private static final String TAG = HttpClient.class.toString();
|
||||||
|
|
||||||
|
private static OkHttpClient sOkHttpClient;
|
||||||
|
private static HttpInterceptor sOkHttpInterceptor;
|
||||||
|
private static Context sContext;
|
||||||
|
private static HashMap<String, List<Cookie>> sCookieStore = new HashMap<>();
|
||||||
|
|
||||||
|
public static void setContext(Context context) {
|
||||||
|
sContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context getContext() {
|
||||||
|
return sContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OkHttpClient getOkHttpClient() {
|
||||||
|
if (sOkHttpClient == null) {
|
||||||
|
try {
|
||||||
|
final X509TrustManager trustManager = new AdvancedX509TrustManager(
|
||||||
|
NetworkUtils.getKnownServersStore(sContext));
|
||||||
|
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, new TrustManager[] {trustManager}, null);
|
||||||
|
|
||||||
|
// Automatic cookie handling, NOT PERSISTENT
|
||||||
|
CookieJar cookieJar = new CookieJar() {
|
||||||
|
@Override
|
||||||
|
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||||
|
// Avoid duplicated cookies
|
||||||
|
Set<Cookie> nonDuplicatedCookiesSet = new HashSet<>();
|
||||||
|
nonDuplicatedCookiesSet.addAll(cookies);
|
||||||
|
List<Cookie> nonDuplicatedCookiesList = new ArrayList<>();
|
||||||
|
nonDuplicatedCookiesList.addAll(nonDuplicatedCookiesSet);
|
||||||
|
|
||||||
|
sCookieStore.put(url.host(), nonDuplicatedCookiesList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||||
|
List<Cookie> cookies = sCookieStore.get(url.host());
|
||||||
|
return cookies != null ? cookies : new ArrayList<>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
|
||||||
|
.addInterceptor(getOkHttpInterceptor())
|
||||||
|
.protocols(Arrays.asList(Protocol.HTTP_1_1))
|
||||||
|
.readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
.followRedirects(false)
|
||||||
|
.sslSocketFactory(sslContext.getSocketFactory(), trustManager)
|
||||||
|
.hostnameVerifier((asdf, usdf) -> true)
|
||||||
|
.cookieJar(cookieJar);
|
||||||
|
// TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok.
|
||||||
|
//.hostnameVerifier(new BrowserCompatHostnameVerifier());
|
||||||
|
sOkHttpClient = clientBuilder.build();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.e(TAG, "Could not setup SSL system.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sOkHttpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpInterceptor getOkHttpInterceptor() {
|
||||||
|
if (sOkHttpInterceptor == null) {
|
||||||
|
sOkHttpInterceptor = new HttpInterceptor();
|
||||||
|
addHeaderForAllRequests(HttpConstants.USER_AGENT_HEADER, OwnCloudClientManagerFactory.getUserAgent());
|
||||||
|
addHeaderForAllRequests(HttpConstants.PARAM_SINGLE_COOKIE_HEADER, "true");
|
||||||
|
addHeaderForAllRequests(HttpConstants.ACCEPT_ENCODING_HEADER, HttpConstants.ACCEPT_ENCODING_IDENTITY);
|
||||||
|
}
|
||||||
|
return sOkHttpInterceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disableAutomaticCookiesHandling() {
|
||||||
|
OkHttpClient.Builder clientBuilder = getOkHttpClient().newBuilder();
|
||||||
|
clientBuilder.cookieJar(new CookieJar() {
|
||||||
|
@Override
|
||||||
|
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||||
|
// DO NOTHING
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sOkHttpClient = clientBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add header that will be included for all the requests from now on
|
||||||
|
* @param headerName
|
||||||
|
* @param headerValue
|
||||||
|
*/
|
||||||
|
public static void addHeaderForAllRequests(String headerName, String headerValue) {
|
||||||
|
getOkHttpInterceptor()
|
||||||
|
.addRequestInterceptor(
|
||||||
|
new RequestHeaderInterceptor(headerName, headerValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteHeaderForAllRequests(String headerName) {
|
||||||
|
getOkHttpInterceptor().deleteRequestHeaderInterceptor(headerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Cookie> getCookiesFromUrl(HttpUrl httpUrl) {
|
||||||
|
return sCookieStore.get(httpUrl.host());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCookies() {
|
||||||
|
sCookieStore.clear();
|
||||||
|
}
|
||||||
|
}
|
189
src/com/owncloud/android/lib/common/http/HttpConstants.java
Normal file
189
src/com/owncloud/android/lib/common/http/HttpConstants.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class HttpConstants {
|
||||||
|
|
||||||
|
/***********************************************************************************************************
|
||||||
|
*************************************************** HEADERS ***********************************************
|
||||||
|
***********************************************************************************************************/
|
||||||
|
|
||||||
|
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
|
public static final String COOKIE_HEADER = "Cookie";
|
||||||
|
public static final String BEARER_AUTHORIZATION_KEY = "Bearer ";
|
||||||
|
public static final String USER_AGENT_HEADER = "User-Agent";
|
||||||
|
public static final String IF_MATCH_HEADER = "If-Match";
|
||||||
|
public static final String IF_NONE_MATCH_HEADER = "If-None-Match";
|
||||||
|
public static final String CONTENT_TYPE_HEADER = "Content-Type";
|
||||||
|
public static final String CONTENT_LENGTH_HEADER = "Content-Length";
|
||||||
|
public static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
||||||
|
public static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
||||||
|
public static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
|
||||||
|
public static final String OC_X_REQUEST_ID = "X-Request-ID";
|
||||||
|
public static final String LOCATION_HEADER = "Location";
|
||||||
|
public static final String LOCATION_HEADER_LOWER = "location";
|
||||||
|
public static final String CONTENT_TYPE_URLENCODED_UTF8 = "application/x-www-form-urlencoded; charset=utf-8";
|
||||||
|
public static final String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
|
||||||
|
public static final String ACCEPT_ENCODING_IDENTITY = "identity";
|
||||||
|
|
||||||
|
/***********************************************************************************************************
|
||||||
|
************************************************ STATUS CODES *********************************************
|
||||||
|
***********************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1xx Informational
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 100 Continue (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_CONTINUE = 100;
|
||||||
|
// 101 Switching Protocols (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_SWITCHING_PROTOCOLS = 101;
|
||||||
|
// 102 Processing (WebDAV - RFC 2518)
|
||||||
|
public static final int HTTP_PROCESSING = 102;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2xx Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 200 OK (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_OK = 200;
|
||||||
|
// 201 Created (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_CREATED = 201;
|
||||||
|
// 202 Accepted (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_ACCEPTED = 202;
|
||||||
|
// 203 Non Authoritative Information (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
|
||||||
|
// 204 No Content</tt> (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_NO_CONTENT = 204;
|
||||||
|
// 205 Reset Content</tt> (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_RESET_CONTENT = 205;
|
||||||
|
// 206 Partial Content</tt> (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_PARTIAL_CONTENT = 206;
|
||||||
|
//207 Multi-Status (WebDAV - RFC 2518) or 207 Partial Update OK (HTTP/1.1 - draft-ietf-http-v11-spec-rev-01?)
|
||||||
|
public static final int HTTP_MULTI_STATUS = 207;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3xx Redirection
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 300 Mutliple Choices</tt> (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_MULTIPLE_CHOICES = 300;
|
||||||
|
// 301 Moved Permanently</tt> (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_MOVED_PERMANENTLY = 301;
|
||||||
|
// 302 Moved Temporarily</tt> (Sometimes <tt>Found) (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_MOVED_TEMPORARILY = 302;
|
||||||
|
// 303 See Other (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_SEE_OTHER = 303;
|
||||||
|
// 304 Not Modified (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_NOT_MODIFIED = 304;
|
||||||
|
// 305 Use Proxy (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_USE_PROXY = 305;
|
||||||
|
// 307 Temporary Redirect (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_TEMPORARY_REDIRECT = 307;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4xx Client Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 400 Bad Request (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_BAD_REQUEST = 400;
|
||||||
|
// 401 Unauthorized (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_UNAUTHORIZED = 401;
|
||||||
|
// 402 Payment Required (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_PAYMENT_REQUIRED = 402;
|
||||||
|
// 403 Forbidden (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_FORBIDDEN = 403;
|
||||||
|
// 404 Not Found (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_NOT_FOUND = 404;
|
||||||
|
// 405 Method Not Allowed (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_METHOD_NOT_ALLOWED = 405;
|
||||||
|
// 406 Not Acceptable (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_NOT_ACCEPTABLE = 406;
|
||||||
|
// 407 Proxy Authentication Required (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||||
|
// 408 Request Timeout (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_REQUEST_TIMEOUT = 408;
|
||||||
|
// 409 Conflict (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_CONFLICT = 409;
|
||||||
|
// 410 Gone (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_GONE = 410;
|
||||||
|
// 411 Length Required (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_LENGTH_REQUIRED = 411;
|
||||||
|
// 412 Precondition Failed (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_PRECONDITION_FAILED = 412;
|
||||||
|
// 413 Request Entity Too Large (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_REQUEST_TOO_LONG = 413;
|
||||||
|
// 414 Request-URI Too Long (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_REQUEST_URI_TOO_LONG = 414;
|
||||||
|
// 415 Unsupported Media Type (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
|
||||||
|
// 416 Requested Range Not Satisfiable (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||||
|
// 417 Expectation Failed (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_EXPECTATION_FAILED = 417;
|
||||||
|
// 419 Insufficient Space on Resource (WebDAV - draft-ietf-webdav-protocol-05?)
|
||||||
|
// or <tt>419 Proxy Reauthentication Required (HTTP/1.1 drafts?)
|
||||||
|
public static final int HTTP_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
|
||||||
|
// 420 Method Failure (WebDAV - draft-ietf-webdav-protocol-05?)
|
||||||
|
public static final int HTTP_METHOD_FAILURE = 420;
|
||||||
|
// 422 Unprocessable Entity (WebDAV - RFC 2518)
|
||||||
|
public static final int HTTP_UNPROCESSABLE_ENTITY = 422;
|
||||||
|
// 423 Locked (WebDAV - RFC 2518)
|
||||||
|
public static final int HTTP_LOCKED = 423;
|
||||||
|
// 424 Failed Dependency (WebDAV - RFC 2518)
|
||||||
|
public static final int HTTP_FAILED_DEPENDENCY = 424;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 5xx Client Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 500 Server Error (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||||
|
// 501 Not Implemented (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_NOT_IMPLEMENTED = 501;
|
||||||
|
// 502 Bad Gateway (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_BAD_GATEWAY = 502;
|
||||||
|
// 503 Service Unavailable (HTTP/1.0 - RFC 1945)
|
||||||
|
public static final int HTTP_SERVICE_UNAVAILABLE = 503;
|
||||||
|
// 504 Gateway Timeout (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_GATEWAY_TIMEOUT = 504;
|
||||||
|
// 505 HTTP Version Not Supported (HTTP/1.1 - RFC 2616)
|
||||||
|
public static final int HTTP_HTTP_VERSION_NOT_SUPPORTED = 505;
|
||||||
|
// 507 Insufficient Storage (WebDAV - RFC 2518)
|
||||||
|
public static final int HTTP_INSUFFICIENT_STORAGE = 507;
|
||||||
|
|
||||||
|
/***********************************************************************************************************
|
||||||
|
*************************************************** TIMEOUTS **********************************************
|
||||||
|
***********************************************************************************************************/
|
||||||
|
|
||||||
|
/** Default timeout for waiting data from the server */
|
||||||
|
public static final int DEFAULT_DATA_TIMEOUT = 60000;
|
||||||
|
|
||||||
|
/** Default timeout for establishing a connection */
|
||||||
|
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.interceptors;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http interceptor to use multiple interceptors in the same {@link okhttp3.OkHttpClient} instance
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class HttpInterceptor implements Interceptor {
|
||||||
|
|
||||||
|
private final ArrayList<RequestInterceptor> mRequestInterceptors = new ArrayList<>();
|
||||||
|
private final ArrayList<ResponseInterceptor> mResponseInterceptors = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
|
||||||
|
for (RequestInterceptor interceptor : mRequestInterceptors) {
|
||||||
|
request = interceptor.intercept(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Response response = chain.proceed(request);
|
||||||
|
|
||||||
|
for (ResponseInterceptor interceptor : mResponseInterceptors) {
|
||||||
|
response = interceptor.intercept(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RequestInterceptor {
|
||||||
|
Request intercept(Request request) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ResponseInterceptor {
|
||||||
|
Response intercept(Response response) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpInterceptor addRequestInterceptor(RequestInterceptor requestInterceptor) {
|
||||||
|
mRequestInterceptors.add(requestInterceptor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpInterceptor addResponseInterceptor (ResponseInterceptor responseInterceptor) {
|
||||||
|
mResponseInterceptors.add(responseInterceptor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<RequestInterceptor> getRequestInterceptors() {
|
||||||
|
return mRequestInterceptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<RequestHeaderInterceptor> getRequestHeaderInterceptors() {
|
||||||
|
ArrayList<RequestHeaderInterceptor> requestHeaderInterceptors = new ArrayList<>();
|
||||||
|
|
||||||
|
for (RequestInterceptor requestInterceptor : mRequestInterceptors) {
|
||||||
|
if (requestInterceptor instanceof RequestHeaderInterceptor) {
|
||||||
|
requestHeaderInterceptors.add((RequestHeaderInterceptor) requestInterceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestHeaderInterceptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteRequestHeaderInterceptor(String headerName) {
|
||||||
|
Iterator<RequestInterceptor> requestInterceptorIterator = mRequestInterceptors.iterator();
|
||||||
|
while (requestInterceptorIterator.hasNext()) {
|
||||||
|
RequestInterceptor currentRequestInterceptor = requestInterceptorIterator.next();
|
||||||
|
if (currentRequestInterceptor instanceof RequestHeaderInterceptor &&
|
||||||
|
((RequestHeaderInterceptor) currentRequestInterceptor).getHeaderName().equals(headerName)) {
|
||||||
|
requestInterceptorIterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ResponseInterceptor> getResponseInterceptors() {
|
||||||
|
return mResponseInterceptors;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.interceptors;
|
||||||
|
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercept requests to update their headers
|
||||||
|
*/
|
||||||
|
public class RequestHeaderInterceptor implements HttpInterceptor.RequestInterceptor {
|
||||||
|
|
||||||
|
private String mHeaderName;
|
||||||
|
private String mHeaderValue;
|
||||||
|
|
||||||
|
public RequestHeaderInterceptor(String headerName, String headerValue) {
|
||||||
|
this.mHeaderName = headerName;
|
||||||
|
this.mHeaderValue = headerValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request intercept(Request request) {
|
||||||
|
return request.newBuilder().addHeader(mHeaderName, mHeaderValue).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderName() {
|
||||||
|
return mHeaderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeaderValue() {
|
||||||
|
return mHeaderValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,192 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.HttpClient;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper to perform http calls transparently by using:
|
||||||
|
* - OkHttp for non webdav methods
|
||||||
|
* - Dav4Android for webdav methods
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public abstract class HttpBaseMethod {
|
||||||
|
protected OkHttpClient mOkHttpClient;
|
||||||
|
protected Request mRequest;
|
||||||
|
protected RequestBody mRequestBody;
|
||||||
|
protected Response mResponse;
|
||||||
|
protected String mResponseBodyString;
|
||||||
|
protected Call mCall;
|
||||||
|
|
||||||
|
protected HttpBaseMethod(URL url) {
|
||||||
|
mOkHttpClient = HttpClient.getOkHttpClient();
|
||||||
|
mRequest = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(url.toString()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int execute() throws Exception {
|
||||||
|
return onExecute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void abort() {
|
||||||
|
mCall.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAborted() {
|
||||||
|
return mCall.isCanceled();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// For override
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
protected abstract int onExecute() throws Exception;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Getter
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
// Request
|
||||||
|
|
||||||
|
public Headers getRequestHeaders() {
|
||||||
|
return mRequest.headers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestHeader(String name) {
|
||||||
|
return mRequest.header(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
|
||||||
|
public int getStatusCode() {
|
||||||
|
return mResponse.code();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatusMessage() {
|
||||||
|
return mResponse.message();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseBodyAsString() throws IOException {
|
||||||
|
if (mResponseBodyString == null && mResponse.body() != null) {
|
||||||
|
mResponseBodyString = mResponse.body().string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mResponseBodyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getResponseBodyAsStream() {
|
||||||
|
if (mResponse.body() != null) {
|
||||||
|
return mResponse.body().byteStream();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Headers getResponseHeaders() {
|
||||||
|
return mResponse.headers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseHeader(String headerName) {
|
||||||
|
return mResponse.header(headerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getRetryOnConnectionFailure() {
|
||||||
|
return mOkHttpClient.retryOnConnectionFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Setter
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
// Connection parameters
|
||||||
|
|
||||||
|
public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
|
||||||
|
mOkHttpClient = mOkHttpClient.newBuilder()
|
||||||
|
.readTimeout(readTimeout, timeUnit)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectionTimeout(long connectionTimeout, TimeUnit timeUnit) {
|
||||||
|
mOkHttpClient = mOkHttpClient.newBuilder()
|
||||||
|
.readTimeout(connectionTimeout, timeUnit)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFollowRedirects(boolean followRedirects) {
|
||||||
|
mOkHttpClient = mOkHttpClient.newBuilder()
|
||||||
|
.followRedirects(followRedirects)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
|
||||||
|
mOkHttpClient = mOkHttpClient.newBuilder()
|
||||||
|
.retryOnConnectionFailure(retryOnConnectionFailure)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request
|
||||||
|
|
||||||
|
public void addRequestHeader(String name, String value) {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.addHeader(name, value)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a header and replace it if already exists with that name
|
||||||
|
*
|
||||||
|
* @param name header name
|
||||||
|
* @param value header value
|
||||||
|
*/
|
||||||
|
public void setRequestHeader(String name, String value) {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.header(name, value)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestBody(RequestBody requestBody) {
|
||||||
|
mRequestBody = requestBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(HttpUrl url) {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.url(url)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.nonwebdav;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OkHttp delete calls wrapper
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class DeleteMethod extends HttpMethod{
|
||||||
|
|
||||||
|
public DeleteMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.delete()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return super.onExecute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.nonwebdav;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OkHttp get calls wrapper
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class GetMethod extends HttpMethod {
|
||||||
|
|
||||||
|
public GetMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return super.onExecute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.nonwebdav;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper to perform OkHttp calls
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public abstract class HttpMethod extends HttpBaseMethod {
|
||||||
|
|
||||||
|
public HttpMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException {
|
||||||
|
mCall = mOkHttpClient.newCall(mRequest);
|
||||||
|
mResponse = mCall.execute();
|
||||||
|
return super.getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.nonwebdav;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OkHttp post calls wrapper
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class PostMethod extends HttpMethod {
|
||||||
|
|
||||||
|
public PostMethod(URL url){
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.post(mRequestBody)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return super.onExecute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.nonwebdav;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
public class PutMethod extends HttpMethod{
|
||||||
|
|
||||||
|
public PutMethod(URL url){
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException {
|
||||||
|
mRequest = mRequest.newBuilder()
|
||||||
|
.put(mRequestBody)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return super.onExecute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy calls wrapper
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class CopyMethod extends DavMethod {
|
||||||
|
|
||||||
|
final String destinationUrl;
|
||||||
|
final boolean forceOverride;
|
||||||
|
|
||||||
|
public CopyMethod(URL url, String destinationUrl, boolean forceOverride) {
|
||||||
|
super(url);
|
||||||
|
this.destinationUrl = destinationUrl;
|
||||||
|
this.forceOverride = forceOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws Exception {
|
||||||
|
mDavResource.copy(destinationUrl, forceOverride, response -> {
|
||||||
|
mResponse = response;
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
return super.getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class DavConstants {
|
||||||
|
public static final int DEPTH_0 = 0;
|
||||||
|
public static final int DEPTH_1 = 1;
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.Constants;
|
||||||
|
import at.bitfire.dav4android.DavOCResource;
|
||||||
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import at.bitfire.dav4android.exception.RedirectException;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Protocol;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper to perform WebDAV (dav4android) calls
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public abstract class DavMethod extends HttpBaseMethod {
|
||||||
|
|
||||||
|
protected DavOCResource mDavResource;
|
||||||
|
|
||||||
|
protected DavMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(url.toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void abort() {
|
||||||
|
mDavResource.cancelCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int execute() throws Exception {
|
||||||
|
try {
|
||||||
|
return onExecute();
|
||||||
|
} catch (HttpException httpException) {
|
||||||
|
// Modify responses with information gathered from exceptions
|
||||||
|
if (httpException instanceof RedirectException) {
|
||||||
|
mResponse = new Response.Builder()
|
||||||
|
.header(
|
||||||
|
HttpConstants.LOCATION_HEADER, ((RedirectException) httpException).getRedirectLocation()
|
||||||
|
)
|
||||||
|
.code(httpException.getCode())
|
||||||
|
.request(mRequest)
|
||||||
|
.message(httpException.getMessage())
|
||||||
|
.protocol(Protocol.HTTP_1_1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
} else if (mResponse != null) {
|
||||||
|
ResponseBody responseBody = ResponseBody.create(
|
||||||
|
mResponse.body().contentType(),
|
||||||
|
httpException.getResponseBody()
|
||||||
|
);
|
||||||
|
|
||||||
|
mResponse = mResponse.newBuilder()
|
||||||
|
.body(responseBody)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpException.getCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Setter
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
// Connection parameters
|
||||||
|
@Override
|
||||||
|
public void setReadTimeout(long readTimeout, TimeUnit timeUnit) {
|
||||||
|
super.setReadTimeout(readTimeout, timeUnit);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(mRequest.url().toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConnectionTimeout(long connectionTimeout, TimeUnit timeUnit) {
|
||||||
|
super.setConnectionTimeout(connectionTimeout, timeUnit);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(mRequest.url().toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFollowRedirects(boolean followRedirects) {
|
||||||
|
super.setFollowRedirects(followRedirects);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(mRequest.url().toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
|
||||||
|
super.setRetryOnConnectionFailure(retryOnConnectionFailure);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(mRequest.url().toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUrl(HttpUrl url){
|
||||||
|
super.setUrl(url);
|
||||||
|
mDavResource = new DavOCResource(
|
||||||
|
mOkHttpClient,
|
||||||
|
HttpUrl.parse(mRequest.url().toString()),
|
||||||
|
Constants.INSTANCE.getLog());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Getter
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getRetryOnConnectionFailure() {
|
||||||
|
return false; //TODO: implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAborted() {
|
||||||
|
return mDavResource.isCallAborted();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.owncloud.android.lib.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.Property;
|
||||||
|
import at.bitfire.dav4android.PropertyUtils;
|
||||||
|
|
||||||
|
public class DavUtils {
|
||||||
|
|
||||||
|
public static final Property.Name[] getAllPropset() {
|
||||||
|
return PropertyUtils.INSTANCE.getAllPropSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Property.Name[] getQuotaPropSet() {
|
||||||
|
return PropertyUtils.INSTANCE.getQuotaPropset();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MkCol calls wrapper
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class MkColMethod extends DavMethod {
|
||||||
|
public MkColMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws Exception {
|
||||||
|
mDavResource.mkCol(null, response -> {
|
||||||
|
mResponse = response;
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
return super.getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move calls wrapper
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class MoveMethod extends DavMethod {
|
||||||
|
final String destinationUrl;
|
||||||
|
final boolean forceOverride;
|
||||||
|
|
||||||
|
public MoveMethod(URL url, String destinationUrl, boolean forceOverride) {
|
||||||
|
super(url);
|
||||||
|
this.destinationUrl = destinationUrl;
|
||||||
|
this.forceOverride = forceOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws Exception {
|
||||||
|
mDavResource.move(
|
||||||
|
destinationUrl,
|
||||||
|
forceOverride,
|
||||||
|
super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER),
|
||||||
|
super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> {
|
||||||
|
mResponse = response;
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
return super.getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.Property;
|
||||||
|
import at.bitfire.dav4android.Response;
|
||||||
|
import at.bitfire.dav4android.exception.DavException;
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propfind calls wrapper
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class PropfindMethod extends DavMethod {
|
||||||
|
|
||||||
|
// request
|
||||||
|
private final int mDepth;
|
||||||
|
private final Property.Name[] mPropertiesToRequest;
|
||||||
|
|
||||||
|
// response
|
||||||
|
private final List<Response> mMembers;
|
||||||
|
private Response mRoot;
|
||||||
|
|
||||||
|
public PropfindMethod(URL url, int depth, Property.Name[] propertiesToRequest) {
|
||||||
|
super(url);
|
||||||
|
mDepth = depth;
|
||||||
|
mPropertiesToRequest = propertiesToRequest;
|
||||||
|
mMembers = new ArrayList<>();
|
||||||
|
mRoot = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException, DavException{
|
||||||
|
mDavResource.propfind(mDepth, mPropertiesToRequest,
|
||||||
|
(Response response, Response.HrefRelation hrefRelation) -> {
|
||||||
|
switch (hrefRelation) {
|
||||||
|
case MEMBER:
|
||||||
|
mMembers.add(response);
|
||||||
|
break;
|
||||||
|
case SELF:
|
||||||
|
mRoot = response;
|
||||||
|
break;
|
||||||
|
case OTHER:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
}, response -> {
|
||||||
|
mResponse = response;
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
return getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDepth() {
|
||||||
|
return mDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Response> getMembers() {
|
||||||
|
return mMembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response getRoot() {
|
||||||
|
return mRoot;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.http.methods.webdav;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put calls wrapper
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class PutMethod extends DavMethod {
|
||||||
|
|
||||||
|
public PutMethod(URL url) {
|
||||||
|
super(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onExecute() throws IOException, HttpException {
|
||||||
|
mDavResource.put(
|
||||||
|
mRequestBody,
|
||||||
|
super.getRequestHeader(HttpConstants.IF_MATCH_HEADER),
|
||||||
|
super.getRequestHeader(HttpConstants.CONTENT_TYPE_HEADER),
|
||||||
|
super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER),
|
||||||
|
super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> {
|
||||||
|
mResponse = response;
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
return super.getStatusCode();
|
||||||
|
}
|
||||||
|
}
|
@ -1,344 +0,0 @@
|
|||||||
/* 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.common.network;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLException;
|
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
|
||||||
import javax.net.ssl.SSLParameters;
|
|
||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
|
||||||
import javax.net.ssl.SSLSession;
|
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.ConnectTimeoutException;
|
|
||||||
import org.apache.commons.httpclient.params.HttpConnectionParams;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
|
|
||||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with
|
|
||||||
* a custom SSLContext and an optional Hostname Verifier.
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class AdvancedSslSocketFactory implements SecureProtocolSocketFactory {
|
|
||||||
|
|
||||||
private static final String TAG = AdvancedSslSocketFactory.class.getSimpleName();
|
|
||||||
|
|
||||||
private SSLContext mSslContext = null;
|
|
||||||
private AdvancedX509TrustManager mTrustManager = null;
|
|
||||||
private X509HostnameVerifier mHostnameVerifier = null;
|
|
||||||
|
|
||||||
public SSLContext getSslContext() {
|
|
||||||
return mSslContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for AdvancedSSLProtocolSocketFactory.
|
|
||||||
*/
|
|
||||||
public AdvancedSslSocketFactory(
|
|
||||||
SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier
|
|
||||||
) {
|
|
||||||
|
|
||||||
if (sslContext == null)
|
|
||||||
throw new IllegalArgumentException("AdvancedSslSocketFactory can not be created with a null SSLContext");
|
|
||||||
if (trustManager == null && mHostnameVerifier != null)
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"AdvancedSslSocketFactory can not be created with a null Trust Manager and a " +
|
|
||||||
"not null Hostname Verifier"
|
|
||||||
);
|
|
||||||
mSslContext = sslContext;
|
|
||||||
mTrustManager = trustManager;
|
|
||||||
mHostnameVerifier = hostnameVerifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ProtocolSocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
|
|
||||||
Socket socket = mSslContext.getSocketFactory().createSocket(host, port, clientHost, clientPort);
|
|
||||||
enableSecureProtocols(socket);
|
|
||||||
verifyPeerIdentity(host, port, socket);
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private void logSslInfo() {
|
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
|
|
||||||
Log_OC.v(TAG, "SUPPORTED SSL PARAMETERS");
|
|
||||||
logSslParameters(mSslContext.getSupportedSSLParameters());
|
|
||||||
Log_OC.v(TAG, "DEFAULT SSL PARAMETERS");
|
|
||||||
logSslParameters(mSslContext.getDefaultSSLParameters());
|
|
||||||
Log_OC.i(TAG, "CURRENT PARAMETERS");
|
|
||||||
Log_OC.i(TAG, "Protocol: " + mSslContext.getProtocol());
|
|
||||||
}
|
|
||||||
Log_OC.i(TAG, "PROVIDER");
|
|
||||||
logSecurityProvider(mSslContext.getProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logSecurityProvider(Provider provider) {
|
|
||||||
Log_OC.i(TAG, "name: " + provider.getName());
|
|
||||||
Log_OC.i(TAG, "version: " + provider.getVersion());
|
|
||||||
Log_OC.i(TAG, "info: " + provider.getInfo());
|
|
||||||
Enumeration<?> keys = provider.propertyNames();
|
|
||||||
String key;
|
|
||||||
while (keys.hasMoreElements()) {
|
|
||||||
key = (String) keys.nextElement();
|
|
||||||
Log_OC.i(TAG, " property " + key + " : " + provider.getProperty(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logSslParameters(SSLParameters params) {
|
|
||||||
Log_OC.v(TAG, "Cipher suites: ");
|
|
||||||
String [] elements = params.getCipherSuites();
|
|
||||||
for (int i=0; i<elements.length ; i++) {
|
|
||||||
Log_OC.v(TAG, " " + elements[i]);
|
|
||||||
}
|
|
||||||
Log_OC.v(TAG, "Protocols: ");
|
|
||||||
elements = params.getProtocols();
|
|
||||||
for (int i=0; i<elements.length ; i++) {
|
|
||||||
Log_OC.v(TAG, " " + elements[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to get a new socket connection to the given host within the
|
|
||||||
* given time limit.
|
|
||||||
*
|
|
||||||
* @param host the host name/IP
|
|
||||||
* @param port the port on the host
|
|
||||||
* @param localAddress the local host name/IP to bind the socket to
|
|
||||||
* @param localPort the port on the local machine
|
|
||||||
* @param params {@link HttpConnectionParams Http connection parameters}
|
|
||||||
* @return Socket a new socket
|
|
||||||
* @throws IOException if an I/O error occurs while creating the socket
|
|
||||||
* @throws UnknownHostException if the IP address of the host cannot be
|
|
||||||
* determined
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(final String host, final int port,
|
|
||||||
final InetAddress localAddress, final int localPort,
|
|
||||||
final HttpConnectionParams params) throws IOException,
|
|
||||||
UnknownHostException, ConnectTimeoutException {
|
|
||||||
Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port + ", local " + localAddress + ":" +
|
|
||||||
localPort + ", params: " + params);
|
|
||||||
if (params == null) {
|
|
||||||
throw new IllegalArgumentException("Parameters may not be null");
|
|
||||||
}
|
|
||||||
int timeout = params.getConnectionTimeout();
|
|
||||||
|
|
||||||
//logSslInfo();
|
|
||||||
|
|
||||||
SocketFactory socketfactory = mSslContext.getSocketFactory();
|
|
||||||
Log_OC.d(TAG, " ... with connection timeout " + timeout + " and socket timeout " + params.getSoTimeout());
|
|
||||||
Socket socket = socketfactory.createSocket();
|
|
||||||
enableSecureProtocols(socket);
|
|
||||||
SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
|
|
||||||
SocketAddress remoteaddr = new InetSocketAddress(host, port);
|
|
||||||
socket.setSoTimeout(params.getSoTimeout());
|
|
||||||
WriteTimeoutEnforcer.setSoWriteTimeout(params.getSoTimeout(), socket);
|
|
||||||
socket.bind(localaddr);
|
|
||||||
ServerNameIndicator.setServerNameIndication(host, (SSLSocket) socket);
|
|
||||||
socket.connect(remoteaddr, timeout);
|
|
||||||
verifyPeerIdentity(host, port, socket);
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ProtocolSocketFactory#createSocket(java.lang.String, int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(String host, int port) throws IOException,
|
|
||||||
UnknownHostException {
|
|
||||||
Log_OC.d(TAG, "Creating SSL Socket with remote " + host + ":" + port);
|
|
||||||
Socket socket = mSslContext.getSocketFactory().createSocket(host, port);
|
|
||||||
enableSecureProtocols(socket);
|
|
||||||
verifyPeerIdentity(host, port, socket);
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
|
|
||||||
UnknownHostException {
|
|
||||||
Socket sslSocket = mSslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
|
|
||||||
enableSecureProtocols(sslSocket);
|
|
||||||
verifyPeerIdentity(host, port, sslSocket);
|
|
||||||
return sslSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return ((obj != null) && obj.getClass().equals(
|
|
||||||
AdvancedSslSocketFactory.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return AdvancedSslSocketFactory.class.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public X509HostnameVerifier getHostNameVerifier() {
|
|
||||||
return mHostnameVerifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setHostNameVerifier(X509HostnameVerifier hostnameVerifier) {
|
|
||||||
mHostnameVerifier = hostnameVerifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the identity of the server.
|
|
||||||
*
|
|
||||||
* The server certificate is verified first.
|
|
||||||
*
|
|
||||||
* Then, the host name is compared with the content of the server certificate using the current host name verifier,
|
|
||||||
* if any.
|
|
||||||
*
|
|
||||||
* @param socket
|
|
||||||
*/
|
|
||||||
private void verifyPeerIdentity(String host, int port, Socket socket) throws IOException {
|
|
||||||
try {
|
|
||||||
CertificateCombinedException failInHandshake = null;
|
|
||||||
/// 1. VERIFY THE SERVER CERTIFICATE through the registered TrustManager
|
|
||||||
/// (that should be an instance of AdvancedX509TrustManager)
|
|
||||||
try {
|
|
||||||
SSLSocket sock = (SSLSocket) socket; // a new SSLSession instance is created as a "side effect"
|
|
||||||
sock.startHandshake();
|
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
|
|
||||||
if (e instanceof CertificateCombinedException) {
|
|
||||||
failInHandshake = (CertificateCombinedException) e;
|
|
||||||
} else {
|
|
||||||
Throwable cause = e.getCause();
|
|
||||||
Throwable previousCause = null;
|
|
||||||
while (cause != null &&
|
|
||||||
cause != previousCause &&
|
|
||||||
!(cause instanceof CertificateCombinedException)) {
|
|
||||||
previousCause = cause;
|
|
||||||
cause = cause.getCause();
|
|
||||||
}
|
|
||||||
if (cause != null && cause instanceof CertificateCombinedException) {
|
|
||||||
failInHandshake = (CertificateCombinedException) cause;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (failInHandshake == null) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
failInHandshake.setHostInUrl(host);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 2. VERIFY HOSTNAME
|
|
||||||
SSLSession newSession = null;
|
|
||||||
boolean verifiedHostname = true;
|
|
||||||
if (mHostnameVerifier != null) {
|
|
||||||
if (failInHandshake != null) {
|
|
||||||
/// 2.1 : a new SSLSession instance was NOT created in the handshake
|
|
||||||
X509Certificate serverCert = failInHandshake.getServerCertificate();
|
|
||||||
try {
|
|
||||||
mHostnameVerifier.verify(host, serverCert);
|
|
||||||
} catch (SSLException e) {
|
|
||||||
verifiedHostname = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/// 2.2 : a new SSLSession instance was created in the handshake
|
|
||||||
newSession = ((SSLSocket) socket).getSession();
|
|
||||||
if (!mTrustManager.isKnownServer((X509Certificate) (newSession.getPeerCertificates()[0]))) {
|
|
||||||
verifiedHostname = mHostnameVerifier.verify(host, newSession);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 3. Combine the exceptions to throw, if any
|
|
||||||
if (!verifiedHostname) {
|
|
||||||
SSLPeerUnverifiedException pue = new SSLPeerUnverifiedException(
|
|
||||||
"Names in the server certificate do not match to " + host + " in the URL"
|
|
||||||
);
|
|
||||||
if (failInHandshake == null) {
|
|
||||||
failInHandshake = new CertificateCombinedException(
|
|
||||||
(X509Certificate) newSession.getPeerCertificates()[0]
|
|
||||||
);
|
|
||||||
failInHandshake.setHostInUrl(host);
|
|
||||||
}
|
|
||||||
failInHandshake.setSslPeerUnverifiedException(pue);
|
|
||||||
pue.initCause(failInHandshake);
|
|
||||||
throw pue;
|
|
||||||
|
|
||||||
} else if (failInHandshake != null) {
|
|
||||||
SSLHandshakeException hse = new SSLHandshakeException("Server certificate could not be verified");
|
|
||||||
hse.initCause(failInHandshake);
|
|
||||||
throw hse;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException io) {
|
|
||||||
try {
|
|
||||||
socket.close();
|
|
||||||
} catch (Exception x) {
|
|
||||||
// NOTHING - irrelevant exception for the caller
|
|
||||||
}
|
|
||||||
throw io;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grants that all protocols supported by the Security Provider in mSslContext are enabled in socket.
|
|
||||||
*
|
|
||||||
* Grants also that no unsupported protocol is tried to be enabled. That would trigger an exception, breaking
|
|
||||||
* the connection process although some protocols are supported.
|
|
||||||
*
|
|
||||||
* This is not cosmetic: not all the supported protocols are enabled by default. Too see an overview of
|
|
||||||
* supported and enabled protocols in the stock Security Provider in Android see the tables in
|
|
||||||
* http://developer.android.com/reference/javax/net/ssl/SSLSocket.html.
|
|
||||||
*
|
|
||||||
* @param socket
|
|
||||||
*/
|
|
||||||
private void enableSecureProtocols(Socket socket) {
|
|
||||||
SSLParameters params = mSslContext.getSupportedSSLParameters();
|
|
||||||
String[] supportedProtocols = params.getProtocols();
|
|
||||||
((SSLSocket) socket).setEnabledProtocols(supportedProtocols);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -100,7 +100,7 @@ public class AdvancedX509TrustManager implements X509TrustManager {
|
|||||||
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
|
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
|
||||||
* String authType)
|
* String authType)
|
||||||
*/
|
*/
|
||||||
public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
|
public void checkServerTrusted(X509Certificate[] certificates, String authType) {
|
||||||
if (!isKnownServer(certificates[0])) {
|
if (!isKnownServer(certificates[0])) {
|
||||||
CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
|
CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
|
||||||
try {
|
try {
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -24,64 +24,51 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.network;
|
package com.owncloud.android.lib.common.network;
|
||||||
|
|
||||||
import java.io.File;
|
import android.util.Log;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.methods.RequestEntity;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okio.BufferedSink;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RequestEntity that represents a PIECE of a file.
|
* A Request body that represents a file chunk and include information about the progress when uploading it
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
|
public class ChunkFromFileRequestBody extends FileRequestBody {
|
||||||
|
|
||||||
|
private static final String TAG = ChunkFromFileRequestBody.class.getSimpleName();
|
||||||
|
|
||||||
private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
|
|
||||||
|
|
||||||
//private final File mFile;
|
//private final File mFile;
|
||||||
private final FileChannel mChannel;
|
private final FileChannel mChannel;
|
||||||
private final String mContentType;
|
|
||||||
private final long mChunkSize;
|
private final long mChunkSize;
|
||||||
private final File mFile;
|
|
||||||
private long mOffset;
|
private long mOffset;
|
||||||
private long mTransferred;
|
private long mTransferred;
|
||||||
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
|
||||||
private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
|
private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
|
||||||
|
|
||||||
public ChunkFromFileChannelRequestEntity(
|
public ChunkFromFileRequestBody(File file, MediaType contentType, FileChannel channel, long chunkSize) {
|
||||||
final FileChannel channel, final String contentType, long chunkSize, final File file
|
super(file, contentType);
|
||||||
) {
|
|
||||||
super();
|
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
throw new IllegalArgumentException("File may not be null");
|
throw new IllegalArgumentException("File may not be null");
|
||||||
}
|
}
|
||||||
if (chunkSize <= 0) {
|
if (chunkSize <= 0) {
|
||||||
throw new IllegalArgumentException("Chunk size must be greater than zero");
|
throw new IllegalArgumentException("Chunk size must be greater than zero");
|
||||||
}
|
}
|
||||||
mChannel = channel;
|
this.mChannel = channel;
|
||||||
mContentType = contentType;
|
this.mChunkSize = chunkSize;
|
||||||
mChunkSize = chunkSize;
|
|
||||||
mFile = file;
|
|
||||||
mOffset = 0;
|
mOffset = 0;
|
||||||
mTransferred = 0;
|
mTransferred = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOffset(long offset) {
|
@Override
|
||||||
mOffset = offset;
|
public long contentLength() {
|
||||||
}
|
|
||||||
|
|
||||||
public long getContentLength() {
|
|
||||||
try {
|
try {
|
||||||
return Math.min(mChunkSize, mChannel.size() - mChannel.position());
|
return Math.min(mChunkSize, mChannel.size() - mChannel.position());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -89,39 +76,10 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity, Progres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContentType() {
|
|
||||||
return mContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRepeatable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
public void writeTo(BufferedSink sink) {
|
||||||
synchronized (mDataTransferListeners) {
|
int readCount;
|
||||||
mDataTransferListeners.add(listener);
|
Iterator<OnDatatransferProgressListener> it;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
mDataTransferListeners.addAll(listeners);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
mDataTransferListeners.remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void writeRequest(final OutputStream out) throws IOException {
|
|
||||||
int readCount = 0;
|
|
||||||
Iterator<OnDatatransferProgressListener> it = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mChannel.position(mOffset);
|
mChannel.position(mOffset);
|
||||||
@ -129,13 +87,20 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity, Progres
|
|||||||
if (size == 0) size = -1;
|
if (size == 0) size = -1;
|
||||||
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
|
||||||
while (mChannel.position() < maxCount) {
|
while (mChannel.position() < maxCount) {
|
||||||
|
|
||||||
|
|
||||||
|
Log_OC.d(TAG, "Sink buffer size: " + sink.buffer().size());
|
||||||
|
|
||||||
readCount = mChannel.read(mBuffer);
|
readCount = mChannel.read(mBuffer);
|
||||||
try {
|
|
||||||
out.write(mBuffer.array(), 0, readCount);
|
Log_OC.d(TAG, "Read " + readCount + " bytes from file channel to " + mBuffer.toString());
|
||||||
} catch (IOException io) {
|
|
||||||
// work-around try catch to filter exception in writing
|
sink.buffer().write(mBuffer.array(), 0 ,readCount);
|
||||||
throw new FileRequestEntity.WriteException(io);
|
|
||||||
}
|
sink.flush();
|
||||||
|
|
||||||
|
Log_OC.d(TAG, "Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size());
|
||||||
|
|
||||||
mBuffer.clear();
|
mBuffer.clear();
|
||||||
if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
|
if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
|
||||||
mTransferred += readCount;
|
mTransferred += readCount;
|
||||||
@ -148,20 +113,23 @@ public class ChunkFromFileChannelRequestEntity implements RequestEntity, Progres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException io) {
|
Log.d(TAG, "Chunk with size " + mChunkSize + " written in request body");
|
||||||
// any read problem will be handled as if the file is not there
|
|
||||||
if (io instanceof FileNotFoundException) {
|
|
||||||
throw io;
|
|
||||||
} else {
|
|
||||||
FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
|
|
||||||
fnf.initCause(io);
|
|
||||||
throw fnf;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (FileRequestEntity.WriteException we) {
|
} catch (Exception exception) {
|
||||||
throw we.getWrapped();
|
|
||||||
|
Log.e(TAG, exception.toString());
|
||||||
|
// // any read problem will be handled as if the file is not there
|
||||||
|
// if (io instanceof FileNotFoundException) {
|
||||||
|
// throw io;
|
||||||
|
// } else {
|
||||||
|
// FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
|
||||||
|
// fnf.initCause(io);
|
||||||
|
// throw fnf;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOffset(long offset) {
|
||||||
|
this.mOffset = offset;
|
||||||
|
}
|
||||||
}
|
}
|
120
src/com/owncloud/android/lib/common/network/FileRequestBody.java
Normal file
120
src/com/owncloud/android/lib/common/network/FileRequestBody.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.network;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okio.BufferedSink;
|
||||||
|
import okio.Okio;
|
||||||
|
import okio.Source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Request body that represents a file and include information about the progress when uploading it
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class FileRequestBody extends RequestBody implements ProgressiveDataTransferer {
|
||||||
|
|
||||||
|
private static final String TAG = FileRequestBody.class.getSimpleName();
|
||||||
|
|
||||||
|
protected File mFile;
|
||||||
|
private MediaType mContentType;
|
||||||
|
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<>();
|
||||||
|
|
||||||
|
public FileRequestBody(File file, MediaType contentType) {
|
||||||
|
mFile = file;
|
||||||
|
mContentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaType contentType() {
|
||||||
|
return mContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long contentLength() {
|
||||||
|
return mFile.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(BufferedSink sink) {
|
||||||
|
Source source;
|
||||||
|
Iterator<OnDatatransferProgressListener> it;
|
||||||
|
try {
|
||||||
|
source = Okio.source(mFile);
|
||||||
|
|
||||||
|
long transferred = 0;
|
||||||
|
long read;
|
||||||
|
|
||||||
|
while ((read = source.read(sink.buffer(), 4096)) != -1) {
|
||||||
|
transferred += read;
|
||||||
|
sink.flush();
|
||||||
|
synchronized (mDataTransferListeners) {
|
||||||
|
it = mDataTransferListeners.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next().onTransferProgress(read, transferred, mFile.length(), mFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "File with name " + mFile.getName() + " and size " + mFile.length() +
|
||||||
|
" written in request body");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||||
|
synchronized (mDataTransferListeners) {
|
||||||
|
mDataTransferListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
|
||||||
|
synchronized (mDataTransferListeners) {
|
||||||
|
mDataTransferListeners.addAll(listeners);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
||||||
|
synchronized (mDataTransferListeners) {
|
||||||
|
mDataTransferListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,166 +0,0 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
|
||||||
* Copyright (C) 2016 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.common.network;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.methods.RequestEntity;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A RequestEntity that represents a File.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
|
|
||||||
|
|
||||||
final File mFile;
|
|
||||||
final String mContentType;
|
|
||||||
Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
|
||||||
|
|
||||||
public FileRequestEntity(final File file, final String contentType) {
|
|
||||||
super();
|
|
||||||
this.mFile = file;
|
|
||||||
this.mContentType = contentType;
|
|
||||||
if (file == null) {
|
|
||||||
throw new IllegalArgumentException("File may not be null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getContentLength() {
|
|
||||||
return mFile.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getContentType() {
|
|
||||||
return mContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRepeatable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
mDataTransferListeners.add(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
mDataTransferListeners.addAll(listeners);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
mDataTransferListeners.remove(listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeRequest(final OutputStream out) throws IOException {
|
|
||||||
ByteBuffer tmp = ByteBuffer.allocate(4096);
|
|
||||||
int readResult = 0;
|
|
||||||
|
|
||||||
RandomAccessFile raf = new RandomAccessFile(mFile, "r");
|
|
||||||
FileChannel channel = raf.getChannel();
|
|
||||||
Iterator<OnDatatransferProgressListener> it = null;
|
|
||||||
long transferred = 0;
|
|
||||||
long size = mFile.length();
|
|
||||||
if (size == 0) size = -1;
|
|
||||||
try {
|
|
||||||
while ((readResult = channel.read(tmp)) >= 0) {
|
|
||||||
try {
|
|
||||||
out.write(tmp.array(), 0, readResult);
|
|
||||||
} catch (IOException io) {
|
|
||||||
// work-around try catch to filter exception in writing
|
|
||||||
throw new WriteException(io);
|
|
||||||
}
|
|
||||||
tmp.clear();
|
|
||||||
transferred += readResult;
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
it = mDataTransferListeners.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next().onTransferProgress(readResult, transferred, size, mFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException io) {
|
|
||||||
// any read problem will be handled as if the file is not there
|
|
||||||
if (io instanceof FileNotFoundException) {
|
|
||||||
throw io;
|
|
||||||
} else {
|
|
||||||
FileNotFoundException fnf = new FileNotFoundException("Exception reading source file");
|
|
||||||
fnf.initCause(io);
|
|
||||||
throw fnf;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (WriteException we) {
|
|
||||||
throw we.getWrapped();
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
channel.close();
|
|
||||||
raf.close();
|
|
||||||
} catch (IOException io) {
|
|
||||||
// ignore failures closing source file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class WriteException extends Exception {
|
|
||||||
IOException mWrapped;
|
|
||||||
|
|
||||||
WriteException(IOException wrapped) {
|
|
||||||
mWrapped = wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IOException getWrapped() {
|
|
||||||
return mWrapped;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -29,19 +29,13 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
|
|
||||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -64,67 +58,7 @@ public class NetworkUtils {
|
|||||||
/** Standard name for protocol TLS version 1.0 in JSSE API */
|
/** Standard name for protocol TLS version 1.0 in JSSE API */
|
||||||
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
|
public static final String PROTOCOL_TLSv1_0 = "TLSv1";
|
||||||
|
|
||||||
/** Connection manager for all the OwnCloudClients */
|
|
||||||
private static MultiThreadedHttpConnectionManager mConnManager = null;
|
|
||||||
|
|
||||||
private static Protocol mDefaultHttpsProtocol = null;
|
|
||||||
|
|
||||||
private static AdvancedSslSocketFactory mAdvancedSslSocketFactory = null;
|
|
||||||
|
|
||||||
private static X509HostnameVerifier mHostnameVerifier = null;
|
private static X509HostnameVerifier mHostnameVerifier = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers or unregisters the proper components for advanced SSL handling.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void registerAdvancedSslContext(boolean register, Context context)
|
|
||||||
throws GeneralSecurityException, IOException {
|
|
||||||
Protocol pr = null;
|
|
||||||
try {
|
|
||||||
pr = Protocol.getProtocol("https");
|
|
||||||
if (pr != null && mDefaultHttpsProtocol == null) {
|
|
||||||
mDefaultHttpsProtocol = pr;
|
|
||||||
}
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
// nothing to do here; really
|
|
||||||
}
|
|
||||||
boolean isRegistered = (pr != null && pr.getSocketFactory() instanceof AdvancedSslSocketFactory);
|
|
||||||
if (register && !isRegistered) {
|
|
||||||
Protocol.registerProtocol("https", new Protocol("https", getAdvancedSslSocketFactory(context), 443));
|
|
||||||
|
|
||||||
} else if (!register && isRegistered) {
|
|
||||||
if (mDefaultHttpsProtocol != null) {
|
|
||||||
Protocol.registerProtocol("https", mDefaultHttpsProtocol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context)
|
|
||||||
throws GeneralSecurityException, IOException {
|
|
||||||
if (mAdvancedSslSocketFactory == null) {
|
|
||||||
KeyStore trustStore = getKnownServersStore(context);
|
|
||||||
AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
|
|
||||||
TrustManager[] tms = new TrustManager[] { trustMgr };
|
|
||||||
|
|
||||||
SSLContext sslContext;
|
|
||||||
try {
|
|
||||||
sslContext = SSLContext.getInstance("TLSv1.2");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
Log_OC.w(TAG, "TLSv1.2 is not supported in this device; falling through TLSv1.0");
|
|
||||||
sslContext = SSLContext.getInstance("TLSv1");
|
|
||||||
// should be available in any device; see reference of supported protocols in
|
|
||||||
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
|
|
||||||
}
|
|
||||||
sslContext.init(null, tms, null);
|
|
||||||
|
|
||||||
mHostnameVerifier = new BrowserCompatHostnameVerifier();
|
|
||||||
mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
|
|
||||||
}
|
|
||||||
return mAdvancedSslSocketFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
|
private static String LOCAL_TRUSTSTORE_FILENAME = "knownServers.bks";
|
||||||
|
|
||||||
@ -147,7 +81,7 @@ public class NetworkUtils {
|
|||||||
* @throws CertificateException When an exception occurred while loading the certificates from the local
|
* @throws CertificateException When an exception occurred while loading the certificates from the local
|
||||||
* trust store.
|
* trust store.
|
||||||
*/
|
*/
|
||||||
private static KeyStore getKnownServersStore(Context context)
|
public static KeyStore getKnownServersStore(Context context)
|
||||||
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
|
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
|
||||||
if (mKnownServersStore == null) {
|
if (mKnownServersStore == null) {
|
||||||
//mKnownServersStore = KeyStore.getInstance("BKS");
|
//mKnownServersStore = KeyStore.getInstance("BKS");
|
||||||
@ -183,16 +117,6 @@ public class NetworkUtils {
|
|||||||
fos.close();
|
fos.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static public MultiThreadedHttpConnectionManager getMultiThreadedConnManager() {
|
|
||||||
if (mConnManager == null) {
|
|
||||||
mConnManager = new MultiThreadedHttpConnectionManager();
|
|
||||||
mConnManager.getParams().setDefaultMaxConnectionsPerHost(5);
|
|
||||||
mConnManager.getParams().setMaxTotalConnections(5);
|
|
||||||
}
|
|
||||||
return mConnManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isCertInKnownServersStore(Certificate cert, Context context)
|
public static boolean isCertInKnownServersStore(Certificate cert, Context context)
|
||||||
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||||
|
@ -26,5 +26,5 @@
|
|||||||
package com.owncloud.android.lib.common.network;
|
package com.owncloud.android.lib.common.network;
|
||||||
|
|
||||||
public interface OnDatatransferProgressListener {
|
public interface OnDatatransferProgressListener {
|
||||||
public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileAbsoluteName);
|
void onTransferProgress(long read, long transferred, long percent, String absolutePath);
|
||||||
}
|
}
|
@ -27,7 +27,6 @@ package com.owncloud.android.lib.common.network;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface ProgressiveDataTransferer {
|
public interface ProgressiveDataTransferer {
|
||||||
|
|
||||||
public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
|
public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
|
||||||
|
@ -27,14 +27,16 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.network;
|
package com.owncloud.android.lib.common.network;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
|
* Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
|
||||||
* {@link com.owncloud.android.lib.common.operations.RemoteOperation}, and the status codes corresponding to all
|
* {@link RemoteOperation}, and the status codes corresponding to all
|
||||||
* of them.
|
* of them.
|
||||||
*
|
*
|
||||||
* The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
|
* The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
|
||||||
@ -108,7 +110,7 @@ public class RedirectionPath {
|
|||||||
*/
|
*/
|
||||||
public String getLastPermanentLocation() {
|
public String getLastPermanentLocation() {
|
||||||
for (int i = mLastStatus; i >= 0; i--) {
|
for (int i = mLastStatus; i >= 0; i--) {
|
||||||
if (mStatuses[i] == HttpStatus.SC_MOVED_PERMANENTLY && i <= mLastLocation) {
|
if (mStatuses[i] == HttpConstants.HTTP_MOVED_PERMANENTLY && i <= mLastLocation) {
|
||||||
return mLocations[i];
|
return mLocations[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,276 +0,0 @@
|
|||||||
/** ownCloud Android Library is available under MIT license
|
|
||||||
*
|
|
||||||
* @author Christian Schabesberger
|
|
||||||
* Copyright (C) 2018 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.common.network;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.webdav.MultiStatusResponse;
|
|
||||||
import org.apache.jackrabbit.webdav.property.DavProperty;
|
|
||||||
import org.apache.jackrabbit.webdav.property.DavPropertyName;
|
|
||||||
import org.apache.jackrabbit.webdav.property.DavPropertySet;
|
|
||||||
import org.apache.jackrabbit.webdav.xml.Namespace;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
|
|
||||||
public class WebdavEntry {
|
|
||||||
|
|
||||||
private static final String TAG = WebdavEntry.class.getSimpleName();
|
|
||||||
|
|
||||||
public static final String NAMESPACE_OC = "http://owncloud.org/ns";
|
|
||||||
public static final String EXTENDED_PROPERTY_NAME_PERMISSIONS = "permissions";
|
|
||||||
public static final String EXTENDED_PROPERTY_NAME_REMOTE_ID = "id";
|
|
||||||
public static final String EXTENDED_PROPERTY_NAME_SIZE = "size";
|
|
||||||
public static final String EXTENDED_PROPERTY_NAME_PRIVATE_LINK = "privatelink";
|
|
||||||
|
|
||||||
public static final String PROPERTY_QUOTA_USED_BYTES = "quota-used-bytes";
|
|
||||||
public static final String PROPERTY_QUOTA_AVAILABLE_BYTES = "quota-available-bytes";
|
|
||||||
|
|
||||||
private static final int CODE_PROP_NOT_FOUND = 404;
|
|
||||||
|
|
||||||
private String mName, mPath, mUri, mContentType, mEtag, mPermissions, mRemoteId, mPrivateLink;
|
|
||||||
private long mContentLength, mCreateTimestamp, mModifiedTimestamp, mSize;
|
|
||||||
private BigDecimal mQuotaUsedBytes, mQuotaAvailableBytes;
|
|
||||||
|
|
||||||
public WebdavEntry(MultiStatusResponse ms, String splitElement) {
|
|
||||||
resetData();
|
|
||||||
if (ms.getStatus().length != 0) {
|
|
||||||
mUri = ms.getHref();
|
|
||||||
|
|
||||||
mPath = mUri.split(splitElement, 2)[1];
|
|
||||||
|
|
||||||
int status = ms.getStatus()[0].getStatusCode();
|
|
||||||
if (status == CODE_PROP_NOT_FOUND) {
|
|
||||||
status = ms.getStatus()[1].getStatusCode();
|
|
||||||
}
|
|
||||||
DavPropertySet propSet = ms.getProperties(status);
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
DavProperty prop = propSet.get(DavPropertyName.DISPLAYNAME);
|
|
||||||
if (prop != null) {
|
|
||||||
mName = (String) prop.getName().toString();
|
|
||||||
mName = mName.substring(1, mName.length() - 1);
|
|
||||||
} else {
|
|
||||||
String[] tmp = mPath.split("/");
|
|
||||||
if (tmp.length > 0)
|
|
||||||
mName = tmp[tmp.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// use unknown mimetype as default behavior
|
|
||||||
// {DAV:}getcontenttype
|
|
||||||
mContentType = "application/octet-stream";
|
|
||||||
prop = propSet.get(DavPropertyName.GETCONTENTTYPE);
|
|
||||||
if (prop != null) {
|
|
||||||
mContentType = (String) prop.getValue();
|
|
||||||
// dvelasco: some builds of ownCloud server 4.0.x added a trailing ';'
|
|
||||||
// to the MIME type ; if looks fixed, but let's be cautious
|
|
||||||
if (mContentType.indexOf(";") >= 0) {
|
|
||||||
mContentType = mContentType.substring(0, mContentType.indexOf(";"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it's a folder in the standard way: see RFC2518 12.2 . RFC4918 14.3
|
|
||||||
// {DAV:}resourcetype
|
|
||||||
prop = propSet.get(DavPropertyName.RESOURCETYPE);
|
|
||||||
if (prop != null) {
|
|
||||||
Object value = prop.getValue();
|
|
||||||
if (value != null) {
|
|
||||||
mContentType = "DIR"; // a specific attribute would be better,
|
|
||||||
// but this is enough;
|
|
||||||
// unless while we have no reason to distinguish
|
|
||||||
// MIME types for folders
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// {DAV:}getcontentlength
|
|
||||||
prop = propSet.get(DavPropertyName.GETCONTENTLENGTH);
|
|
||||||
if (prop != null)
|
|
||||||
mContentLength = Long.parseLong((String) prop.getValue());
|
|
||||||
|
|
||||||
// {DAV:}getlastmodified
|
|
||||||
prop = propSet.get(DavPropertyName.GETLASTMODIFIED);
|
|
||||||
if (prop != null) {
|
|
||||||
Date d = WebdavUtils
|
|
||||||
.parseResponseDate((String) prop.getValue());
|
|
||||||
mModifiedTimestamp = (d != null) ? d.getTime() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
prop = propSet.get(DavPropertyName.CREATIONDATE);
|
|
||||||
if (prop != null) {
|
|
||||||
Date d = WebdavUtils
|
|
||||||
.parseResponseDate((String) prop.getValue());
|
|
||||||
mCreateTimestamp = (d != null) ? d.getTime() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// {DAV:}getetag
|
|
||||||
prop = propSet.get(DavPropertyName.GETETAG);
|
|
||||||
if (prop != null) {
|
|
||||||
mEtag = (String) prop.getValue();
|
|
||||||
mEtag = WebdavUtils.parseEtag(mEtag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// {DAV:}quota-used-bytes
|
|
||||||
prop = propSet.get(DavPropertyName.create(PROPERTY_QUOTA_USED_BYTES));
|
|
||||||
if (prop != null) {
|
|
||||||
String quotaUsedBytesSt = (String) prop.getValue();
|
|
||||||
try {
|
|
||||||
mQuotaUsedBytes = new BigDecimal(quotaUsedBytesSt);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
Log_OC.w(TAG, "No value for QuotaUsedBytes - NumberFormatException");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
Log_OC.w(TAG, "No value for QuotaUsedBytes - NullPointerException");
|
|
||||||
}
|
|
||||||
Log_OC.d(TAG, "QUOTA_USED_BYTES " + quotaUsedBytesSt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// {DAV:}quota-available-bytes
|
|
||||||
prop = propSet.get(DavPropertyName.create(PROPERTY_QUOTA_AVAILABLE_BYTES));
|
|
||||||
if (prop != null) {
|
|
||||||
String quotaAvailableBytesSt = (String) prop.getValue();
|
|
||||||
try {
|
|
||||||
mQuotaAvailableBytes = new BigDecimal(quotaAvailableBytesSt);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
Log_OC.w(TAG, "No value for QuotaAvailableBytes - NumberFormatException");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
Log_OC.w(TAG, "No value for QuotaAvailableBytes");
|
|
||||||
}
|
|
||||||
Log_OC.d(TAG, "QUOTA_AVAILABLE_BYTES " + quotaAvailableBytesSt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// OC permissions property <oc:permissions>
|
|
||||||
prop = propSet.get(
|
|
||||||
EXTENDED_PROPERTY_NAME_PERMISSIONS, Namespace.getNamespace(NAMESPACE_OC)
|
|
||||||
);
|
|
||||||
if (prop != null && prop.getValue() != null) {
|
|
||||||
mPermissions = prop.getValue().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OC remote id property <oc:id>
|
|
||||||
prop = propSet.get(
|
|
||||||
EXTENDED_PROPERTY_NAME_REMOTE_ID, Namespace.getNamespace(NAMESPACE_OC)
|
|
||||||
);
|
|
||||||
if (prop != null) {
|
|
||||||
mRemoteId = prop.getValue().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// OC size property <oc:size>
|
|
||||||
prop = propSet.get(
|
|
||||||
EXTENDED_PROPERTY_NAME_SIZE, Namespace.getNamespace(NAMESPACE_OC)
|
|
||||||
);
|
|
||||||
if (prop != null) {
|
|
||||||
mSize = Long.parseLong((String) prop.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
// OC privatelink property <oc:privatelink>
|
|
||||||
prop = propSet.get(
|
|
||||||
EXTENDED_PROPERTY_NAME_PRIVATE_LINK, Namespace.getNamespace(NAMESPACE_OC)
|
|
||||||
);
|
|
||||||
if (prop != null) {
|
|
||||||
mPrivateLink = prop.getValue().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Log_OC.e("WebdavEntry",
|
|
||||||
"General fuckup, no status for webdav response");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String path() {
|
|
||||||
return mPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String decodedPath() {
|
|
||||||
return Uri.decode(mPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String name() {
|
|
||||||
return mName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirectory() {
|
|
||||||
return mContentType.equals("DIR");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String contentType() {
|
|
||||||
return mContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String uri() {
|
|
||||||
return mUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long contentLength() {
|
|
||||||
return mContentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long createTimestamp() {
|
|
||||||
return mCreateTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long modifiedTimestamp() {
|
|
||||||
return mModifiedTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String etag() {
|
|
||||||
return mEtag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String permissions() {
|
|
||||||
return mPermissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String remoteId() {
|
|
||||||
return mRemoteId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long size() {
|
|
||||||
return mSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal quotaUsedBytes() {
|
|
||||||
return mQuotaUsedBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal quotaAvailableBytes() {
|
|
||||||
return mQuotaAvailableBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String privateLink() {
|
|
||||||
return mPrivateLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetData() {
|
|
||||||
mName = mUri = mContentType = mPermissions = null;
|
|
||||||
mRemoteId = null;
|
|
||||||
mContentLength = mCreateTimestamp = mModifiedTimestamp = 0;
|
|
||||||
mSize = 0;
|
|
||||||
mQuotaUsedBytes = null;
|
|
||||||
mQuotaAvailableBytes = null;
|
|
||||||
mPrivateLink = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,11 +32,7 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Header;
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
|
||||||
import org.apache.jackrabbit.webdav.property.DavPropertyName;
|
|
||||||
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
|
|
||||||
import org.apache.jackrabbit.webdav.xml.Namespace;
|
|
||||||
|
|
||||||
public class WebdavUtils {
|
public class WebdavUtils {
|
||||||
public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
|
public static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat(
|
||||||
@ -85,72 +81,6 @@ public class WebdavUtils {
|
|||||||
return encodedPath;
|
return encodedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a DavPropertyNameSet with all prop
|
|
||||||
* For using instead of DavConstants.PROPFIND_ALL_PROP
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static DavPropertyNameSet getAllPropSet(){
|
|
||||||
DavPropertyNameSet propSet = new DavPropertyNameSet();
|
|
||||||
propSet.add(DavPropertyName.DISPLAYNAME);
|
|
||||||
propSet.add(DavPropertyName.GETCONTENTTYPE);
|
|
||||||
propSet.add(DavPropertyName.RESOURCETYPE);
|
|
||||||
propSet.add(DavPropertyName.GETCONTENTLENGTH);
|
|
||||||
propSet.add(DavPropertyName.GETLASTMODIFIED);
|
|
||||||
propSet.add(DavPropertyName.CREATIONDATE);
|
|
||||||
propSet.add(DavPropertyName.GETETAG);
|
|
||||||
propSet.add(DavPropertyName.create(WebdavEntry.PROPERTY_QUOTA_USED_BYTES));
|
|
||||||
propSet.add(DavPropertyName.create(WebdavEntry.PROPERTY_QUOTA_AVAILABLE_BYTES));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_PERMISSIONS,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_REMOTE_ID,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_SIZE,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_PRIVATE_LINK,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
|
|
||||||
return propSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a DavPropertyNameSet with properties for files
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static DavPropertyNameSet getFilePropSet(){
|
|
||||||
DavPropertyNameSet propSet = new DavPropertyNameSet();
|
|
||||||
propSet.add(DavPropertyName.DISPLAYNAME);
|
|
||||||
propSet.add(DavPropertyName.GETCONTENTTYPE);
|
|
||||||
propSet.add(DavPropertyName.RESOURCETYPE);
|
|
||||||
propSet.add(DavPropertyName.GETCONTENTLENGTH);
|
|
||||||
propSet.add(DavPropertyName.GETLASTMODIFIED);
|
|
||||||
propSet.add(DavPropertyName.CREATIONDATE);
|
|
||||||
propSet.add(DavPropertyName.GETETAG);
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_PERMISSIONS,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_REMOTE_ID,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_SIZE,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_SIZE,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_PRIVATE_LINK,
|
|
||||||
Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
|
|
||||||
|
|
||||||
return propSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a DavPropertyNameSet with properties for user quotas
|
|
||||||
* @return set of quota properties
|
|
||||||
*/
|
|
||||||
public static DavPropertyNameSet getQuotaPropSet() {
|
|
||||||
DavPropertyNameSet propSet = new DavPropertyNameSet();
|
|
||||||
propSet.add(DavPropertyName.create(WebdavEntry.PROPERTY_QUOTA_AVAILABLE_BYTES));
|
|
||||||
propSet.add(DavPropertyName.create(WebdavEntry.PROPERTY_QUOTA_USED_BYTES));
|
|
||||||
return propSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param rawEtag
|
* @param rawEtag
|
||||||
@ -169,28 +99,26 @@ public class WebdavUtils {
|
|||||||
return rawEtag;
|
return rawEtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param method
|
* @param httpBaseMethod from which to get the etag
|
||||||
* @return
|
* @return etag from response
|
||||||
*/
|
*/
|
||||||
public static String getEtagFromResponse(HttpMethod method) {
|
public static String getEtagFromResponse(HttpBaseMethod httpBaseMethod) {
|
||||||
Header eTag = method.getResponseHeader("OC-ETag");
|
String eTag = httpBaseMethod.getResponseHeader("OC-ETag");
|
||||||
if (eTag == null) {
|
if (eTag == null) {
|
||||||
eTag = method.getResponseHeader("oc-etag");
|
eTag = httpBaseMethod.getResponseHeader("oc-etag");
|
||||||
}
|
}
|
||||||
if (eTag == null) {
|
if (eTag == null) {
|
||||||
eTag = method.getResponseHeader("ETag");
|
eTag = httpBaseMethod.getResponseHeader("ETag");
|
||||||
}
|
}
|
||||||
if (eTag == null) {
|
if (eTag == null) {
|
||||||
eTag = method.getResponseHeader("etag");
|
eTag = httpBaseMethod.getResponseHeader("etag");
|
||||||
}
|
}
|
||||||
String result = "";
|
String result = "";
|
||||||
if (eTag != null) {
|
if (eTag != null) {
|
||||||
result = parseEtag(eTag.getValue());
|
result = eTag;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,27 +1,3 @@
|
|||||||
/* 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.common.operations;
|
package com.owncloud.android.lib.common.operations;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
@ -39,16 +15,9 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
/**
|
public abstract class RemoteOperation<T extends Object> implements Runnable {
|
||||||
* Operation which execution involves one or several interactions with an ownCloud server.
|
|
||||||
*
|
|
||||||
* Provides methods to execute the operation both synchronously or asynchronously.
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
|
||||||
* @author David González Verdugo
|
|
||||||
*/
|
|
||||||
public abstract class RemoteOperation implements Runnable {
|
|
||||||
|
|
||||||
private static final String TAG = RemoteOperation.class.getSimpleName();
|
private static final String TAG = RemoteOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -65,82 +34,32 @@ public abstract class RemoteOperation implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* ownCloud account in the remote ownCloud server to operate
|
* ownCloud account in the remote ownCloud server to operate
|
||||||
*/
|
*/
|
||||||
private Account mAccount = null;
|
protected Account mAccount = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android Application context
|
* Android Application context
|
||||||
*/
|
*/
|
||||||
private Context mContext = null;
|
protected Context mContext = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to interact with the remote server
|
* Object to interact with the remote server
|
||||||
*/
|
*/
|
||||||
private OwnCloudClient mClient = null;
|
protected OwnCloudClient mClient = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object to interact with the remote server
|
||||||
|
*/
|
||||||
|
protected OkHttpClient mHttpClient = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback object to notify about the execution of the remote operation
|
* Callback object to notify about the execution of the remote operation
|
||||||
*/
|
*/
|
||||||
private OnRemoteOperationListener mListener = null;
|
protected OnRemoteOperationListener mListener = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to the thread where mListener methods will be called
|
* Handler to the thread where mListener methods will be called
|
||||||
*/
|
*/
|
||||||
private Handler mListenerHandler = null;
|
protected Handler mListenerHandler = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract method to implement the operation in derived classes.
|
|
||||||
*/
|
|
||||||
protected abstract RemoteOperationResult run(OwnCloudClient client);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronously executes the remote operation on the received ownCloud account.
|
|
||||||
*
|
|
||||||
* Do not call this method from the main thread.
|
|
||||||
*
|
|
||||||
* This method should be used whenever an ownCloud account is available, instead of
|
|
||||||
* {@link #execute(OwnCloudClient)}.
|
|
||||||
*
|
|
||||||
* @param account ownCloud account in remote ownCloud server to reach during the
|
|
||||||
* execution of the operation.
|
|
||||||
* @param context Android context for the component calling the method.
|
|
||||||
* @return Result of the operation.
|
|
||||||
*/
|
|
||||||
public RemoteOperationResult execute(Account account, Context context) {
|
|
||||||
if (account == null)
|
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
|
||||||
"Account");
|
|
||||||
if (context == null)
|
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
|
||||||
"Context");
|
|
||||||
mAccount = account;
|
|
||||||
mContext = context.getApplicationContext();
|
|
||||||
|
|
||||||
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(OwnCloudClient client) {
|
|
||||||
if (client == null)
|
|
||||||
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
|
||||||
"OwnCloudClient");
|
|
||||||
mClient = client;
|
|
||||||
if (client.getAccount() != null) {
|
|
||||||
mAccount = client.getAccount().getSavedAccount();
|
|
||||||
}
|
|
||||||
mContext = client.getContext();
|
|
||||||
|
|
||||||
return runOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,6 +138,126 @@ public abstract class RemoteOperation implements Runnable {
|
|||||||
return runnerThread;
|
return runnerThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void grantOwnCloudClient() throws
|
||||||
|
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
||||||
|
if (mClient == null) {
|
||||||
|
if (mAccount != null && mContext != null) {
|
||||||
|
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
||||||
|
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
||||||
|
getClientFor(ocAccount, mContext);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Trying to run a remote operation " +
|
||||||
|
"asynchronously with no client and no chance to create one (no account)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current client instance to access the remote server.
|
||||||
|
*
|
||||||
|
* @return Current client instance to access the remote server.
|
||||||
|
*/
|
||||||
|
public final OwnCloudClient getClient() {
|
||||||
|
return mClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract method to implement the operation in derived classes.
|
||||||
|
*/
|
||||||
|
protected abstract RemoteOperationResult<T> run(OwnCloudClient client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously executes the remote operation on the received ownCloud account.
|
||||||
|
*
|
||||||
|
* Do not call this method from the main thread.
|
||||||
|
*
|
||||||
|
* This method should be used whenever an ownCloud account is available, instead of
|
||||||
|
* {@link #execute(OwnCloudClient)}.
|
||||||
|
*
|
||||||
|
* @param account ownCloud account in remote ownCloud server to reach during the
|
||||||
|
* execution of the operation.
|
||||||
|
* @param context Android context for the component calling the method.
|
||||||
|
* @return Result of the operation.
|
||||||
|
*/
|
||||||
|
public RemoteOperationResult<T> execute(Account account, Context context) {
|
||||||
|
if (account == null)
|
||||||
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||||
|
"Account");
|
||||||
|
if (context == null)
|
||||||
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||||
|
"Context");
|
||||||
|
mAccount = account;
|
||||||
|
mContext = context.getApplicationContext();
|
||||||
|
|
||||||
|
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<T> execute(OwnCloudClient client) {
|
||||||
|
if (client == null)
|
||||||
|
throw new IllegalArgumentException("Trying to execute a remote operation with a NULL " +
|
||||||
|
"OwnCloudClient");
|
||||||
|
mClient = client;
|
||||||
|
if (client.getAccount() != null) {
|
||||||
|
mAccount = client.getAccount().getSavedAccount();
|
||||||
|
}
|
||||||
|
mContext = client.getContext();
|
||||||
|
|
||||||
|
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<T> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run operation for asynchronous or synchronous 'onExecute' method.
|
||||||
|
*
|
||||||
|
* Considers and performs silent refresh of account credentials if possible, and if
|
||||||
|
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
|
||||||
|
* parameter 'true' before the execution.
|
||||||
|
*
|
||||||
|
* @return Remote operation result
|
||||||
|
*/
|
||||||
|
private RemoteOperationResult<T> runOperation() {
|
||||||
|
|
||||||
|
RemoteOperationResult<T> result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
grantOwnCloudClient();
|
||||||
|
result = run(mClient);
|
||||||
|
|
||||||
|
} catch (AccountsException | IOException e) {
|
||||||
|
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
||||||
|
result = new RemoteOperationResult<>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronous execution of the operation
|
* Asynchronous execution of the operation
|
||||||
@ -237,65 +276,10 @@ public abstract class RemoteOperation implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mListenerHandler != null && mListener != null) {
|
if (mListenerHandler != null && mListener != null) {
|
||||||
mListenerHandler.post(new Runnable() {
|
mListenerHandler.post(() ->
|
||||||
@Override
|
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend));
|
||||||
public void run() {
|
|
||||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (mListener != null) {
|
} else if (mListener != null) {
|
||||||
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Run operation for asynchronous or synchronous 'execute' method.
|
|
||||||
*
|
|
||||||
* Considers and performs silent refresh of account credentials if possible, and if
|
|
||||||
* {@link RemoteOperation#setSilentRefreshOfAccountCredentials(boolean)} was called with
|
|
||||||
* parameter 'true' before the execution.
|
|
||||||
*
|
|
||||||
* @return Remote operation result
|
|
||||||
*/
|
|
||||||
private RemoteOperationResult runOperation() {
|
|
||||||
|
|
||||||
RemoteOperationResult result;
|
|
||||||
|
|
||||||
try {
|
|
||||||
grantOwnCloudClient();
|
|
||||||
result = run(mClient);
|
|
||||||
|
|
||||||
} catch (AccountsException | IOException e) {
|
|
||||||
Log_OC.e(TAG, "Error while trying to access to " + mAccount.name, e);
|
|
||||||
result = new RemoteOperationResult(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void grantOwnCloudClient() throws
|
|
||||||
AccountUtils.AccountNotFoundException, OperationCanceledException, AuthenticatorException, IOException {
|
|
||||||
if (mClient == null) {
|
|
||||||
if (mAccount != null && mContext != null) {
|
|
||||||
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
|
|
||||||
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
|
||||||
getClientFor(ocAccount, mContext);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Trying to run a remote operation " +
|
|
||||||
"asynchronously with no client and no chance to create one (no account)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current client instance to access the remote server.
|
|
||||||
*
|
|
||||||
* @return Current client instance to access the remote server.
|
|
||||||
*/
|
|
||||||
public final OwnCloudClient getClient() {
|
|
||||||
return mClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -24,6 +24,17 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.common.operations;
|
package com.owncloud.android.lib.common.operations;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountsException;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.HttpBaseMethod;
|
||||||
|
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -34,35 +45,18 @@ import java.net.SocketException;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import android.accounts.Account;
|
import java.util.Map;
|
||||||
import android.accounts.AccountsException;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
|
|
||||||
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.ConnectTimeoutException;
|
|
||||||
import org.apache.commons.httpclient.Header;
|
|
||||||
import org.apache.commons.httpclient.HttpException;
|
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavException;
|
|
||||||
import org.json.JSONException;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.exception.DavException;
|
||||||
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
|
||||||
/**
|
public class RemoteOperationResult<T extends Object>
|
||||||
* The result of a remote operation required to an ownCloud server.
|
implements Serializable {
|
||||||
*
|
|
||||||
* Provides a common classification of remote operation results for all the
|
|
||||||
* application.
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
|
||||||
* @author David González Verdugo
|
|
||||||
*/
|
|
||||||
public class RemoteOperationResult implements Serializable {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated - should be refreshed every time the class changes!!
|
* Generated - should be refreshed every time the class changes!!
|
||||||
@ -132,8 +126,7 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
private String mRedirectedLocation;
|
private String mRedirectedLocation;
|
||||||
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
private ArrayList<String> mAuthenticate = new ArrayList<>();
|
||||||
private String mLastPermanentLocation = null;
|
private String mLastPermanentLocation = null;
|
||||||
|
private T mData = null;
|
||||||
private ArrayList<Object> mData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public constructor from result code.
|
* Public constructor from result code.
|
||||||
@ -147,7 +140,22 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL ||
|
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL ||
|
||||||
code == ResultCode.OK_NO_SSL ||
|
code == ResultCode.OK_NO_SSL ||
|
||||||
code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
code == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
||||||
mData = null;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new RemoteOperationResult based on the result given by a previous one.
|
||||||
|
* It does not copy the data.
|
||||||
|
* @param prevRemoteOperation
|
||||||
|
*/
|
||||||
|
public RemoteOperationResult(RemoteOperationResult prevRemoteOperation) {
|
||||||
|
mCode = prevRemoteOperation.mCode;
|
||||||
|
mHttpCode = prevRemoteOperation.mHttpCode;
|
||||||
|
mHttpPhrase = prevRemoteOperation.mHttpPhrase;
|
||||||
|
mAuthenticate = prevRemoteOperation.mAuthenticate;
|
||||||
|
mException = prevRemoteOperation.mException;
|
||||||
|
mLastPermanentLocation = prevRemoteOperation.mLastPermanentLocation;
|
||||||
|
mSuccess = prevRemoteOperation.mSuccess;
|
||||||
|
mRedirectedLocation = prevRemoteOperation.mRedirectedLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,33 +179,34 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
} else if (e instanceof SocketTimeoutException) {
|
} else if (e instanceof SocketTimeoutException) {
|
||||||
mCode = ResultCode.TIMEOUT;
|
mCode = ResultCode.TIMEOUT;
|
||||||
|
|
||||||
} else if (e instanceof ConnectTimeoutException) {
|
|
||||||
mCode = ResultCode.TIMEOUT;
|
|
||||||
|
|
||||||
} else if (e instanceof MalformedURLException) {
|
} else if (e instanceof MalformedURLException) {
|
||||||
mCode = ResultCode.INCORRECT_ADDRESS;
|
mCode = ResultCode.INCORRECT_ADDRESS;
|
||||||
|
|
||||||
} else if (e instanceof UnknownHostException) {
|
} else if (e instanceof UnknownHostException) {
|
||||||
mCode = ResultCode.HOST_NOT_AVAILABLE;
|
mCode = ResultCode.HOST_NOT_AVAILABLE;
|
||||||
|
|
||||||
} else if (e instanceof AccountNotFoundException) {
|
} else if (e instanceof AccountUtils.AccountNotFoundException) {
|
||||||
mCode = ResultCode.ACCOUNT_NOT_FOUND;
|
mCode = ResultCode.ACCOUNT_NOT_FOUND;
|
||||||
|
|
||||||
} else if (e instanceof AccountsException) {
|
} else if (e instanceof AccountsException) {
|
||||||
mCode = ResultCode.ACCOUNT_EXCEPTION;
|
mCode = ResultCode.ACCOUNT_EXCEPTION;
|
||||||
|
|
||||||
} else if (e instanceof SSLException || e instanceof RuntimeException) {
|
} else if (e instanceof SSLException || e instanceof RuntimeException) {
|
||||||
CertificateCombinedException se = getCertificateCombinedException(e);
|
if(e instanceof SSLPeerUnverifiedException) {
|
||||||
if (se != null) {
|
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
||||||
mException = se;
|
|
||||||
if (se.isRecoverable()) {
|
|
||||||
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
|
|
||||||
}
|
|
||||||
} else if (e instanceof RuntimeException) {
|
|
||||||
mCode = ResultCode.HOST_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mCode = ResultCode.SSL_ERROR;
|
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) {
|
} else if (e instanceof FileNotFoundException) {
|
||||||
@ -206,7 +215,6 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
} else {
|
} else {
|
||||||
mCode = ResultCode.UNKNOWN_ERROR;
|
mCode = ResultCode.UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,25 +224,21 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
*
|
*
|
||||||
* Determines a {@link ResultCode} from the already executed method received as a parameter. Generally,
|
* 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
|
* will depend on the HTTP code and HTTP response headers received. In some cases will inspect also the
|
||||||
* response body.
|
* response body
|
||||||
*
|
*
|
||||||
* @param success The operation was considered successful or not.
|
* @param httpMethod
|
||||||
* @param httpMethod HTTP/DAV method already executed which response will be examined to interpret the
|
* @throws IOException
|
||||||
* result.
|
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult(boolean success, HttpMethod httpMethod) throws IOException {
|
public RemoteOperationResult(HttpBaseMethod httpMethod) throws IOException {
|
||||||
this(
|
this(httpMethod.getStatusCode(),
|
||||||
success,
|
httpMethod.getStatusMessage(),
|
||||||
httpMethod.getStatusCode(),
|
|
||||||
httpMethod.getStatusText(),
|
|
||||||
httpMethod.getResponseHeaders()
|
httpMethod.getResponseHeaders()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mHttpCode == HttpStatus.SC_BAD_REQUEST) { // 400
|
if (mHttpCode == HttpConstants.HTTP_BAD_REQUEST) { // 400
|
||||||
|
|
||||||
String bodyResponse = httpMethod.getResponseBodyAsString();
|
String bodyResponse = httpMethod.getResponseBodyAsString();
|
||||||
// do not get for other HTTP codes!; could not be available
|
|
||||||
|
|
||||||
|
// do not get for other HTTP codes!; could not be available
|
||||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||||
InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
|
InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser();
|
||||||
@ -250,34 +254,40 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHttpCode == HttpStatus.SC_FORBIDDEN) { // 403
|
// before
|
||||||
|
switch (mHttpCode) {
|
||||||
parseErrorMessageAndSetCode(httpMethod, ResultCode.SPECIFIC_FORBIDDEN);
|
case HttpConstants.HTTP_FORBIDDEN:
|
||||||
}
|
parseErrorMessageAndSetCode(
|
||||||
|
httpMethod.getResponseBodyAsString(),
|
||||||
if (mHttpCode == HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE) { // 415
|
ResultCode.SPECIFIC_FORBIDDEN
|
||||||
|
);
|
||||||
parseErrorMessageAndSetCode(httpMethod, ResultCode.SPECIFIC_UNSUPPORTED_MEDIA_TYPE);
|
break;
|
||||||
}
|
case HttpConstants.HTTP_UNSUPPORTED_MEDIA_TYPE:
|
||||||
|
parseErrorMessageAndSetCode(
|
||||||
if (mHttpCode == HttpStatus.SC_SERVICE_UNAVAILABLE) { // 503
|
httpMethod.getResponseBodyAsString(),
|
||||||
|
ResultCode.SPECIFIC_UNSUPPORTED_MEDIA_TYPE
|
||||||
parseErrorMessageAndSetCode(httpMethod, ResultCode.SPECIFIC_SERVICE_UNAVAILABLE);
|
);
|
||||||
|
break;
|
||||||
|
case HttpConstants.HTTP_SERVICE_UNAVAILABLE:
|
||||||
|
parseErrorMessageAndSetCode(
|
||||||
|
httpMethod.getResponseBodyAsString(),
|
||||||
|
ResultCode.SPECIFIC_SERVICE_UNAVAILABLE
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the error message included in the body response, if any, and set the specific result
|
* Parse the error message included in the body response, if any, and set the specific result
|
||||||
* code
|
* code
|
||||||
* @param httpMethod HTTP/DAV method already executed which response body will be parsed to get
|
*
|
||||||
* the specific error message
|
* @param bodyResponse okHttp response body
|
||||||
* @param resultCode specific result code
|
* @param resultCode our own custom result code
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void parseErrorMessageAndSetCode(HttpMethod httpMethod, ResultCode resultCode)
|
private void parseErrorMessageAndSetCode(String bodyResponse, ResultCode resultCode) {
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
String bodyResponse = httpMethod.getResponseBodyAsString();
|
|
||||||
|
|
||||||
if (bodyResponse != null && bodyResponse.length() > 0) {
|
if (bodyResponse != null && bodyResponse.length() > 0) {
|
||||||
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
InputStream is = new ByteArrayInputStream(bodyResponse.getBytes());
|
||||||
@ -301,31 +311,29 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
* To be used when the result needs to be interpreted from HTTP response elements that could come from
|
* 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).
|
* different requests (WARNING: black magic, try to avoid).
|
||||||
*
|
*
|
||||||
* If all the fields come from the same HTTP/DAV response, {@link #RemoteOperationResult(boolean, HttpMethod)}
|
|
||||||
* should be used instead.
|
|
||||||
*
|
*
|
||||||
* Determines a {@link ResultCode} depending on the HTTP code and HTTP response headers received.
|
* 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 httpCode HTTP status code returned by an HTTP/DAV method.
|
||||||
* @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method
|
* @param httpPhrase HTTP status line phrase returned by an HTTP/DAV method
|
||||||
* @param httpHeaders HTTP response header 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, Header[] httpHeaders) {
|
public RemoteOperationResult(int httpCode, String httpPhrase, Headers headers) {
|
||||||
this(success, httpCode, httpPhrase);
|
this(httpCode, httpPhrase);
|
||||||
if (httpHeaders != null) {
|
if (headers != null) {
|
||||||
for (Header httpHeader : httpHeaders) {
|
for (Map.Entry<String, List<String>> header : headers.toMultimap().entrySet()) {
|
||||||
if ("location".equals(httpHeader.getName().toLowerCase())) {
|
if ("location".equals(header.getKey().toLowerCase())) {
|
||||||
mRedirectedLocation = httpHeader.getValue();
|
mRedirectedLocation = header.getValue().get(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ("www-authenticate".equals(httpHeader.getName().toLowerCase())) {
|
if ("www-authenticate".equals(header.getKey().toLowerCase())) {
|
||||||
mAuthenticate.add(httpHeader.getValue().toLowerCase());
|
mAuthenticate.add(header.getValue().get(0).toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isIdPRedirection()) {
|
if (isIdPRedirection()) {
|
||||||
mCode = ResultCode.UNAUTHORIZED; // overrides default ResultCode.UNKNOWN
|
// overrides default ResultCode.UNKNOWN
|
||||||
|
mCode = ResultCode.UNAUTHORIZED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,58 +342,47 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
*
|
*
|
||||||
* Determines a {@link ResultCode} depending of the type of the exception.
|
* 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 httpCode HTTP status code returned by the HTTP/DAV method.
|
||||||
* @param httpPhrase HTTP status line phrase 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) {
|
private RemoteOperationResult(int httpCode, String httpPhrase) {
|
||||||
mSuccess = success;
|
|
||||||
mHttpCode = httpCode;
|
mHttpCode = httpCode;
|
||||||
mHttpPhrase = httpPhrase;
|
mHttpPhrase = httpPhrase;
|
||||||
|
|
||||||
if (success) {
|
if (httpCode > 0) {
|
||||||
mCode = ResultCode.OK;
|
|
||||||
|
|
||||||
} else if (httpCode > 0) {
|
|
||||||
switch (httpCode) {
|
switch (httpCode) {
|
||||||
case HttpStatus.SC_UNAUTHORIZED: // 401
|
case HttpConstants.HTTP_UNAUTHORIZED: // 401
|
||||||
mCode = ResultCode.UNAUTHORIZED;
|
mCode = ResultCode.UNAUTHORIZED;
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_FORBIDDEN: // 403
|
case HttpConstants.HTTP_FORBIDDEN: // 403
|
||||||
mCode = ResultCode.FORBIDDEN;
|
mCode = ResultCode.FORBIDDEN;
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_NOT_FOUND: // 404
|
case HttpConstants.HTTP_NOT_FOUND: // 404
|
||||||
mCode = ResultCode.FILE_NOT_FOUND;
|
mCode = ResultCode.FILE_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_CONFLICT: // 409
|
case HttpConstants.HTTP_CONFLICT: // 409
|
||||||
mCode = ResultCode.CONFLICT;
|
mCode = ResultCode.CONFLICT;
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_INTERNAL_SERVER_ERROR: // 500
|
case HttpConstants.HTTP_INTERNAL_SERVER_ERROR: // 500
|
||||||
mCode = ResultCode.INSTANCE_NOT_CONFIGURED; // assuming too much...
|
mCode = ResultCode.INSTANCE_NOT_CONFIGURED; // assuming too much...
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_SERVICE_UNAVAILABLE: // 503
|
case HttpConstants.HTTP_SERVICE_UNAVAILABLE: // 503
|
||||||
mCode = ResultCode.SERVICE_UNAVAILABLE;
|
mCode = ResultCode.SERVICE_UNAVAILABLE;
|
||||||
break;
|
break;
|
||||||
case HttpStatus.SC_INSUFFICIENT_STORAGE: // 507
|
case HttpConstants.HTTP_INSUFFICIENT_STORAGE: // 507
|
||||||
mCode = ResultCode.QUOTA_EXCEEDED; // surprise!
|
mCode = ResultCode.QUOTA_EXCEEDED; // surprise!
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
mCode = ResultCode.UNHANDLED_HTTP_CODE; // UNKNOWN ERROR
|
||||||
Log_OC.d(TAG,
|
Log_OC.d(TAG,
|
||||||
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
"RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " +
|
||||||
|
|
||||||
mHttpCode + " " + mHttpPhrase
|
mHttpCode + " " + mHttpPhrase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(ArrayList<Object> items) {
|
|
||||||
mData = items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<Object> getData() {
|
|
||||||
return mData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSuccess() {
|
public boolean isSuccess() {
|
||||||
return mSuccess;
|
return mSuccess;
|
||||||
@ -449,9 +446,6 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
} else if (mException instanceof SocketTimeoutException) {
|
} else if (mException instanceof SocketTimeoutException) {
|
||||||
return "Socket timeout exception";
|
return "Socket timeout exception";
|
||||||
|
|
||||||
} else if (mException instanceof ConnectTimeoutException) {
|
|
||||||
return "Connect timeout exception";
|
|
||||||
|
|
||||||
} else if (mException instanceof MalformedURLException) {
|
} else if (mException instanceof MalformedURLException) {
|
||||||
return "Malformed URL exception";
|
return "Malformed URL exception";
|
||||||
|
|
||||||
@ -476,9 +470,9 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
} else if (mException instanceof IOException) {
|
} else if (mException instanceof IOException) {
|
||||||
return "Unrecovered transport exception";
|
return "Unrecovered transport exception";
|
||||||
|
|
||||||
} else if (mException instanceof AccountNotFoundException) {
|
} else if (mException instanceof AccountUtils.AccountNotFoundException) {
|
||||||
Account failedAccount =
|
Account failedAccount =
|
||||||
((AccountNotFoundException) mException).getFailedAccount();
|
((AccountUtils.AccountNotFoundException) mException).getFailedAccount();
|
||||||
return mException.getMessage() + " (" +
|
return mException.getMessage() + " (" +
|
||||||
(failedAccount != null ? failedAccount.name : "NULL") + ")";
|
(failedAccount != null ? failedAccount.name : "NULL") + ")";
|
||||||
|
|
||||||
@ -530,7 +524,7 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isServerFail() {
|
public boolean isServerFail() {
|
||||||
return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
|
return (mHttpCode >= HttpConstants.HTTP_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isException() {
|
public boolean isException() {
|
||||||
@ -572,4 +566,15 @@ public class RemoteOperationResult implements Serializable {
|
|||||||
mLastPermanentLocation = lastPermanentLocation;
|
mLastPermanentLocation = lastPermanentLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public void setSuccess(boolean success) {
|
||||||
|
this.mSuccess = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(T data) {
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getData() {
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.owncloud.android.lib.common.utils;
|
package com.owncloud.android.lib.common.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@ -7,10 +9,6 @@ import java.io.IOException;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
|
|
||||||
public class Log_OC {
|
public class Log_OC {
|
||||||
private static final String SIMPLE_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
|
private static final String SIMPLE_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
|
||||||
private static final String LOG_FOLDER_NAME = "log";
|
private static final String LOG_FOLDER_NAME = "log";
|
||||||
@ -63,11 +61,6 @@ public class Log_OC {
|
|||||||
Log.w(TAG, message);
|
Log.w(TAG, message);
|
||||||
appendLog(TAG+" : "+ message);
|
appendLog(TAG+" : "+ message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void wtf(String TAG, String message) {
|
|
||||||
Log.wtf(TAG, message);
|
|
||||||
appendLog(TAG+" : "+ message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start doing logging
|
* Start doing logging
|
||||||
|
63
src/com/owncloud/android/lib/common/utils/RandomUtils.java
Normal file
63
src/com/owncloud/android/lib/common/utils/RandomUtils.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.common.utils;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class with methods to generate random values
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class RandomUtils {
|
||||||
|
|
||||||
|
private static final String CANDIDATECHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||||
|
"1234567890-+/_=.:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param length the number of random chars to be generated
|
||||||
|
*
|
||||||
|
* @return String containing random chars
|
||||||
|
*/
|
||||||
|
public static String generateRandomString(int length) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Random random = new Random();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
sb.append(CANDIDATECHARS.charAt(random.nextInt(CANDIDATECHARS.length())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param min minimum integer to obtain randomly
|
||||||
|
* @param max maximum integer to obtain randomly
|
||||||
|
* @return random integer between min and max
|
||||||
|
*/
|
||||||
|
public static int generateRandomInteger(int min, int max) {
|
||||||
|
Random r = new Random();
|
||||||
|
return r.nextInt(max-min) + min;
|
||||||
|
}
|
||||||
|
}
|
@ -1,151 +0,0 @@
|
|||||||
/* 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.resources.files;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.methods.PutMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
|
||||||
import com.owncloud.android.lib.common.network.ChunkFromFileChannelRequestEntity;
|
|
||||||
import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
|
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
|
||||||
import com.owncloud.android.lib.common.operations.InvalidCharacterExceptionParser;
|
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
||||||
|
|
||||||
|
|
||||||
public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation {
|
|
||||||
|
|
||||||
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
|
||||||
|
|
||||||
public static final long CHUNK_SIZE = 1024000;
|
|
||||||
private static final String OC_CHUNKED_HEADER = "OC-Chunked";
|
|
||||||
private static final String OC_CHUNK_SIZE_HEADER = "OC-Chunk-Size";
|
|
||||||
private static final String OC_CHUNK_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
|
||||||
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
|
||||||
|
|
||||||
public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType,
|
|
||||||
String fileLastModifTimestamp) {
|
|
||||||
super(storagePath, remotePath, mimeType, fileLastModifTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkedUploadRemoteFileOperation(
|
|
||||||
String storagePath, String remotePath, String mimeType, String requiredEtag,
|
|
||||||
String fileLastModifTimestamp
|
|
||||||
) {
|
|
||||||
super(storagePath, remotePath, mimeType, requiredEtag, fileLastModifTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RemoteOperationResult uploadFile(OwnCloudClient client) throws IOException {
|
|
||||||
int status = -1;
|
|
||||||
RemoteOperationResult result = null;
|
|
||||||
|
|
||||||
FileChannel channel = null;
|
|
||||||
RandomAccessFile raf = null;
|
|
||||||
try {
|
|
||||||
File file = new File(mLocalPath);
|
|
||||||
raf = new RandomAccessFile(file, "r");
|
|
||||||
channel = raf.getChannel();
|
|
||||||
mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
((ProgressiveDataTransferer) mEntity)
|
|
||||||
.addDatatransferProgressListeners(mDataTransferListeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
long offset = 0;
|
|
||||||
String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) +
|
|
||||||
"-chunking-" + Math.abs((new Random()).nextInt(9000) + 1000) + "-";
|
|
||||||
long totalLength = file.length();
|
|
||||||
long chunkCount = (long) Math.ceil((double) totalLength / CHUNK_SIZE);
|
|
||||||
String chunkSizeStr = String.valueOf(CHUNK_SIZE);
|
|
||||||
String totalLengthStr = String.valueOf(file.length());
|
|
||||||
for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++, offset += CHUNK_SIZE) {
|
|
||||||
if (chunkIndex == chunkCount - 1) {
|
|
||||||
chunkSizeStr = String.valueOf(CHUNK_SIZE * chunkCount - totalLength);
|
|
||||||
}
|
|
||||||
if (mPutMethod != null) {
|
|
||||||
mPutMethod.releaseConnection(); // let the connection available
|
|
||||||
// for other methods
|
|
||||||
}
|
|
||||||
mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
|
|
||||||
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
|
||||||
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
|
||||||
}
|
|
||||||
mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
|
|
||||||
mPutMethod.addRequestHeader(OC_CHUNK_SIZE_HEADER, chunkSizeStr);
|
|
||||||
mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, totalLengthStr);
|
|
||||||
|
|
||||||
mPutMethod.addRequestHeader(OC_CHUNK_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
|
||||||
|
|
||||||
((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset);
|
|
||||||
mPutMethod.setRequestEntity(mEntity);
|
|
||||||
if (mCancellationRequested.get()) {
|
|
||||||
mPutMethod.abort();
|
|
||||||
// next method will throw an exception
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunkIndex == chunkCount - 1) {
|
|
||||||
// Added a high timeout to the last chunk due to when the last chunk
|
|
||||||
// arrives to the server with the last PUT, all chunks get assembled
|
|
||||||
// within that PHP request, so last one takes longer.
|
|
||||||
mPutMethod.getParams().setSoTimeout(LAST_CHUNK_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = client.executeMethod(mPutMethod);
|
|
||||||
|
|
||||||
result = new RemoteOperationResult(
|
|
||||||
isSuccess(status),
|
|
||||||
mPutMethod
|
|
||||||
);
|
|
||||||
|
|
||||||
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
|
|
||||||
Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath +
|
|
||||||
", chunk index " + chunkIndex + ", count " + chunkCount +
|
|
||||||
", HTTP result status " + status);
|
|
||||||
|
|
||||||
if (!isSuccess(status))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (channel != null)
|
|
||||||
channel.close();
|
|
||||||
if (raf != null)
|
|
||||||
raf.close();
|
|
||||||
if (mPutMethod != null)
|
|
||||||
mPutMethod.releaseConnection(); // let the connection available for other methods
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -27,28 +27,25 @@ package com.owncloud.android.lib.resources.files;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.CopyMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.jackrabbit.webdav.DavException;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.jackrabbit.webdav.MultiStatusResponse;
|
|
||||||
import org.apache.jackrabbit.webdav.Status;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.CopyMethod;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||||
* in the same account.
|
* in the same account.
|
||||||
* <p/>
|
*
|
||||||
* Allows renaming the moving file/folder at the same time.
|
* Allows renaming the moving file/folder at the same time.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
|
* @author Christian Schabesberger
|
||||||
*/
|
*/
|
||||||
public class CopyRemoteFileOperation extends RemoteOperation {
|
public class CopyRemoteFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
@ -62,7 +59,6 @@ public class CopyRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
private boolean mOverwrite;
|
private boolean mOverwrite;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* <p/>
|
* <p/>
|
||||||
@ -78,7 +74,6 @@ public class CopyRemoteFileOperation extends RemoteOperation {
|
|||||||
mOverwrite = overwrite;
|
mOverwrite = overwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the rename operation.
|
* Performs the rename operation.
|
||||||
*
|
*
|
||||||
@ -93,36 +88,35 @@ public class CopyRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
/// check parameters
|
/// check parameters
|
||||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
|
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||||
// nothing to do!
|
// nothing to do!
|
||||||
return new RemoteOperationResult(ResultCode.OK);
|
return new RemoteOperationResult<>(ResultCode.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT);
|
return new RemoteOperationResult<>(ResultCode.INVALID_COPY_INTO_DESCENDANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// perform remote operation
|
/// perform remote operation
|
||||||
CopyMethod copyMethod = null;
|
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result = null;
|
||||||
try {
|
try {
|
||||||
copyMethod = new CopyMethod(
|
CopyMethod copyMethod = new CopyMethod(new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||||
client.getWebdavUri() + WebdavUtils.encodePath(mSrcRemotePath),
|
client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
||||||
client.getWebdavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
mOverwrite);
|
||||||
mOverwrite
|
|
||||||
);
|
|
||||||
int status = client.executeMethod(copyMethod, COPY_READ_TIMEOUT, COPY_CONNECTION_TIMEOUT);
|
|
||||||
|
|
||||||
/// process response
|
copyMethod.setReadTimeout(COPY_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
if (status == HttpStatus.SC_MULTI_STATUS) {
|
copyMethod.setConnectionTimeout(COPY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
result = processPartialError(copyMethod);
|
|
||||||
|
|
||||||
} else if (status == HttpStatus.SC_PRECONDITION_FAILED && !mOverwrite) {
|
final int status = client.executeHttpMethod(copyMethod);
|
||||||
|
|
||||||
result = new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
if(status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT) {
|
||||||
|
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||||
|
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
|
||||||
|
|
||||||
|
result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||||
|
|
||||||
|
|
||||||
@ -130,7 +124,7 @@ public class CopyRemoteFileOperation extends RemoteOperation {
|
|||||||
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(isSuccess(status), copyMethod);
|
result = new RemoteOperationResult<>(copyMethod);
|
||||||
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
client.exhaustResponse(copyMethod.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,67 +132,11 @@ public class CopyRemoteFileOperation extends RemoteOperation {
|
|||||||
result.getLogMessage());
|
result.getLogMessage());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||||
result.getLogMessage(), e);
|
result.getLogMessage(), e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (copyMethod != null)
|
|
||||||
copyMethod.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analyzes a multistatus response from the OC server to generate an appropriate result.
|
|
||||||
* <p/>
|
|
||||||
* In WebDAV, a COPY request on collections (folders) can be PARTIALLY successful: some
|
|
||||||
* children are copied, some other aren't.
|
|
||||||
* <p/>
|
|
||||||
* According to the WebDAV specification, a multistatus response SHOULD NOT include partial
|
|
||||||
* successes (201, 204) nor for descendants of already failed children (424) in the response
|
|
||||||
* entity. But SHOULD NOT != MUST NOT, so take carefully.
|
|
||||||
*
|
|
||||||
* @param copyMethod Copy operation just finished with a multistatus response
|
|
||||||
* @return A result for the {@link com.owncloud.android.lib.resources.files.CopyRemoteFileOperation} caller
|
|
||||||
* @throws java.io.IOException If the response body could not be parsed
|
|
||||||
* @throws org.apache.jackrabbit.webdav.DavException If the status code is other than MultiStatus or if obtaining
|
|
||||||
* the response XML document fails
|
|
||||||
*/
|
|
||||||
private RemoteOperationResult processPartialError(CopyMethod copyMethod)
|
|
||||||
throws IOException, DavException {
|
|
||||||
// Adding a list of failed descendants to the result could be interesting; or maybe not.
|
|
||||||
// For the moment, let's take the easy way.
|
|
||||||
|
|
||||||
/// check that some error really occurred
|
|
||||||
MultiStatusResponse[] responses = copyMethod.getResponseBodyAsMultiStatus().getResponses();
|
|
||||||
Status[] status;
|
|
||||||
boolean failFound = false;
|
|
||||||
for (int i = 0; i < responses.length && !failFound; i++) {
|
|
||||||
status = responses[i].getStatus();
|
|
||||||
failFound = (
|
|
||||||
status != null &&
|
|
||||||
status.length > 0 &&
|
|
||||||
status[0].getStatusCode() > 299
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteOperationResult result;
|
|
||||||
if (failFound) {
|
|
||||||
result = new RemoteOperationResult(ResultCode.PARTIAL_COPY_DONE);
|
|
||||||
} else {
|
|
||||||
result = new RemoteOperationResult(true, copyMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected boolean isSuccess(int status) {
|
|
||||||
return status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,16 +24,22 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
|
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.MkColMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the creation of a new folder in the ownCloud server.
|
* Remote operation performing the creation of a new folder in the ownCloud server.
|
||||||
@ -48,20 +54,19 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
private static final int READ_TIMEOUT = 30000;
|
private static final int READ_TIMEOUT = 30000;
|
||||||
private static final int CONNECTION_TIMEOUT = 5000;
|
private static final int CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
|
private String mRemotePath;
|
||||||
protected String mRemotePath;
|
private boolean mCreateFullPath;
|
||||||
protected boolean mCreateFullPath;
|
protected boolean createChunksFolder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
|
||||||
* @param remotePath Full path to the new directory to create in the remote server.
|
* @param remotePath Full path to the new directory to create in the remote server.
|
||||||
* @param createFullPath 'True' means that all the ancestor folders should be created
|
* @param createFullPath 'True' means that all the ancestor folders should be created.
|
||||||
* if don't exist yet.
|
|
||||||
*/
|
*/
|
||||||
public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
|
public CreateRemoteFolderOperation(String remotePath, boolean createFullPath) {
|
||||||
mRemotePath = remotePath;
|
mRemotePath = remotePath;
|
||||||
mCreateFullPath = createFullPath;
|
mCreateFullPath = createFullPath;
|
||||||
|
createChunksFolder = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,7 +76,7 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result;
|
||||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
OwnCloudVersion version = client.getOwnCloudVersion();
|
||||||
boolean versionWithForbiddenChars =
|
boolean versionWithForbiddenChars =
|
||||||
(version != null && version.isVersionWithForbiddenCharacters());
|
(version != null && version.isVersionWithForbiddenCharacters());
|
||||||
@ -85,41 +90,38 @@ public class CreateRemoteFolderOperation extends RemoteOperation {
|
|||||||
result = createFolder(client); // second (and last) try
|
result = createFolder(client); // second (and last) try
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
|
result = new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private RemoteOperationResult createFolder(OwnCloudClient client) {
|
private RemoteOperationResult createFolder(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result;
|
||||||
MkColMethod mkcol = null;
|
|
||||||
try {
|
try {
|
||||||
mkcol = new MkColMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
|
Uri webDavUri = createChunksFolder ? client.getNewUploadsWebDavUri() : client.getNewFilesWebDavUri();
|
||||||
client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT);
|
final MkColMethod mkcol = new MkColMethod(new URL(webDavUri + WebdavUtils.encodePath(mRemotePath)));
|
||||||
result = new RemoteOperationResult(mkcol.succeeded(), mkcol);
|
mkcol.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
mkcol.setConnectionTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
final int status = client.executeHttpMethod(mkcol);
|
||||||
|
|
||||||
|
result = (status == HttpConstants.HTTP_CREATED)
|
||||||
|
? new RemoteOperationResult<>(ResultCode.OK)
|
||||||
|
: new RemoteOperationResult<>(mkcol);
|
||||||
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage());
|
||||||
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
client.exhaustResponse(mkcol.getResponseBodyAsStream());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
|
Log_OC.e(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (mkcol != null)
|
|
||||||
mkcol.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RemoteOperationResult createParentFolder(String parentPath, OwnCloudClient client) {
|
private RemoteOperationResult createParentFolder(String parentPath, OwnCloudClient client) {
|
||||||
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath,
|
RemoteOperation operation = new CreateRemoteFolderOperation(parentPath, mCreateFullPath);
|
||||||
mCreateFullPath);
|
|
||||||
return operation.execute(client);
|
return operation.execute(client);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -24,21 +24,9 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Header;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||||
@ -46,6 +34,16 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the download of a remote file in the ownCloud server.
|
* Remote operation performing the download of a remote file in the ownCloud server.
|
||||||
*
|
*
|
||||||
@ -88,7 +86,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
result.getLogMessage());
|
result.getLogMessage());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " +
|
||||||
result.getLogMessage(), e);
|
result.getLogMessage(), e);
|
||||||
}
|
}
|
||||||
@ -98,28 +96,30 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
|
|
||||||
private RemoteOperationResult downloadFile(OwnCloudClient client, File targetFile) throws
|
private RemoteOperationResult downloadFile(OwnCloudClient client, File targetFile) throws
|
||||||
IOException, OperationCancelledException {
|
Exception {
|
||||||
|
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult result;
|
||||||
int status;
|
int status;
|
||||||
boolean savedFile = false;
|
boolean savedFile = false;
|
||||||
mGet = new GetMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
|
mGet = new GetMethod(new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)));
|
||||||
Iterator<OnDatatransferProgressListener> it;
|
Iterator<OnDatatransferProgressListener> it;
|
||||||
|
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
BufferedInputStream bis = null;
|
BufferedInputStream bis = null;
|
||||||
try {
|
try {
|
||||||
status = client.executeMethod(mGet);
|
status = client.executeHttpMethod(mGet);
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
targetFile.createNewFile();
|
targetFile.createNewFile();
|
||||||
bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
|
bis = new BufferedInputStream(mGet.getResponseBodyAsStream());
|
||||||
fos = new FileOutputStream(targetFile);
|
fos = new FileOutputStream(targetFile);
|
||||||
long transferred = 0;
|
long transferred = 0;
|
||||||
|
|
||||||
Header contentLength = mGet.getResponseHeader("Content-Length");
|
String contentLength = mGet.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER);
|
||||||
long totalToTransfer = (contentLength != null &&
|
long totalToTransfer =
|
||||||
contentLength.getValue().length() > 0) ?
|
(contentLength != null
|
||||||
Long.parseLong(contentLength.getValue()) : 0;
|
&& contentLength.length() > 0)
|
||||||
|
? Long.parseLong(contentLength)
|
||||||
|
: 0;
|
||||||
|
|
||||||
byte[] bytes = new byte[4096];
|
byte[] bytes = new byte[4096];
|
||||||
int readResult;
|
int readResult;
|
||||||
@ -142,18 +142,23 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
if (transferred == totalToTransfer) { // Check if the file is completed
|
if (transferred == totalToTransfer) { // Check if the file is completed
|
||||||
savedFile = true;
|
savedFile = true;
|
||||||
Header modificationTime = mGet.getResponseHeader("Last-Modified");
|
final String modificationTime =
|
||||||
if (modificationTime == null) {
|
mGet.getResponseHeaders().get("Last-Modified") != null
|
||||||
modificationTime = mGet.getResponseHeader("last-modified");
|
? mGet.getResponseHeaders().get("Last-Modified")
|
||||||
}
|
: mGet.getResponseHeader("last-modified");
|
||||||
|
|
||||||
if (modificationTime != null) {
|
if (modificationTime != null) {
|
||||||
Date d = WebdavUtils.parseResponseDate(modificationTime.getValue());
|
final Date d = WebdavUtils.parseResponseDate(modificationTime);
|
||||||
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
||||||
} else {
|
} else {
|
||||||
Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath);
|
Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
||||||
|
|
||||||
|
// Get rid of extra quotas
|
||||||
|
mEtag = mEtag.replace("\"", "");
|
||||||
|
|
||||||
if (mEtag.length() == 0) {
|
if (mEtag.length() == 0) {
|
||||||
Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath);
|
Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath);
|
||||||
}
|
}
|
||||||
@ -168,21 +173,21 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
} // else, body read by RemoteOperationResult constructor
|
} // else, body read by RemoteOperationResult constructor
|
||||||
|
|
||||||
result = new RemoteOperationResult(isSuccess(status), mGet);
|
result = isSuccess(status)
|
||||||
|
? new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK)
|
||||||
|
: new RemoteOperationResult<>(mGet);
|
||||||
} finally {
|
} finally {
|
||||||
if (fos != null) fos.close();
|
if (fos != null) fos.close();
|
||||||
if (bis != null) bis.close();
|
if (bis != null) bis.close();
|
||||||
if (!savedFile && targetFile.exists()) {
|
if (!savedFile && targetFile.exists()) {
|
||||||
targetFile.delete();
|
targetFile.delete();
|
||||||
}
|
}
|
||||||
mGet.releaseConnection(); // let the connection available for other methods
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTmpPath() {
|
private String getTmpPath() {
|
||||||
@ -212,4 +217,4 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
|||||||
public String getEtag() {
|
public String getEtag() {
|
||||||
return mEtag;
|
return mEtag;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,22 +1,22 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -24,47 +24,50 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavConstants;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||||
import com.owncloud.android.lib.common.network.RedirectionPath;
|
import com.owncloud.android.lib.common.network.RedirectionPath;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation to check the existence or absence of a path in a remote server.
|
* Operation to check the existence or absence of a path in a remote server.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class ExistenceCheckRemoteOperation extends RemoteOperation {
|
public class ExistenceCheckRemoteOperation extends RemoteOperation {
|
||||||
|
|
||||||
/** Maximum time to wait for a response from the server in MILLISECONDs. */
|
/**
|
||||||
|
* Maximum time to wait for a response from the server in MILLISECONDs.
|
||||||
|
*/
|
||||||
public static final int TIMEOUT = 10000;
|
public static final int TIMEOUT = 10000;
|
||||||
|
|
||||||
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
|
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
|
||||||
|
|
||||||
private static final int FORBIDDEN_ERROR = 403;
|
|
||||||
private static final int SERVICE_UNAVAILABLE_ERROR = 503;
|
|
||||||
|
|
||||||
private String mPath;
|
private String mPath;
|
||||||
private boolean mSuccessIfAbsent;
|
private boolean mSuccessIfAbsent;
|
||||||
|
|
||||||
/** Sequence of redirections followed. Available only after executing the operation */
|
/**
|
||||||
|
* Sequence of redirections followed. Available only after executing the operation
|
||||||
|
*/
|
||||||
private RedirectionPath mRedirectionPath = null;
|
private RedirectionPath mRedirectionPath = null;
|
||||||
// TODO move to {@link RemoteOperation}, that needs a nice refactoring
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full constructor. Success of the operation will depend upon the value of successIfAbsent.
|
* Full constructor. Success of the operation will depend upon the value of successIfAbsent.
|
||||||
*
|
*
|
||||||
* @param remotePath Path to append to the URL owned by the client instance.
|
* @param remotePath Path to append to the URL owned by the client instance.
|
||||||
* @param successIfAbsent When 'true', the operation finishes in success if the path does
|
* @param successIfAbsent When 'true', the operation finishes in success if the path does
|
||||||
* NOT exist in the remote server (HTTP 404).
|
* NOT exist in the remote server (HTTP 404).
|
||||||
*/
|
*/
|
||||||
public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent) {
|
public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent) {
|
||||||
mPath = (remotePath != null) ? remotePath : "";
|
mPath = (remotePath != null) ? remotePath : "";
|
||||||
@ -72,69 +75,73 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
|
||||||
PropFindMethod propfind = null;
|
boolean previousFollowRedirects = client.followRedirects();
|
||||||
boolean previousFollowRedirects = client.getFollowRedirects();
|
|
||||||
try {
|
try {
|
||||||
propfind = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mPath),
|
PropfindMethod propfindMethod = new PropfindMethod(
|
||||||
WebdavUtils.getAllPropSet(), DavConstants.DEPTH_0);
|
new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mPath)),
|
||||||
|
0,
|
||||||
|
DavUtils.getAllPropset()
|
||||||
|
);
|
||||||
|
propfindMethod.setReadTimeout(TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
propfindMethod.setConnectionTimeout(TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
|
||||||
client.setFollowRedirects(false);
|
client.setFollowRedirects(false);
|
||||||
int status = client.executeMethod(propfind, TIMEOUT, TIMEOUT);
|
int status = client.executeHttpMethod(propfindMethod);
|
||||||
|
|
||||||
if (previousFollowRedirects) {
|
if (previousFollowRedirects) {
|
||||||
mRedirectionPath = client.followRedirection(propfind);
|
mRedirectionPath = client.followRedirection(propfindMethod);
|
||||||
status = mRedirectionPath.getLastStatus();
|
status = mRedirectionPath.getLastStatus();
|
||||||
}
|
}
|
||||||
if (status != FORBIDDEN_ERROR && status != SERVICE_UNAVAILABLE_ERROR) {
|
|
||||||
client.exhaustResponse(propfind.getResponseBodyAsStream());
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* PROPFIND method
|
* PROPFIND method
|
||||||
* 404 NOT FOUND: path doesn't exist,
|
* 404 NOT FOUND: path doesn't exist,
|
||||||
* 207 MULTI_STATUS: path exists.
|
* 207 MULTI_STATUS: path exists.
|
||||||
*/
|
*/
|
||||||
boolean success = ((status == HttpStatus.SC_OK || status == HttpStatus.SC_MULTI_STATUS) &&
|
|
||||||
!mSuccessIfAbsent) ||
|
Log_OC.d(TAG, "Existence check for " + client.getNewFilesWebDavUri() +
|
||||||
(status == HttpStatus.SC_MULTI_STATUS && !mSuccessIfAbsent) ||
|
|
||||||
(status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
|
|
||||||
result = new RemoteOperationResult(
|
|
||||||
success,
|
|
||||||
propfind
|
|
||||||
);
|
|
||||||
Log_OC.d(TAG, "Existence check for " + client.getWebdavUri() +
|
|
||||||
WebdavUtils.encodePath(mPath) + " targeting for " +
|
WebdavUtils.encodePath(mPath) + " targeting for " +
|
||||||
(mSuccessIfAbsent ? " absence " : " existence ") +
|
(mSuccessIfAbsent ? " absence " : " existence ") +
|
||||||
"finished with HTTP status " + status + (!success?"(FAIL)":""));
|
"finished with HTTP status " + status + (!isSuccess(status) ? "(FAIL)" : ""));
|
||||||
|
|
||||||
|
return isSuccess(status)
|
||||||
|
? new RemoteOperationResult<>(OK)
|
||||||
|
: new RemoteOperationResult<>(propfindMethod);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Existence check for " + client.getWebdavUri() +
|
Log_OC.e(TAG, "Existence check for " + client.getNewFilesWebDavUri() +
|
||||||
WebdavUtils.encodePath(mPath) + " targeting for " +
|
WebdavUtils.encodePath(mPath) + " targeting for " +
|
||||||
(mSuccessIfAbsent ? " absence " : " existence ") + ": " +
|
(mSuccessIfAbsent ? " absence " : " existence ") + ": " +
|
||||||
result.getLogMessage(), result.getException());
|
result.getLogMessage(), result.getException());
|
||||||
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
if (propfind != null)
|
|
||||||
propfind.releaseConnection();
|
|
||||||
client.setFollowRedirects(previousFollowRedirects);
|
client.setFollowRedirects(previousFollowRedirects);
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the sequence of redirections followed during the execution of the operation.
|
* Gets the sequence of redirections followed during the execution of the operation.
|
||||||
*
|
*
|
||||||
* @return Sequence of redirections followed, if any, or NULL if the operation was not executed.
|
* @return Sequence of redirections followed, if any, or NULL if the operation was not executed.
|
||||||
*/
|
*/
|
||||||
public RedirectionPath getRedirectionPath() {
|
public RedirectionPath getRedirectionPath() {
|
||||||
return mRedirectionPath;
|
return mRedirectionPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 'True' if the operation was executed and at least one redirection was followed.
|
* @return 'True' if the operation was executed and at least one redirection was followed.
|
||||||
*/
|
*/
|
||||||
public boolean wasRedirected() {
|
public boolean wasRedirected() {
|
||||||
return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0);
|
return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private boolean isSuccess(int status) {
|
||||||
|
return ((status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_MULTI_STATUS) && !mSuccessIfAbsent)
|
||||||
|
|| (status == HttpConstants.HTTP_MULTI_STATUS && !mSuccessIfAbsent)
|
||||||
|
|| (status == HttpConstants.HTTP_NOT_FOUND && mSuccessIfAbsent);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,17 +24,16 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
private static final String TAG = FileUtils.class.getSimpleName();
|
private static final String TAG = FileUtils.class.getSimpleName();
|
||||||
|
|
||||||
public static final String PATH_SEPARATOR = "/";
|
public static final String PATH_SEPARATOR = "/";
|
||||||
|
public static final String FINAL_CHUNKS_FILE = ".file";
|
||||||
|
|
||||||
public static String getParentPath(String remotePath) {
|
public static String getParentPath(String remotePath) {
|
||||||
String parentPath = new File(remotePath).getParent();
|
String parentPath = new File(remotePath).getParent();
|
||||||
@ -82,5 +81,4 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,31 +24,29 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.io.IOException;
|
import android.net.Uri;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavException;
|
|
||||||
import org.apache.jackrabbit.webdav.MultiStatusResponse;
|
|
||||||
import org.apache.jackrabbit.webdav.Status;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
* Remote operation moving a remote file or folder in the ownCloud server to a different folder
|
||||||
* in the same account.
|
* in the same account.
|
||||||
* <p>
|
*
|
||||||
* Allows renaming the moving file/folder at the same time.
|
* Allows renaming the moving file/folder at the same time.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class MoveRemoteFileOperation extends RemoteOperation {
|
public class MoveRemoteFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
@ -59,28 +57,29 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
private String mSrcRemotePath;
|
private String mSrcRemotePath;
|
||||||
private String mTargetRemotePath;
|
private String mTargetRemotePath;
|
||||||
|
|
||||||
private boolean mOverwrite;
|
private boolean mOverwrite;
|
||||||
|
|
||||||
|
protected boolean moveChunkedFile = false;
|
||||||
|
protected String mFileLastModifTimestamp;
|
||||||
|
protected long mFileLength;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* <p>
|
*
|
||||||
* TODO Paths should finish in "/" in the case of folders. ?
|
* TODO Paths should finish in "/" in the case of folders. ?
|
||||||
*
|
*
|
||||||
* @param srcRemotePath Remote path of the file/folder to move.
|
* @param srcRemotePath Remote path of the file/folder to move.
|
||||||
* @param targetRemotePath Remove path desired for the file/folder after moving it.
|
* @param targetRemotePath Remote path desired for the file/folder after moving it.
|
||||||
*/
|
*/
|
||||||
public MoveRemoteFileOperation(
|
public MoveRemoteFileOperation(String srcRemotePath,
|
||||||
String srcRemotePath, String targetRemotePath, boolean overwrite
|
String targetRemotePath,
|
||||||
) {
|
boolean overwrite) {
|
||||||
|
|
||||||
mSrcRemotePath = srcRemotePath;
|
mSrcRemotePath = srcRemotePath;
|
||||||
mTargetRemotePath = targetRemotePath;
|
mTargetRemotePath = targetRemotePath;
|
||||||
mOverwrite = overwrite;
|
mOverwrite = overwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the rename operation.
|
* Performs the rename operation.
|
||||||
*
|
*
|
||||||
@ -95,45 +94,52 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
/// check parameters
|
/// check parameters
|
||||||
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) {
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
|
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
if (mTargetRemotePath.equals(mSrcRemotePath)) {
|
||||||
// nothing to do!
|
// nothing to do!
|
||||||
return new RemoteOperationResult(ResultCode.OK);
|
return new RemoteOperationResult<>(ResultCode.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
if (mTargetRemotePath.startsWith(mSrcRemotePath)) {
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_MOVE_INTO_DESCENDANT);
|
return new RemoteOperationResult<>(ResultCode.INVALID_MOVE_INTO_DESCENDANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// perform remote operation
|
/// perform remote operation
|
||||||
MoveMethod move = null;
|
RemoteOperationResult result;
|
||||||
RemoteOperationResult result = null;
|
|
||||||
try {
|
try {
|
||||||
move = new MoveMethod(
|
// After finishing a chunked upload, we have to move the resulting file from uploads folder to files one,
|
||||||
client.getWebdavUri() + WebdavUtils.encodePath(mSrcRemotePath),
|
// so this uri has to be customizable
|
||||||
client.getWebdavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
Uri srcWebDavUri = moveChunkedFile ? client.getNewUploadsWebDavUri() : client.getNewFilesWebDavUri();
|
||||||
mOverwrite
|
|
||||||
);
|
|
||||||
int status = client.executeMethod(move, MOVE_READ_TIMEOUT, MOVE_CONNECTION_TIMEOUT);
|
|
||||||
|
|
||||||
|
final MoveMethod move = new MoveMethod(
|
||||||
|
new URL(srcWebDavUri + WebdavUtils.encodePath(mSrcRemotePath)),
|
||||||
|
client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mTargetRemotePath),
|
||||||
|
mOverwrite);
|
||||||
|
|
||||||
|
if (moveChunkedFile) {
|
||||||
|
move.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
||||||
|
move.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(mFileLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
move.setReadTimeout(MOVE_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
move.setConnectionTimeout(MOVE_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
final int status = client.executeHttpMethod(move);
|
||||||
/// process response
|
/// process response
|
||||||
if (status == HttpStatus.SC_MULTI_STATUS) {
|
if(isSuccess(status)) {
|
||||||
result = processPartialError(move);
|
result = new RemoteOperationResult<>(ResultCode.OK);
|
||||||
|
} else if (status == HttpConstants.HTTP_PRECONDITION_FAILED && !mOverwrite) {
|
||||||
|
|
||||||
} else if (status == HttpStatus.SC_PRECONDITION_FAILED && !mOverwrite) {
|
result = new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||||
|
|
||||||
result = new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
|
||||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||||
|
|
||||||
|
|
||||||
/// for other errors that could be explicitly handled, check first:
|
/// for other errors that could be explicitly handled, check first:
|
||||||
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
/// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(isSuccess(status), move);
|
result = new RemoteOperationResult<>(move);
|
||||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,67 +147,15 @@ public class MoveRemoteFileOperation extends RemoteOperation {
|
|||||||
result.getLogMessage());
|
result.getLogMessage());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
Log.e(TAG, "Move " + mSrcRemotePath + " to " + mTargetRemotePath + ": " +
|
||||||
result.getLogMessage(), e);
|
result.getLogMessage(), e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (move != null)
|
|
||||||
move.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analyzes a multistatus response from the OC server to generate an appropriate result.
|
|
||||||
* <p>
|
|
||||||
* In WebDAV, a MOVE request on collections (folders) can be PARTIALLY successful: some
|
|
||||||
* children are moved, some other aren't.
|
|
||||||
* <p>
|
|
||||||
* According to the WebDAV specification, a multistatus response SHOULD NOT include partial
|
|
||||||
* successes (201, 204) nor for descendants of already failed children (424) in the response
|
|
||||||
* entity. But SHOULD NOT != MUST NOT, so take carefully.
|
|
||||||
*
|
|
||||||
* @param move Move operation just finished with a multistatus response
|
|
||||||
* @throws IOException If the response body could not be parsed
|
|
||||||
* @throws DavException If the status code is other than MultiStatus or if obtaining
|
|
||||||
* the response XML document fails
|
|
||||||
* @return A result for the {@link MoveRemoteFileOperation} caller
|
|
||||||
*/
|
|
||||||
private RemoteOperationResult processPartialError(MoveMethod move)
|
|
||||||
throws IOException, DavException {
|
|
||||||
// Adding a list of failed descendants to the result could be interesting; or maybe not.
|
|
||||||
// For the moment, let's take the easy way.
|
|
||||||
|
|
||||||
/// check that some error really occurred
|
|
||||||
MultiStatusResponse[] responses = move.getResponseBodyAsMultiStatus().getResponses();
|
|
||||||
Status[] status = null;
|
|
||||||
boolean failFound = false;
|
|
||||||
for (int i = 0; i < responses.length && !failFound; i++) {
|
|
||||||
status = responses[i].getStatus();
|
|
||||||
failFound = (
|
|
||||||
status != null &&
|
|
||||||
status.length > 0 &&
|
|
||||||
status[0].getStatusCode() > 299
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteOperationResult result;
|
|
||||||
if (failFound) {
|
|
||||||
result = new RemoteOperationResult(ResultCode.PARTIAL_MOVE_DONE);
|
|
||||||
} else {
|
|
||||||
result = new RemoteOperationResult(true, move);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected boolean isSuccess(int status) {
|
protected boolean isSuccess(int status) {
|
||||||
return status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT;
|
return status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -23,20 +23,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavConstants;
|
|
||||||
import org.apache.jackrabbit.webdav.MultiStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.network.WebdavEntry;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the read a file from the ownCloud server.
|
* Remote operation performing the read a file from the ownCloud server.
|
||||||
@ -45,7 +45,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ReadRemoteFileOperation extends RemoteOperation {
|
public class ReadRemoteFileOperation extends RemoteOperation<RemoteFile> {
|
||||||
|
|
||||||
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
|
private static final String TAG = ReadRemoteFileOperation.class.getSimpleName();
|
||||||
private static final int SYNC_READ_TIMEOUT = 40000;
|
private static final int SYNC_READ_TIMEOUT = 40000;
|
||||||
@ -53,7 +53,6 @@ public class ReadRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
private String mRemotePath;
|
private String mRemotePath;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -69,51 +68,41 @@ public class ReadRemoteFileOperation extends RemoteOperation {
|
|||||||
* @param client Client object to communicate with the remote ownCloud server.
|
* @param client Client object to communicate with the remote ownCloud server.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<RemoteFile> run(OwnCloudClient client) {
|
||||||
PropFindMethod propfind = null;
|
PropfindMethod propfind;
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<RemoteFile> result;
|
||||||
|
|
||||||
/// take the duty of check the server for the current state of the file there
|
/// take the duty of check the server for the current state of the file there
|
||||||
try {
|
try {
|
||||||
// remote request
|
// remote request
|
||||||
propfind = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath),
|
propfind = new PropfindMethod(new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
|
||||||
WebdavUtils.getFilePropSet(), // PropFind Properties
|
DEPTH_0,
|
||||||
DavConstants.DEPTH_0);
|
DavUtils.getAllPropset());
|
||||||
int status;
|
|
||||||
status = client.executeMethod(propfind, SYNC_READ_TIMEOUT, SYNC_CONNECTION_TIMEOUT);
|
|
||||||
|
|
||||||
boolean isSuccess = (
|
propfind.setReadTimeout(SYNC_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
status == HttpStatus.SC_MULTI_STATUS ||
|
propfind.setConnectionTimeout(SYNC_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
status == HttpStatus.SC_OK
|
final int status = client.executeHttpMethod(propfind);
|
||||||
);
|
|
||||||
if (isSuccess) {
|
|
||||||
// Parse response
|
|
||||||
MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
|
|
||||||
WebdavEntry we = new WebdavEntry(resp.getResponses()[0],
|
|
||||||
client.getWebdavUri().getPath());
|
|
||||||
RemoteFile remoteFile = new RemoteFile(we);
|
|
||||||
ArrayList<Object> files = new ArrayList<Object>();
|
|
||||||
files.add(remoteFile);
|
|
||||||
|
|
||||||
// Result of the operation
|
if (status == HttpConstants.HTTP_MULTI_STATUS
|
||||||
result = new RemoteOperationResult(true, propfind);
|
|| status == HttpConstants.HTTP_OK) {
|
||||||
result.setData(files);
|
|
||||||
|
final RemoteFile file = new RemoteFile(propfind.getRoot(), client.getCredentials().getUsername());
|
||||||
|
|
||||||
|
result = new RemoteOperationResult<>(OK);
|
||||||
|
result.setData(file);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, propfind);
|
result = new RemoteOperationResult<>(propfind);
|
||||||
client.exhaustResponse(propfind.getResponseBodyAsStream());
|
client.exhaustResponse(propfind.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
|
Log_OC.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(),
|
||||||
result.getException());
|
result.getException());
|
||||||
} finally {
|
|
||||||
if (propfind != null)
|
|
||||||
propfind.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,22 +1,22 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -24,33 +24,36 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavConstants;
|
|
||||||
import org.apache.jackrabbit.webdav.MultiStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.network.WebdavEntry;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.DavConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.Response;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the read of remote file or folder in the ownCloud server.
|
* Remote operation performing the read of remote file or folder in the ownCloud server.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ReadRemoteFolderOperation extends RemoteOperation {
|
public class ReadRemoteFolderOperation extends RemoteOperation<ArrayList<RemoteFile>> {
|
||||||
|
|
||||||
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
|
private static final String TAG = ReadRemoteFolderOperation.class.getSimpleName();
|
||||||
|
|
||||||
private String mRemotePath;
|
private String mRemotePath;
|
||||||
private ArrayList<Object> mFolderAndFiles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -67,110 +70,60 @@ public class ReadRemoteFolderOperation extends RemoteOperation {
|
|||||||
* @param client Client object to communicate with the remote ownCloud server.
|
* @param client Client object to communicate with the remote ownCloud server.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ArrayList<RemoteFile>> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<ArrayList<RemoteFile>> result = null;
|
||||||
PropFindMethod query = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// remote request
|
PropfindMethod propfindMethod = new PropfindMethod(
|
||||||
query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath),
|
new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
|
||||||
WebdavUtils.getAllPropSet(), // PropFind Properties
|
DavConstants.DEPTH_1,
|
||||||
DavConstants.DEPTH_1);
|
DavUtils.getAllPropset());
|
||||||
int status = client.executeMethod(query);
|
|
||||||
|
|
||||||
// check and process response
|
client.setFollowRedirects(true);
|
||||||
boolean isSuccess = (
|
|
||||||
status == HttpStatus.SC_MULTI_STATUS ||
|
int status = client.executeHttpMethod(propfindMethod);
|
||||||
status == HttpStatus.SC_OK
|
|
||||||
);
|
if (isSuccess(status)) {
|
||||||
if (isSuccess) {
|
ArrayList<RemoteFile> mFolderAndFiles = new ArrayList<>();
|
||||||
// get data from remote folder
|
|
||||||
MultiStatus dataInServer = query.getResponseBodyAsMultiStatus();
|
// parse data from remote folder
|
||||||
readData(dataInServer, client);
|
mFolderAndFiles.add(
|
||||||
|
new RemoteFile(propfindMethod.getRoot(), client.getCredentials().getUsername())
|
||||||
|
);
|
||||||
|
|
||||||
|
// loop to update every child
|
||||||
|
for (Response resource : propfindMethod.getMembers()) {
|
||||||
|
RemoteFile file = new RemoteFile(resource, client.getCredentials().getUsername());
|
||||||
|
mFolderAndFiles.add(file);
|
||||||
|
}
|
||||||
|
|
||||||
// Result of the operation
|
// Result of the operation
|
||||||
result = new RemoteOperationResult(true, query);
|
result = new RemoteOperationResult<>(OK);
|
||||||
// Add data to the result
|
result.setData(mFolderAndFiles);
|
||||||
if (result.isSuccess()) {
|
|
||||||
result.setData(mFolderAndFiles);
|
} else { // synchronization failed
|
||||||
}
|
result = new RemoteOperationResult<> (propfindMethod);
|
||||||
} else {
|
|
||||||
// synchronization failed
|
|
||||||
result = new RemoteOperationResult(false, query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (query != null)
|
|
||||||
query.releaseConnection(); // let the connection available for other methods
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
Log_OC.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
Log_OC.i(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||||
} else {
|
} else {
|
||||||
if (result.isException()) {
|
if (result.isException()) {
|
||||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(),
|
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage(),
|
||||||
result.getException());
|
result.getException());
|
||||||
} else {
|
} else {
|
||||||
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
Log_OC.e(TAG, "Synchronized " + mRemotePath + ": " + result.getLogMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMultiStatus(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_MULTI_STATUS);
|
return status == HttpConstants.HTTP_MULTI_STATUS ||
|
||||||
|
status == HttpConstants.HTTP_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Read the data retrieved from the server about the contents of the target folder
|
|
||||||
*
|
|
||||||
* @param remoteData Full response got from the server with the data of the target
|
|
||||||
* folder and its direct children.
|
|
||||||
* @param client Client instance to the remote server where the data were
|
|
||||||
* retrieved.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private void readData(MultiStatus remoteData, OwnCloudClient client) {
|
|
||||||
mFolderAndFiles = new ArrayList<Object>();
|
|
||||||
|
|
||||||
// parse data from remote folder
|
|
||||||
WebdavEntry we = new WebdavEntry(remoteData.getResponses()[0],
|
|
||||||
client.getWebdavUri().getPath());
|
|
||||||
mFolderAndFiles.add(fillOCFile(we));
|
|
||||||
|
|
||||||
// loop to update every child
|
|
||||||
RemoteFile remoteFile = null;
|
|
||||||
for (int i = 1; i < remoteData.getResponses().length; ++i) {
|
|
||||||
/// new OCFile instance with the data from the server
|
|
||||||
we = new WebdavEntry(remoteData.getResponses()[i], client.getWebdavUri().getPath());
|
|
||||||
remoteFile = fillOCFile(we);
|
|
||||||
mFolderAndFiles.add(remoteFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and populates a new {@link RemoteFile} object with the data read from the server.
|
|
||||||
*
|
|
||||||
* @param we WebDAV entry read from the server for a WebDAV resource (remote file or folder).
|
|
||||||
* @return New OCFile instance representing the remote resource described by we.
|
|
||||||
*/
|
|
||||||
private RemoteFile fillOCFile(WebdavEntry we) {
|
|
||||||
RemoteFile file = new RemoteFile(we.decodedPath());
|
|
||||||
file.setCreationTimestamp(we.createTimestamp());
|
|
||||||
file.setLength(we.contentLength());
|
|
||||||
file.setMimeType(we.contentType());
|
|
||||||
file.setModifiedTimestamp(we.modifiedTimestamp());
|
|
||||||
file.setEtag(we.etag());
|
|
||||||
file.setPermissions(we.permissions());
|
|
||||||
file.setRemoteId(we.remoteId());
|
|
||||||
file.setSize(we.size());
|
|
||||||
file.setQuotaUsedBytes(we.quotaUsedBytes());
|
|
||||||
file.setQuotaAvailableBytes(we.quotaAvailableBytes());
|
|
||||||
file.setPrivateLink(we.privateLink());
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,18 +24,36 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import android.net.Uri;
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.network.WebdavEntry;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import at.bitfire.dav4android.Property;
|
||||||
|
import at.bitfire.dav4android.Response;
|
||||||
|
import at.bitfire.dav4android.property.CreationDate;
|
||||||
|
import at.bitfire.dav4android.property.GetContentLength;
|
||||||
|
import at.bitfire.dav4android.property.GetContentType;
|
||||||
|
import at.bitfire.dav4android.property.GetETag;
|
||||||
|
import at.bitfire.dav4android.property.GetLastModified;
|
||||||
|
import at.bitfire.dav4android.property.QuotaAvailableBytes;
|
||||||
|
import at.bitfire.dav4android.property.QuotaUsedBytes;
|
||||||
|
import at.bitfire.dav4android.property.owncloud.OCId;
|
||||||
|
import at.bitfire.dav4android.property.owncloud.OCPermissions;
|
||||||
|
import at.bitfire.dav4android.property.owncloud.OCPrivatelink;
|
||||||
|
import at.bitfire.dav4android.property.owncloud.OCSize;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.OwnCloudClient.NEW_WEBDAV_FILES_PATH_4_0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the data of a Remote File from a WebDavEntry
|
* Contains the data of a Remote File from a WebDavEntry
|
||||||
*
|
*
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author Christian Schabesberger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RemoteFile implements Parcelable, Serializable {
|
public class RemoteFile implements Parcelable, Serializable {
|
||||||
@ -156,7 +174,7 @@ public class RemoteFile implements Parcelable, Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new {@link RemoteFile} with given path.
|
* Create new {@link RemoteFile} with given path.
|
||||||
* <p>
|
*
|
||||||
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
|
* The path received must be URL-decoded. Path separator must be OCFile.PATH_SEPARATOR, and it must be the first character in 'path'.
|
||||||
*
|
*
|
||||||
* @param path The remote path of the file.
|
* @param path The remote path of the file.
|
||||||
@ -167,21 +185,52 @@ public class RemoteFile implements Parcelable, Serializable {
|
|||||||
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
|
throw new IllegalArgumentException("Trying to create a OCFile with a non valid remote path: " + path);
|
||||||
}
|
}
|
||||||
mRemotePath = path;
|
mRemotePath = path;
|
||||||
|
mCreationTimestamp = 0;
|
||||||
|
mLength = 0;
|
||||||
|
mMimeType = "DIR";
|
||||||
|
mQuotaUsedBytes = BigDecimal.ZERO;
|
||||||
|
mQuotaAvailableBytes = BigDecimal.ZERO;
|
||||||
|
mPrivateLink = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteFile(WebdavEntry webdavEntry) {
|
public RemoteFile(final Response davResource, String userName) {
|
||||||
this(webdavEntry.decodedPath());
|
this(getRemotePathFromUrl(davResource.getHref(), userName));
|
||||||
this.setCreationTimestamp(webdavEntry.createTimestamp());
|
final List<Property> properties = davResource.getProperties();
|
||||||
this.setLength(webdavEntry.contentLength());
|
|
||||||
this.setMimeType(webdavEntry.contentType());
|
for(Property property : properties) {
|
||||||
this.setModifiedTimestamp(webdavEntry.modifiedTimestamp());
|
if(property instanceof CreationDate)
|
||||||
this.setEtag(webdavEntry.etag());
|
this.setCreationTimestamp(
|
||||||
this.setPermissions(webdavEntry.permissions());
|
Long.parseLong(((CreationDate) property).getCreationDate()));
|
||||||
this.setRemoteId(webdavEntry.remoteId());
|
if(property instanceof GetContentLength)
|
||||||
this.setSize(webdavEntry.size());
|
this.setLength(((GetContentLength) property).getContentLength());
|
||||||
this.setQuotaUsedBytes(webdavEntry.quotaUsedBytes());
|
if(property instanceof GetContentType)
|
||||||
this.setQuotaAvailableBytes(webdavEntry.quotaAvailableBytes());
|
this.setMimeType(((GetContentType) property).getType());
|
||||||
this.setPrivateLink(webdavEntry.privateLink());
|
if(property instanceof GetLastModified)
|
||||||
|
this.setModifiedTimestamp(((GetLastModified) property).getLastModified());
|
||||||
|
if(property instanceof GetETag)
|
||||||
|
this.setEtag(((GetETag) property).getETag());
|
||||||
|
if(property instanceof OCPermissions)
|
||||||
|
this.setPermissions(((OCPermissions) property).getPermission());
|
||||||
|
if(property instanceof OCId)
|
||||||
|
this.setRemoteId(((OCId) property).getId());
|
||||||
|
if(property instanceof OCSize)
|
||||||
|
this.setSize(((OCSize) property).getSize());
|
||||||
|
if(property instanceof QuotaUsedBytes)
|
||||||
|
this.setQuotaUsedBytes(
|
||||||
|
BigDecimal.valueOf(((QuotaUsedBytes) property).getQuotaUsedBytes()));
|
||||||
|
if(property instanceof QuotaAvailableBytes)
|
||||||
|
this.setQuotaAvailableBytes(
|
||||||
|
BigDecimal.valueOf(((QuotaAvailableBytes) property).getQuotaAvailableBytes()));
|
||||||
|
if(property instanceof OCPrivatelink)
|
||||||
|
this.setPrivateLink(((OCPrivatelink) property).getLink());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String getRemotePathFromUrl(HttpUrl url, String displayName) {
|
||||||
|
final String davPath = NEW_WEBDAV_FILES_PATH_4_0 + displayName;
|
||||||
|
final String pathToOc = url.encodedPath().split(davPath)[0];
|
||||||
|
return Uri.decode(url.encodedPath()).replace(pathToOc + davPath, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,5 +311,4 @@ public class RemoteFile implements Parcelable, Serializable {
|
|||||||
dest.writeSerializable(mQuotaAvailableBytes);
|
dest.writeSerializable(mQuotaAvailableBytes);
|
||||||
dest.writeString(mPrivateLink);
|
dest.writeString(mPrivateLink);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,29 +24,33 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import android.net.Uri;
|
||||||
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the removal of a remote file or folder in the ownCloud server.
|
* Remote operation performing the removal of a remote file or folder in the ownCloud server.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class RemoveRemoteFileOperation extends RemoteOperation {
|
public class RemoveRemoteFileOperation extends RemoteOperation {
|
||||||
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
|
private static final String TAG = RemoveRemoteFileOperation.class.getSimpleName();
|
||||||
|
|
||||||
private static final int REMOVE_READ_TIMEOUT = 30000;
|
|
||||||
private static final int REMOVE_CONNECTION_TIMEOUT = 5000;
|
|
||||||
|
|
||||||
private String mRemotePath;
|
private String mRemotePath;
|
||||||
|
|
||||||
|
protected boolean removeChunksFolder = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -63,30 +67,31 @@ public class RemoveRemoteFileOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result;
|
||||||
DeleteMethod delete = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
delete = new DeleteMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
|
Uri srcWebDavUri = removeChunksFolder ? client.getNewUploadsWebDavUri() : client.getNewFilesWebDavUri();
|
||||||
int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
|
|
||||||
|
DeleteMethod deleteMethod = new DeleteMethod(
|
||||||
|
new URL(srcWebDavUri + WebdavUtils.encodePath(mRemotePath)));
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(deleteMethod);
|
||||||
|
|
||||||
|
result = isSuccess(status) ?
|
||||||
|
new RemoteOperationResult<>(OK) :
|
||||||
|
new RemoteOperationResult<>(deleteMethod);
|
||||||
|
|
||||||
delete.getResponseBodyAsString(); // exhaust the response, although not interesting
|
|
||||||
result = new RemoteOperationResult(
|
|
||||||
(delete.succeeded() || status == HttpStatus.SC_NOT_FOUND),
|
|
||||||
delete
|
|
||||||
);
|
|
||||||
Log_OC.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
Log_OC.i(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage());
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
|
Log_OC.e(TAG, "Remove " + mRemotePath + ": " + result.getLogMessage(), e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (delete != null)
|
|
||||||
delete.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private boolean isSuccess(int status) {
|
||||||
|
return status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_NO_CONTENT;
|
||||||
|
}
|
||||||
|
}
|
@ -24,17 +24,17 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import android.os.RemoteException;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
import org.apache.jackrabbit.webdav.client.methods.DavMethodBase;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.MoveMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
|
||||||
@ -57,7 +57,6 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
private String mNewName;
|
private String mNewName;
|
||||||
private String mNewRemotePath;
|
private String mNewRemotePath;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -88,51 +87,48 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
|
||||||
|
|
||||||
LocalMoveMethod move = null;
|
final OwnCloudVersion version = client.getOwnCloudVersion();
|
||||||
|
final boolean versionWithForbiddenChars =
|
||||||
OwnCloudVersion version = client.getOwnCloudVersion();
|
|
||||||
boolean versionWithForbiddenChars =
|
|
||||||
(version != null && version.isVersionWithForbiddenCharacters());
|
(version != null && version.isVersionWithForbiddenCharacters());
|
||||||
boolean noInvalidChars = FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars);
|
|
||||||
|
|
||||||
if (noInvalidChars) {
|
if(!FileUtils.isValidPath(mNewRemotePath, versionWithForbiddenChars))
|
||||||
try {
|
return new RemoteOperationResult<>(ResultCode.INVALID_CHARACTER_IN_NAME);
|
||||||
if (mNewName.equals(mOldName)) {
|
|
||||||
return new RemoteOperationResult(ResultCode.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetPathIsUsed(client)) {
|
try {
|
||||||
return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
|
if (mNewName.equals(mOldName)) {
|
||||||
}
|
return new RemoteOperationResult<>(ResultCode.OK);
|
||||||
|
|
||||||
move = new LocalMoveMethod(client.getWebdavUri() +
|
|
||||||
WebdavUtils.encodePath(mOldRemotePath),
|
|
||||||
client.getWebdavUri() + WebdavUtils.encodePath(mNewRemotePath));
|
|
||||||
client.executeMethod(move, RENAME_READ_TIMEOUT, RENAME_CONNECTION_TIMEOUT);
|
|
||||||
result = new RemoteOperationResult(move.succeeded(), move);
|
|
||||||
Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
|
|
||||||
result.getLogMessage()
|
|
||||||
);
|
|
||||||
client.exhaustResponse(move.getResponseBodyAsStream());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
result = new RemoteOperationResult(e);
|
|
||||||
Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
|
|
||||||
((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ": " +
|
|
||||||
result.getLogMessage(), e);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (move != null)
|
|
||||||
move.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
if (targetPathIsUsed(client)) {
|
||||||
result = new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME);
|
return new RemoteOperationResult<>(ResultCode.INVALID_OVERWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
final MoveMethod move = new MoveMethod(new URL(client.getNewFilesWebDavUri() +
|
||||||
|
WebdavUtils.encodePath(mOldRemotePath)),
|
||||||
|
client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mNewRemotePath), false);
|
||||||
|
|
||||||
|
move.setReadTimeout(RENAME_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
move.setConnectionTimeout(RENAME_READ_TIMEOUT, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
final int status = client.executeHttpMethod(move);
|
||||||
|
final RemoteOperationResult result =
|
||||||
|
(status == HttpConstants.HTTP_CREATED || status == HttpConstants.HTTP_NO_CONTENT)
|
||||||
|
? new RemoteOperationResult<>(ResultCode.OK)
|
||||||
|
: new RemoteOperationResult<>(move);
|
||||||
|
|
||||||
|
Log_OC.i(TAG, "Rename " + mOldRemotePath + " to " + mNewRemotePath + ": " +
|
||||||
|
result.getLogMessage()
|
||||||
|
);
|
||||||
|
client.exhaustResponse(move.getResponseBodyAsStream());
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
final RemoteOperationResult result = new RemoteOperationResult<>(e);
|
||||||
|
Log_OC.e(TAG, "Rename " + mOldRemotePath + " to " +
|
||||||
|
((mNewRemotePath == null) ? mNewName : mNewRemotePath) + ": " +
|
||||||
|
result.getLogMessage(), e);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,27 +142,4 @@ public class RenameRemoteFileOperation extends RemoteOperation {
|
|||||||
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
|
RemoteOperationResult exists = existenceCheckRemoteOperation.run(client);
|
||||||
return exists.isSuccess();
|
return exists.isSuccess();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Move operation
|
|
||||||
*/
|
|
||||||
private class LocalMoveMethod extends DavMethodBase {
|
|
||||||
|
|
||||||
public LocalMoveMethod(String uri, String dest) {
|
|
||||||
super(uri);
|
|
||||||
addRequestHeader(new org.apache.commons.httpclient.Header("Destination", dest));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "MOVE";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isSuccess(int status) {
|
|
||||||
return status == 201 || status == 204;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,46 +24,39 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.files;
|
package com.owncloud.android.lib.resources.files;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.PutMethod;
|
|
||||||
import org.apache.commons.httpclient.methods.RequestEntity;
|
|
||||||
import org.apache.commons.httpclient.params.HttpMethodParams;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.network.FileRequestEntity;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PutMethod;
|
||||||
|
import com.owncloud.android.lib.common.network.FileRequestBody;
|
||||||
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
||||||
import com.owncloud.android.lib.common.network.ProgressiveDataTransferer;
|
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.InvalidCharacterExceptionParser;
|
|
||||||
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remote operation performing the upload of a remote file to the ownCloud server.
|
* Remote operation performing the upload of a remote file to the ownCloud server.
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class UploadRemoteFileOperation extends RemoteOperation {
|
public class UploadRemoteFileOperation extends RemoteOperation {
|
||||||
|
|
||||||
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
||||||
|
|
||||||
protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
|
||||||
protected static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime";
|
|
||||||
protected static final String IF_MATCH_HEADER = "If-Match";
|
|
||||||
|
|
||||||
protected String mLocalPath;
|
protected String mLocalPath;
|
||||||
protected String mRemotePath;
|
protected String mRemotePath;
|
||||||
protected String mMimeType;
|
protected String mMimeType;
|
||||||
@ -74,7 +67,7 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
||||||
|
|
||||||
protected RequestEntity mEntity = null;
|
protected FileRequestBody mFileRequestBody = null;
|
||||||
|
|
||||||
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType,
|
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType,
|
||||||
String fileLastModifTimestamp) {
|
String fileLastModifTimestamp) {
|
||||||
@ -92,80 +85,69 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result;
|
||||||
DefaultHttpMethodRetryHandler oldRetryHandler =
|
|
||||||
(DefaultHttpMethodRetryHandler) client.getParams().getParameter(HttpMethodParams.RETRY_HANDLER);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// prevent that uploads are retried automatically by network library
|
mPutMethod = new PutMethod(
|
||||||
client.getParams().setParameter(
|
new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)));
|
||||||
HttpMethodParams.RETRY_HANDLER,
|
|
||||||
new DefaultHttpMethodRetryHandler(0, false)
|
|
||||||
);
|
|
||||||
|
|
||||||
mPutMethod = new PutMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
|
mPutMethod.setRetryOnConnectionFailure(false);
|
||||||
|
|
||||||
if (mCancellationRequested.get()) {
|
if (mCancellationRequested.get()) {
|
||||||
// the operation was cancelled before getting it's turn to be executed in the queue of uploads
|
// the operation was cancelled before getting it's turn to be executed in the queue of uploads
|
||||||
result = new RemoteOperationResult(new OperationCancelledException());
|
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// perform the upload
|
// perform the upload
|
||||||
result = uploadFile(client);
|
result = uploadFile(client);
|
||||||
|
Log_OC.i(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||||
|
result.getLogMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
if (mPutMethod != null && mPutMethod.isAborted()) {
|
if (mPutMethod != null && mPutMethod.isAborted()) {
|
||||||
result = new RemoteOperationResult(new OperationCancelledException());
|
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||||
|
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||||
|
result.getLogMessage(), new OperationCancelledException());
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
|
Log_OC.e(TAG, "Upload of " + mLocalPath + " to " + mRemotePath + ": " +
|
||||||
|
result.getLogMessage(), e);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
// reset previous retry handler
|
|
||||||
client.getParams().setParameter(
|
|
||||||
HttpMethodParams.RETRY_HANDLER,
|
|
||||||
oldRetryHandler
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSuccess(int status) {
|
protected RemoteOperationResult<? extends Object> uploadFile(OwnCloudClient client) throws Exception {
|
||||||
return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED ||
|
|
||||||
status == HttpStatus.SC_NO_CONTENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RemoteOperationResult uploadFile(OwnCloudClient client) throws IOException {
|
File fileToUpload = new File(mLocalPath);
|
||||||
int status;
|
|
||||||
RemoteOperationResult result;
|
|
||||||
try {
|
|
||||||
File f = new File(mLocalPath);
|
|
||||||
mEntity = new FileRequestEntity(f, mMimeType);
|
|
||||||
synchronized (mDataTransferListeners) {
|
|
||||||
((ProgressiveDataTransferer)mEntity)
|
|
||||||
.addDatatransferProgressListeners(mDataTransferListeners);
|
|
||||||
}
|
|
||||||
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
|
||||||
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
|
||||||
}
|
|
||||||
mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length()));
|
|
||||||
|
|
||||||
mPutMethod.addRequestHeader(OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
MediaType mediaType = MediaType.parse(mMimeType);
|
||||||
|
|
||||||
mPutMethod.setRequestEntity(mEntity);
|
mFileRequestBody = new FileRequestBody(fileToUpload, mediaType);
|
||||||
status = client.executeMethod(mPutMethod);
|
|
||||||
|
|
||||||
result = new RemoteOperationResult(
|
synchronized (mDataTransferListeners) {
|
||||||
isSuccess(status),
|
mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners);
|
||||||
mPutMethod
|
}
|
||||||
);
|
|
||||||
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
|
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
||||||
|
mPutMethod.addRequestHeader(HttpConstants.IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
||||||
} finally {
|
}
|
||||||
mPutMethod.releaseConnection(); // let the connection available for other methods
|
|
||||||
|
mPutMethod.addRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER, String.valueOf(fileToUpload.length()));
|
||||||
|
mPutMethod.addRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp);
|
||||||
|
|
||||||
|
mPutMethod.setRequestBody(mFileRequestBody);
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(mPutMethod);
|
||||||
|
|
||||||
|
if (isSuccess(status)) {
|
||||||
|
return new RemoteOperationResult<>(OK);
|
||||||
|
|
||||||
|
} else { // synchronization failed
|
||||||
|
return new RemoteOperationResult<>(mPutMethod);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
|
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
|
||||||
@ -176,8 +158,8 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
synchronized (mDataTransferListeners) {
|
synchronized (mDataTransferListeners) {
|
||||||
mDataTransferListeners.add(listener);
|
mDataTransferListeners.add(listener);
|
||||||
}
|
}
|
||||||
if (mEntity != null) {
|
if (mFileRequestBody != null) {
|
||||||
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
|
mFileRequestBody.addDatatransferProgressListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +167,8 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
synchronized (mDataTransferListeners) {
|
synchronized (mDataTransferListeners) {
|
||||||
mDataTransferListeners.remove(listener);
|
mDataTransferListeners.remove(listener);
|
||||||
}
|
}
|
||||||
if (mEntity != null) {
|
if (mFileRequestBody != null) {
|
||||||
((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
|
mFileRequestBody.removeDatatransferProgressListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,4 +180,8 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public boolean isSuccess(int status) {
|
||||||
|
return ((status == HttpConstants.HTTP_OK || status == HttpConstants.HTTP_CREATED ||
|
||||||
|
status == HttpConstants.HTTP_NO_CONTENT));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.resources.files.chunks;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PutMethod;
|
||||||
|
import com.owncloud.android.lib.common.network.ChunkFromFileRequestBody;
|
||||||
|
import com.owncloud.android.lib.common.operations.OperationCancelledException;
|
||||||
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
import com.owncloud.android.lib.resources.files.FileUtils;
|
||||||
|
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.http.HttpConstants.IF_MATCH_HEADER;
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote operation performing the chunked upload of a remote file to the ownCloud server.
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation {
|
||||||
|
|
||||||
|
private static final int LAST_CHUNK_TIMEOUT = 900000; //15 mins.
|
||||||
|
public static final long CHUNK_SIZE = 1024000;
|
||||||
|
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
||||||
|
|
||||||
|
private String mTransferId;
|
||||||
|
|
||||||
|
public ChunkedUploadRemoteFileOperation(String transferId, String localPath, String remotePath, String mimeType,
|
||||||
|
String requiredEtag, String fileLastModifTimestamp) {
|
||||||
|
super(localPath, remotePath, mimeType, requiredEtag, fileLastModifTimestamp);
|
||||||
|
mTransferId = transferId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RemoteOperationResult uploadFile(OwnCloudClient client) throws Exception {
|
||||||
|
int status;
|
||||||
|
RemoteOperationResult result = null;
|
||||||
|
FileChannel channel;
|
||||||
|
RandomAccessFile raf;
|
||||||
|
|
||||||
|
File fileToUpload = new File(mLocalPath);
|
||||||
|
MediaType mediaType = MediaType.parse(mMimeType);
|
||||||
|
|
||||||
|
raf = new RandomAccessFile(fileToUpload, "r");
|
||||||
|
channel = raf.getChannel();
|
||||||
|
|
||||||
|
mFileRequestBody = new ChunkFromFileRequestBody(fileToUpload, mediaType, channel, CHUNK_SIZE);
|
||||||
|
|
||||||
|
synchronized (mDataTransferListeners) {
|
||||||
|
mFileRequestBody.addDatatransferProgressListeners(mDataTransferListeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
long offset = 0;
|
||||||
|
String uriPrefix = client.getNewUploadsWebDavUri() + FileUtils.PATH_SEPARATOR + String.valueOf(mTransferId);
|
||||||
|
long totalLength = fileToUpload.length();
|
||||||
|
long chunkCount = (long) Math.ceil((double) totalLength / CHUNK_SIZE);
|
||||||
|
|
||||||
|
for (int chunkIndex = 0; chunkIndex < chunkCount; chunkIndex++, offset += CHUNK_SIZE) {
|
||||||
|
mPutMethod = new PutMethod(
|
||||||
|
new URL(uriPrefix + FileUtils.PATH_SEPARATOR + chunkIndex)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
||||||
|
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
((ChunkFromFileRequestBody) mFileRequestBody).setOffset(offset);
|
||||||
|
|
||||||
|
if (mCancellationRequested.get()) {
|
||||||
|
result = new RemoteOperationResult<>(new OperationCancelledException());
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (chunkIndex == chunkCount - 1) {
|
||||||
|
// Added a high timeout to the last chunk due to when the last chunk
|
||||||
|
// arrives to the server with the last PUT, all chunks get assembled
|
||||||
|
// within that PHP request, so last one takes longer.
|
||||||
|
mPutMethod.setReadTimeout(LAST_CHUNK_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPutMethod.setRequestBody(mFileRequestBody);
|
||||||
|
|
||||||
|
status = client.executeHttpMethod(mPutMethod);
|
||||||
|
|
||||||
|
Log_OC.d(TAG, "Upload of " + mLocalPath + " to " + mRemotePath +
|
||||||
|
", chunk index " + chunkIndex + ", count " + chunkCount +
|
||||||
|
", HTTP result status " + status);
|
||||||
|
|
||||||
|
if (isSuccess(status)) {
|
||||||
|
result = new RemoteOperationResult<>(OK);
|
||||||
|
} else {
|
||||||
|
result = new RemoteOperationResult<>(mPutMethod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel != null)
|
||||||
|
channel.close();
|
||||||
|
|
||||||
|
if (raf != null)
|
||||||
|
raf.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.resources.files.chunks;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote operation performing the creation of a new folder to save chunks during an upload to the ownCloud server.
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class CreateRemoteChunkFolderOperation extends CreateRemoteFolderOperation {
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param remotePath Full path to the new directory to create in the remote server.
|
||||||
|
* @param createFullPath 'True' means that all the ancestor folders should be created.
|
||||||
|
*/
|
||||||
|
public CreateRemoteChunkFolderOperation(String remotePath, boolean createFullPath) {
|
||||||
|
super(remotePath, createFullPath);
|
||||||
|
createChunksFolder = true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* Copyright (C) 2018 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.resources.files.chunks;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.resources.files.MoveRemoteFileOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remote operation to move the file built from chunks after uploading it
|
||||||
|
*
|
||||||
|
* @author David González Verdugo
|
||||||
|
*/
|
||||||
|
public class MoveRemoteChunksFileOperation extends MoveRemoteFileOperation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param srcRemotePath Remote path of the file/folder to move.
|
||||||
|
* @param targetRemotePath Remove path desired for the file/folder after moving it.
|
||||||
|
* @param overwrite
|
||||||
|
*/
|
||||||
|
public MoveRemoteChunksFileOperation(String srcRemotePath, String targetRemotePath, boolean overwrite,
|
||||||
|
String fileLastModifTimestamp, long fileLength) {
|
||||||
|
super(srcRemotePath, targetRemotePath, overwrite);
|
||||||
|
moveChunkedFile = true;
|
||||||
|
mFileLastModifTimestamp = fileLastModifTimestamp;
|
||||||
|
mFileLength = fileLength;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* @author David González Verdugo
|
||||||
|
* Copyright (C) 2018 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.resources.files.chunks;
|
||||||
|
|
||||||
|
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
||||||
|
|
||||||
|
public class RemoveRemoteChunksFolderOperation extends RemoveRemoteFileOperation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param remotePath RemotePath of the remote file or folder to remove from the server
|
||||||
|
*/
|
||||||
|
public RemoveRemoteChunksFolderOperation(String remotePath) {
|
||||||
|
super(remotePath);
|
||||||
|
removeChunksFolder = true;
|
||||||
|
}
|
||||||
|
}
|
@ -2,24 +2,24 @@
|
|||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -30,20 +30,26 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.commons.httpclient.methods.PostMethod;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new share. This allows sharing with a user or group or as a link.
|
* Creates a new share. This allows sharing with a user or group or as a link.
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class CreateRemoteShareOperation extends RemoteOperation {
|
public class CreateRemoteShareOperation extends RemoteOperation {
|
||||||
|
|
||||||
@ -180,38 +186,22 @@ public class CreateRemoteShareOperation extends RemoteOperation {
|
|||||||
mPublicUpload = publicUpload;
|
mPublicUpload = publicUpload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGettingShareDetails() {
|
|
||||||
return mGetShareDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGetShareDetails(boolean set) {
|
public void setGetShareDetails(boolean set) {
|
||||||
mGetShareDetails = set;
|
mGetShareDetails = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult<ShareParserResult> result;
|
||||||
int status;
|
|
||||||
|
|
||||||
PostMethod post = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Uri requestUri = client.getBaseUri();
|
FormBody.Builder formBodyBuilder = new FormBody.Builder()
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
.add(PARAM_PATH, mRemoteFilePath)
|
||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
.add(PARAM_SHARE_TYPE, Integer.toString(mShareType.getValue()))
|
||||||
|
.add(PARAM_SHARE_WITH, mShareWith);
|
||||||
// Post Method
|
|
||||||
post = new PostMethod(uriBuilder.build().toString());
|
|
||||||
|
|
||||||
post.setRequestHeader("Content-Type",
|
|
||||||
"application/x-www-form-urlencoded; charset=utf-8"); // necessary for special characters
|
|
||||||
|
|
||||||
post.addParameter(PARAM_PATH, mRemoteFilePath);
|
|
||||||
post.addParameter(PARAM_SHARE_TYPE, Integer.toString(mShareType.getValue()));
|
|
||||||
post.addParameter(PARAM_SHARE_WITH, mShareWith);
|
|
||||||
|
|
||||||
if (mName.length() > 0) {
|
if (mName.length() > 0) {
|
||||||
post.addParameter(PARAM_NAME, mName);
|
formBodyBuilder.add(PARAM_NAME, mName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExpirationDateInMillis > 0) {
|
if (mExpirationDateInMillis > 0) {
|
||||||
@ -219,25 +209,33 @@ public class CreateRemoteShareOperation extends RemoteOperation {
|
|||||||
Calendar expirationDate = Calendar.getInstance();
|
Calendar expirationDate = Calendar.getInstance();
|
||||||
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
||||||
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
||||||
post.addParameter(PARAM_EXPIRATION_DATE, formattedExpirationDate);
|
formBodyBuilder.add(PARAM_EXPIRATION_DATE, formattedExpirationDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPublicUpload) {
|
if (mPublicUpload) {
|
||||||
post.addParameter(PARAM_PUBLIC_UPLOAD, Boolean.toString(true));
|
formBodyBuilder.add(PARAM_PUBLIC_UPLOAD, Boolean.toString(true));
|
||||||
}
|
}
|
||||||
if (mPassword != null && mPassword.length() > 0) {
|
if (mPassword != null && mPassword.length() > 0) {
|
||||||
post.addParameter(PARAM_PASSWORD, mPassword);
|
formBodyBuilder.add(PARAM_PASSWORD, mPassword);
|
||||||
}
|
}
|
||||||
if (OCShare.DEFAULT_PERMISSION != mPermissions) {
|
if (OCShare.DEFAULT_PERMISSION != mPermissions) {
|
||||||
post.addParameter(PARAM_PERMISSIONS, Integer.toString(mPermissions));
|
formBodyBuilder.add(PARAM_PERMISSIONS, Integer.toString(mPermissions));
|
||||||
}
|
}
|
||||||
|
|
||||||
post.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
Uri requestUri = client.getBaseUri();
|
||||||
|
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||||
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
|
|
||||||
status = client.executeMethod(post);
|
PostMethod postMethod = new PostMethod(new URL(uriBuilder.build().toString()));
|
||||||
|
|
||||||
|
postMethod.setRequestBody(formBodyBuilder.build());
|
||||||
|
|
||||||
|
postMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8);
|
||||||
|
postMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(postMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = post.getResponseBodyAsString();
|
|
||||||
|
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
new ShareXMLParser()
|
new ShareXMLParser()
|
||||||
@ -245,11 +243,13 @@ public class CreateRemoteShareOperation extends RemoteOperation {
|
|||||||
parser.setOneOrMoreSharesRequired(true);
|
parser.setOneOrMoreSharesRequired(true);
|
||||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||||
parser.setServerBaseUri(client.getBaseUri());
|
parser.setServerBaseUri(client.getBaseUri());
|
||||||
result = parser.parse(response);
|
result = parser.parse(postMethod.getResponseBodyAsString());
|
||||||
|
|
||||||
if (result.isSuccess() && mGetShareDetails) {
|
if (result.isSuccess() && mGetShareDetails) {
|
||||||
|
|
||||||
|
// TODO Use executeHttpMethod
|
||||||
// retrieve more info - POST only returns the index of the new share
|
// retrieve more info - POST only returns the index of the new share
|
||||||
OCShare emptyShare = (OCShare) result.getData().get(0);
|
OCShare emptyShare = result.getData().getShares().get(0);
|
||||||
GetRemoteShareOperation getInfo = new GetRemoteShareOperation(
|
GetRemoteShareOperation getInfo = new GetRemoteShareOperation(
|
||||||
emptyShare.getRemoteId()
|
emptyShare.getRemoteId()
|
||||||
);
|
);
|
||||||
@ -257,23 +257,17 @@ public class CreateRemoteShareOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, post);
|
result = new RemoteOperationResult<>(postMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while Creating New Share", e);
|
Log_OC.e(TAG, "Exception while Creating New Share", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (post != null) {
|
|
||||||
post.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -2,23 +2,23 @@
|
|||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -29,18 +29,22 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the data about a Share resource, known its remote ID.
|
* Get the data about a Share resource, known its remote ID.
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GetRemoteShareOperation extends RemoteOperation {
|
public class GetRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -51,58 +55,45 @@ public class GetRemoteShareOperation extends RemoteOperation {
|
|||||||
mRemoteId = remoteId;
|
mRemoteId = remoteId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<ShareParserResult> result;
|
||||||
int status = -1;
|
|
||||||
|
|
||||||
// Get Method
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
// Get the response
|
|
||||||
try {
|
try {
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
||||||
|
|
||||||
get = new GetMethod(uriBuilder.build().toString());
|
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
|
|
||||||
status = client.executeMethod(get);
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
|
|
||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
new ShareXMLParser()
|
new ShareXMLParser()
|
||||||
);
|
);
|
||||||
parser.setOneOrMoreSharesRequired(true);
|
parser.setOneOrMoreSharesRequired(true);
|
||||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||||
parser.setServerBaseUri(client.getBaseUri());
|
parser.setServerBaseUri(client.getBaseUri());
|
||||||
result = parser.parse(response);
|
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -31,17 +31,20 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by masensio on 08/10/2015.
|
* Created by masensio on 08/10/2015.
|
||||||
*
|
*
|
||||||
@ -62,8 +65,12 @@ import java.util.ArrayList;
|
|||||||
*
|
*
|
||||||
* Status codes:
|
* Status codes:
|
||||||
* 100 - successful
|
* 100 - successful
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class GetRemoteShareesOperation extends RemoteOperation{
|
public class GetRemoteShareesOperation extends RemoteOperation<ArrayList<JSONObject>> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteShareesOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteShareesOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -81,7 +88,6 @@ public class GetRemoteShareesOperation extends RemoteOperation{
|
|||||||
private static final String VALUE_FORMAT = "json";
|
private static final String VALUE_FORMAT = "json";
|
||||||
private static final String VALUE_ITEM_TYPE = "file"; // to get the server search for users / groups
|
private static final String VALUE_ITEM_TYPE = "file"; // to get the server search for users / groups
|
||||||
|
|
||||||
|
|
||||||
// JSON Node names
|
// JSON Node names
|
||||||
private static final String NODE_OCS = "ocs";
|
private static final String NODE_OCS = "ocs";
|
||||||
private static final String NODE_DATA = "data";
|
private static final String NODE_DATA = "data";
|
||||||
@ -112,29 +118,27 @@ public class GetRemoteShareesOperation extends RemoteOperation{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ArrayList<JSONObject>> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult<ArrayList<JSONObject>> result;
|
||||||
int status;
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
Uri.Builder uriBuilder = requestUri.buildUpon()
|
||||||
uriBuilder.appendEncodedPath(OCS_ROUTE);
|
.appendEncodedPath(OCS_ROUTE)
|
||||||
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT);
|
.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT)
|
||||||
uriBuilder.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE);
|
.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE)
|
||||||
uriBuilder.appendQueryParameter(PARAM_SEARCH, mSearchString);
|
.appendQueryParameter(PARAM_SEARCH, mSearchString)
|
||||||
uriBuilder.appendQueryParameter(PARAM_PAGE, String.valueOf(mPage));
|
.appendQueryParameter(PARAM_PAGE, String.valueOf(mPage))
|
||||||
uriBuilder.appendQueryParameter(PARAM_PER_PAGE, String.valueOf(mPerPage));
|
.appendQueryParameter(PARAM_PER_PAGE, String.valueOf(mPerPage));
|
||||||
|
|
||||||
// Get Method
|
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||||
get = new GetMethod(uriBuilder.build().toString());
|
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
|
|
||||||
status = client.executeMethod(get);
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
String response = getMethod.getResponseBodyAsString();
|
||||||
|
|
||||||
if(isSuccess(status)) {
|
if(isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log_OC.d(TAG, "Successful response: " + response);
|
Log_OC.d(TAG, "Successful response: " + response);
|
||||||
|
|
||||||
// Parse the response
|
// Parse the response
|
||||||
@ -157,7 +161,7 @@ public class GetRemoteShareesOperation extends RemoteOperation{
|
|||||||
respPartialRemotes
|
respPartialRemotes
|
||||||
};
|
};
|
||||||
|
|
||||||
ArrayList<Object> data = new ArrayList<Object>(); // For result data
|
ArrayList<JSONObject> data = new ArrayList<>(); // For result data
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i<6; i++) {
|
||||||
for(int j=0; j< jsonResults[i].length(); j++){
|
for(int j=0; j< jsonResults[i].length(); j++){
|
||||||
JSONObject jsonResult = jsonResults[i].getJSONObject(j);
|
JSONObject jsonResult = jsonResults[i].getJSONObject(j);
|
||||||
@ -166,15 +170,13 @@ public class GetRemoteShareesOperation extends RemoteOperation{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result
|
result = new RemoteOperationResult<>(OK);
|
||||||
result = new RemoteOperationResult(true, get);
|
|
||||||
result.setData(data);
|
result.setData(data);
|
||||||
|
|
||||||
Log_OC.d(TAG, "*** Get Users or groups completed " );
|
Log_OC.d(TAG, "*** Get Users or groups completed " );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log_OC.e(TAG, "Failed response while getting users/groups from the server ");
|
Log_OC.e(TAG, "Failed response while getting users/groups from the server ");
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
||||||
@ -182,20 +184,15 @@ public class GetRemoteShareesOperation extends RemoteOperation{
|
|||||||
Log_OC.e(TAG, "*** status code: " + status);
|
Log_OC.e(TAG, "*** status code: " + status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting users/groups", e);
|
Log_OC.e(TAG, "Exception while getting users/groups", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,23 +3,23 @@
|
|||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -30,20 +30,24 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.commons.httpclient.NameValuePair;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a list shares for a specific file.
|
* Provide a list shares for a specific file.
|
||||||
* The input is the full path of the desired file.
|
* The input is the full path of the desired file.
|
||||||
* The output is a list of everyone who has the file shared with them.
|
* The output is a list of everyone who has the file shared with them.
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class GetRemoteSharesForFileOperation extends RemoteOperation {
|
public class GetRemoteSharesForFileOperation extends RemoteOperation<ShareParserResult> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteSharesForFileOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteSharesForFileOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -73,63 +77,48 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult<ShareParserResult> result;
|
||||||
int status;
|
|
||||||
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
|
uriBuilder.appendQueryParameter(PARAM_PATH, mRemoteFilePath);
|
||||||
|
uriBuilder.appendQueryParameter(PARAM_RESHARES, String.valueOf(mReshares));
|
||||||
|
uriBuilder.appendQueryParameter(PARAM_SUBFILES, String.valueOf(mSubfiles));
|
||||||
|
|
||||||
// Get Method
|
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||||
get = new GetMethod(uriBuilder.build().toString());
|
|
||||||
|
|
||||||
// Add Parameters to Get Method
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
get.setQueryString(new NameValuePair[]{
|
|
||||||
new NameValuePair(PARAM_PATH, mRemoteFilePath),
|
|
||||||
new NameValuePair(PARAM_RESHARES, String.valueOf(mReshares)),
|
|
||||||
new NameValuePair(PARAM_SUBFILES, String.valueOf(mSubfiles))
|
|
||||||
});
|
|
||||||
|
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
|
||||||
status = client.executeMethod(get);
|
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
|
|
||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
new ShareXMLParser()
|
new ShareXMLParser()
|
||||||
);
|
);
|
||||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||||
parser.setServerBaseUri(client.getBaseUri());
|
parser.setServerBaseUri(client.getBaseUri());
|
||||||
result = parser.parse(response);
|
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
Log_OC.d(TAG, "Got " + result.getData().size() + " shares");
|
Log_OC.d(TAG, "Got " + result.getData().getShares().size() + " shares");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting shares", e);
|
Log_OC.e(TAG, "Exception while getting shares", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,24 +1,23 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author masensio
|
*
|
||||||
* @author David A. Velasco
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
*
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -29,45 +28,44 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the data from the server about ALL the known shares owned by the requester.
|
* Get the data from the server about ALL the known shares owned by the requester.
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GetRemoteSharesOperation extends RemoteOperation {
|
public class GetRemoteSharesOperation extends RemoteOperation {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteSharesOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteSharesOperation.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
public GetRemoteSharesOperation() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult result;
|
||||||
int status = -1;
|
|
||||||
|
|
||||||
// Get Method
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
// Get the response
|
|
||||||
try {
|
try {
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
|
|
||||||
get = new GetMethod(uriBuilder.build().toString());
|
GetMethod getMethod = new GetMethod(
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
new URL(client.getBaseUri() + ShareUtils.SHARING_API_PATH)
|
||||||
status = client.executeMethod(get);
|
);
|
||||||
|
|
||||||
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
|
|
||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
@ -75,26 +73,19 @@ public class GetRemoteSharesOperation extends RemoteOperation {
|
|||||||
);
|
);
|
||||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||||
parser.setServerBaseUri(client.getBaseUri());
|
parser.setServerBaseUri(client.getBaseUri());
|
||||||
result = parser.parse(response);
|
result = parser.parse(getMethod.getResponseBodyAsString());
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
Log_OC.e(TAG, "Exception while getting remote shares ", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
@ -3,23 +3,23 @@
|
|||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -30,15 +30,20 @@ package com.owncloud.android.lib.resources.shares;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.DeleteMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a share
|
* Remove a share
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RemoveRemoteShareOperation extends RemoteOperation {
|
public class RemoveRemoteShareOperation extends RemoteOperation {
|
||||||
@ -55,15 +60,11 @@ public class RemoveRemoteShareOperation extends RemoteOperation {
|
|||||||
|
|
||||||
public RemoveRemoteShareOperation(int remoteShareId) {
|
public RemoveRemoteShareOperation(int remoteShareId) {
|
||||||
mRemoteShareId = remoteShareId;
|
mRemoteShareId = remoteShareId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult result;
|
||||||
int status;
|
|
||||||
|
|
||||||
DeleteMethod delete = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
@ -71,39 +72,37 @@ public class RemoveRemoteShareOperation extends RemoteOperation {
|
|||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
uriBuilder.appendEncodedPath(String.valueOf(mRemoteShareId));
|
uriBuilder.appendEncodedPath(String.valueOf(mRemoteShareId));
|
||||||
|
|
||||||
delete = new DeleteMethod(uriBuilder.build().toString());
|
DeleteMethod deleteMethod = new DeleteMethod(
|
||||||
|
new URL(uriBuilder.build().toString())
|
||||||
|
);
|
||||||
|
|
||||||
delete.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
deleteMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
status = client.executeMethod(delete);
|
int status = client.executeHttpMethod(deleteMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = delete.getResponseBodyAsString();
|
|
||||||
|
|
||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
new ShareXMLParser()
|
new ShareXMLParser()
|
||||||
);
|
);
|
||||||
result = parser.parse(response);
|
result = parser.parse(deleteMethod.getResponseBodyAsString());
|
||||||
|
|
||||||
Log_OC.d(TAG, "Unshare " + mRemoteShareId + ": " + result.getLogMessage());
|
Log_OC.d(TAG, "Unshare " + mRemoteShareId + ": " + result.getLogMessage());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, delete);
|
result = new RemoteOperationResult<>(deleteMethod);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
result = new RemoteOperationResult(e);
|
|
||||||
Log_OC.e(TAG, "Unshare Link Exception " + result.getLogMessage(), e);
|
|
||||||
|
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
if (delete != null)
|
result = new RemoteOperationResult<>(e);
|
||||||
delete.releaseConnection();
|
Log_OC.e(TAG, "Unshare Link Exception " + result.getLogMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/* ownCloud Android Library is available under MIT license
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
* Copyright (C) 2018 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.resources.shares;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ShareParserResult {
|
||||||
|
private ArrayList<OCShare> shares;
|
||||||
|
private String parserMessage;
|
||||||
|
|
||||||
|
public ShareParserResult(ArrayList<OCShare> shares, String parserMessage) {
|
||||||
|
this.shares = shares;
|
||||||
|
this.parserMessage = parserMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<OCShare> getShares() {
|
||||||
|
return shares;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParserMessage() {
|
||||||
|
return parserMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
|
* @author Christian Schabesberger
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -66,13 +67,13 @@ public class ShareToRemoteOperationResultParser {
|
|||||||
mServerBaseUri = serverBaseURi;
|
mServerBaseUri = serverBaseURi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteOperationResult parse(String serverResponse) {
|
public RemoteOperationResult<ShareParserResult> parse(String serverResponse) {
|
||||||
if (serverResponse == null || serverResponse.length() == 0) {
|
if (serverResponse == null || serverResponse.length() == 0) {
|
||||||
return new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
return new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteOperationResult result;
|
RemoteOperationResult<ShareParserResult> result;
|
||||||
ArrayList<Object> resultData = new ArrayList<Object>();
|
final ArrayList<OCShare> resultData = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Parse xml response and obtain the list of shares
|
// Parse xml response and obtain the list of shares
|
||||||
@ -85,17 +86,16 @@ public class ShareToRemoteOperationResultParser {
|
|||||||
|
|
||||||
if (mShareXmlParser.isSuccess()) {
|
if (mShareXmlParser.isSuccess()) {
|
||||||
if ((shares != null && shares.size() > 0) || !mOneOrMoreSharesRequired) {
|
if ((shares != null && shares.size() > 0) || !mOneOrMoreSharesRequired) {
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK);
|
||||||
if (shares != null) {
|
if (shares != null) {
|
||||||
for (OCShare share : shares) {
|
for (OCShare share : shares) {
|
||||||
resultData.add(share);
|
resultData.add(share);
|
||||||
// build the share link if not in the response
|
// build the share link if not in the response
|
||||||
// (needed for OC servers < 9.0.0, see ShareXMLParser.java#line256)
|
// (needed for OC servers < 9.0.0, see ShareXMLParser.java#line256)
|
||||||
if (share.getShareType() == ShareType.PUBLIC_LINK &&
|
if (share.getShareType() == ShareType.PUBLIC_LINK
|
||||||
(share.getShareLink() == null ||
|
&& (share.getShareLink() == null
|
||||||
share.getShareLink().length() <= 0) &&
|
|| share.getShareLink().length() <= 0)
|
||||||
share.getToken().length() > 0
|
&& share.getToken().length() > 0) {
|
||||||
) {
|
|
||||||
if (mServerBaseUri != null) {
|
if (mServerBaseUri != null) {
|
||||||
String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion);
|
String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion);
|
||||||
share.setShareLink(mServerBaseUri + sharingLinkPath + share.getToken());
|
share.setShareLink(mServerBaseUri + sharingLinkPath + share.getToken());
|
||||||
@ -105,43 +105,38 @@ public class ShareToRemoteOperationResultParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.setData(resultData);
|
result.setData(new ShareParserResult(resultData, ""));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||||
Log_OC.e(TAG, "Successful status with no share in the response");
|
Log_OC.e(TAG, "Successful status with no share in the response");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (mShareXmlParser.isWrongParameter()){
|
} else if (mShareXmlParser.isWrongParameter()){
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER);
|
||||||
resultData.add(mShareXmlParser.getMessage());
|
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||||
result.setData(resultData);
|
|
||||||
|
|
||||||
} else if (mShareXmlParser.isNotFound()){
|
} else if (mShareXmlParser.isNotFound()){
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND);
|
||||||
resultData.add(mShareXmlParser.getMessage());
|
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||||
result.setData(resultData);
|
|
||||||
|
|
||||||
} else if (mShareXmlParser.isForbidden()) {
|
} else if (mShareXmlParser.isForbidden()) {
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_FORBIDDEN);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.SHARE_FORBIDDEN);
|
||||||
resultData.add(mShareXmlParser.getMessage());
|
result.setData(new ShareParserResult(null, mShareXmlParser.getMessage()));
|
||||||
result.setData(resultData);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
Log_OC.e(TAG, "Error parsing response from server ", e);
|
Log_OC.e(TAG, "Error parsing response from server ", e);
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log_OC.e(TAG, "Error reading response from server ", e);
|
Log_OC.e(TAG, "Error reading response from server ", e);
|
||||||
result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* @author David A. Velasco
|
*
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,32 +26,32 @@
|
|||||||
package com.owncloud.android.lib.resources.shares;
|
package com.owncloud.android.lib.resources.shares;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.PutMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.commons.httpclient.methods.PutMethod;
|
|
||||||
import org.apache.commons.httpclient.methods.StringRequestEntity;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates parameters of an existing Share resource, known its remote ID.
|
* Updates parameters of an existing Share resource, known its remote ID.
|
||||||
* <p/>
|
*
|
||||||
* Allow updating several parameters, triggering a request to the server per parameter.
|
* Allow updating several parameters, triggering a request to the server per parameter.
|
||||||
|
*
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class UpdateRemoteShareOperation extends RemoteOperation {
|
public class UpdateRemoteShareOperation extends RemoteOperation<ShareParserResult> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteShareOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -163,104 +163,77 @@ public class UpdateRemoteShareOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ShareParserResult> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<ShareParserResult> result;
|
||||||
int status;
|
|
||||||
|
|
||||||
/// prepare array of parameters to update
|
|
||||||
List<Pair<String, String>> parametersToUpdate = new ArrayList<>();
|
|
||||||
if (mName != null) {
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_NAME, mName));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPassword != null) {
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_PASSWORD, mPassword));
|
|
||||||
}
|
|
||||||
if (mExpirationDateInMillis < 0) {
|
|
||||||
// clear expiration date
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_EXPIRATION_DATE, ""));
|
|
||||||
|
|
||||||
} else if (mExpirationDateInMillis > 0) {
|
|
||||||
// set expiration date
|
|
||||||
DateFormat dateFormat = new SimpleDateFormat(FORMAT_EXPIRATION_DATE, Locale.GERMAN);
|
|
||||||
Calendar expirationDate = Calendar.getInstance();
|
|
||||||
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
|
||||||
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_EXPIRATION_DATE, formattedExpirationDate));
|
|
||||||
|
|
||||||
} // else, ignore - no update
|
|
||||||
|
|
||||||
if (mPublicUpload != null) {
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_PUBLIC_UPLOAD, Boolean.toString(mPublicUpload)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPORTANT: permissions parameter needs to be updated after mPublicUpload parameter,
|
|
||||||
// otherwise they would be set always as 1 (READ) in the server when mPublicUpload was updated
|
|
||||||
if (mPermissions > 0) {
|
|
||||||
// set permissions
|
|
||||||
parametersToUpdate.add(new Pair<>(PARAM_PERMISSIONS, Integer.toString(mPermissions)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// perform required PUT requests
|
|
||||||
PutMethod put = null;
|
|
||||||
String uriString;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
FormBody.Builder formBodyBuilder = new FormBody.Builder();
|
||||||
|
|
||||||
|
// Parameters to update
|
||||||
|
if (mName != null) {
|
||||||
|
formBodyBuilder.add(PARAM_NAME, mName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mExpirationDateInMillis < 0) {
|
||||||
|
// clear expiration date
|
||||||
|
formBodyBuilder.add(PARAM_EXPIRATION_DATE, "");
|
||||||
|
|
||||||
|
} else if (mExpirationDateInMillis > 0) {
|
||||||
|
// set expiration date
|
||||||
|
DateFormat dateFormat = new SimpleDateFormat(FORMAT_EXPIRATION_DATE, Locale.GERMAN);
|
||||||
|
Calendar expirationDate = Calendar.getInstance();
|
||||||
|
expirationDate.setTimeInMillis(mExpirationDateInMillis);
|
||||||
|
String formattedExpirationDate = dateFormat.format(expirationDate.getTime());
|
||||||
|
formBodyBuilder.add(PARAM_EXPIRATION_DATE, formattedExpirationDate);
|
||||||
|
} // else, ignore - no update
|
||||||
|
|
||||||
|
if (mPublicUpload != null) {
|
||||||
|
formBodyBuilder.add(PARAM_PUBLIC_UPLOAD, Boolean.toString(mPublicUpload));
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMPORTANT: permissions parameter needs to be updated after mPublicUpload parameter,
|
||||||
|
// otherwise they would be set always as 1 (READ) in the server when mPublicUpload was updated
|
||||||
|
if (mPermissions > 0) {
|
||||||
|
// set permissions
|
||||||
|
formBodyBuilder.add(PARAM_PERMISSIONS, Integer.toString(mPermissions));
|
||||||
|
}
|
||||||
|
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
Uri.Builder uriBuilder = requestUri.buildUpon();
|
Uri.Builder uriBuilder = requestUri.buildUpon();
|
||||||
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
uriBuilder.appendEncodedPath(ShareUtils.SHARING_API_PATH);
|
||||||
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
uriBuilder.appendEncodedPath(Long.toString(mRemoteId));
|
||||||
uriString = uriBuilder.build().toString();
|
|
||||||
|
|
||||||
for (Pair<String, String> parameter : parametersToUpdate) {
|
PutMethod putMethod = new PutMethod(new URL(uriBuilder.build().toString()));
|
||||||
if (put != null) {
|
|
||||||
put.releaseConnection();
|
|
||||||
}
|
|
||||||
put = new PutMethod(uriString);
|
|
||||||
put.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
put.setRequestEntity(new StringRequestEntity(
|
|
||||||
parameter.first + "=" + parameter.second,
|
|
||||||
ENTITY_CONTENT_TYPE,
|
|
||||||
ENTITY_CHARSET
|
|
||||||
));
|
|
||||||
|
|
||||||
status = client.executeMethod(put);
|
putMethod.setRequestBody(formBodyBuilder.build());
|
||||||
|
|
||||||
if (status == HttpStatus.SC_OK) {
|
putMethod.setRequestHeader(HttpConstants.CONTENT_TYPE_HEADER, HttpConstants.CONTENT_TYPE_URLENCODED_UTF8);
|
||||||
String response = put.getResponseBodyAsString();
|
putMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
// Parse xml response
|
int status = client.executeHttpMethod(putMethod);
|
||||||
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
|
||||||
new ShareXMLParser()
|
|
||||||
);
|
|
||||||
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
|
||||||
parser.setServerBaseUri(client.getBaseUri());
|
|
||||||
result = parser.parse(response);
|
|
||||||
|
|
||||||
} else {
|
if (isSuccess(status)) {
|
||||||
result = new RemoteOperationResult(false, put);
|
// Parse xml response
|
||||||
}
|
ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser(
|
||||||
if (!result.isSuccess() &&
|
new ShareXMLParser()
|
||||||
!PARAM_NAME.equals(parameter.first)
|
);
|
||||||
// fail in "name" parameter will be ignored; requires OCX, will fail
|
parser.setOwnCloudVersion(client.getOwnCloudVersion());
|
||||||
// fails in previous versions
|
parser.setServerBaseUri(client.getBaseUri());
|
||||||
) {
|
result = parser.parse(putMethod.getResponseBodyAsString());
|
||||||
break;
|
|
||||||
}
|
} else {
|
||||||
|
result = new RemoteOperationResult<>(putMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while updating remote share ", e);
|
Log_OC.e(TAG, "Exception while Creating New Share", e);
|
||||||
if (put != null) {
|
|
||||||
put.releaseConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (put != null) {
|
|
||||||
put.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private boolean isSuccess(int status) {
|
||||||
|
return (status == HttpConstants.HTTP_OK);
|
||||||
|
}
|
||||||
|
}
|
@ -24,31 +24,35 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package com.owncloud.android.lib.resources.status;
|
package com.owncloud.android.lib.resources.status;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Capabilities from the server
|
* Get the Capabilities from the server
|
||||||
*
|
|
||||||
* Save in Result.getData in a OCCapability object
|
* Save in Result.getData in a OCCapability object
|
||||||
|
*
|
||||||
|
* @author masensio
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
public class GetRemoteCapabilitiesOperation extends RemoteOperation<OCCapability> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteCapabilitiesOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteCapabilitiesOperation.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
// OCS Routes
|
// OCS Routes
|
||||||
private static final String OCS_ROUTE = "ocs/v2.php/cloud/capabilities";
|
private static final String OCS_ROUTE = "ocs/v2.php/cloud/capabilities";
|
||||||
|
|
||||||
@ -115,10 +119,8 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<OCCapability> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<OCCapability> result;
|
||||||
int status;
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Uri requestUri = client.getBaseUri();
|
Uri requestUri = client.getBaseUri();
|
||||||
@ -126,14 +128,14 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
|||||||
uriBuilder.appendEncodedPath(OCS_ROUTE); // avoid starting "/" in this method
|
uriBuilder.appendEncodedPath(OCS_ROUTE); // avoid starting "/" in this method
|
||||||
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT);
|
uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT);
|
||||||
|
|
||||||
// Get Method
|
GetMethod getMethod = new GetMethod(new URL(uriBuilder.build().toString()));
|
||||||
get = new GetMethod(uriBuilder.build().toString());
|
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
|
|
||||||
status = client.executeMethod(get);
|
getMethod.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
||||||
|
|
||||||
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
|
||||||
|
String response = getMethod.getResponseBodyAsString();
|
||||||
if(isSuccess(status)) {
|
if(isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log_OC.d(TAG, "Successful response: " + response);
|
Log_OC.d(TAG, "Successful response: " + response);
|
||||||
|
|
||||||
// Parse the response
|
// Parse the response
|
||||||
@ -148,7 +150,6 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
|||||||
String message = respMeta.getString(PROPERTY_MESSAGE);
|
String message = respMeta.getString(PROPERTY_MESSAGE);
|
||||||
|
|
||||||
if (statusProp) {
|
if (statusProp) {
|
||||||
ArrayList<Object> data = new ArrayList<Object>(); // For result data
|
|
||||||
OCCapability capability = new OCCapability();
|
OCCapability capability = new OCCapability();
|
||||||
// Add Version
|
// Add Version
|
||||||
if (respData.has(NODE_VERSION)) {
|
if (respData.has(NODE_VERSION)) {
|
||||||
@ -254,20 +255,18 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Result
|
// Result
|
||||||
data.add(capability);
|
result = new RemoteOperationResult<>(OK);
|
||||||
result = new RemoteOperationResult(true, get);
|
result.setData(capability);
|
||||||
result.setData(data);
|
|
||||||
|
|
||||||
Log_OC.d(TAG, "*** Get Capabilities completed ");
|
Log_OC.d(TAG, "*** Get Capabilities completed ");
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(statusProp, statuscode, null, null);
|
result = new RemoteOperationResult<>(statuscode, message, null);
|
||||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
||||||
Log_OC.e(TAG, "*** status: " + statusProp + "; message: " + message);
|
Log_OC.e(TAG, "*** status: " + statusProp + "; message: " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
Log_OC.e(TAG, "Failed response while getting capabilities from the server ");
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response);
|
||||||
@ -277,18 +276,13 @@ public class GetRemoteCapabilitiesOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting capabilities", e);
|
Log_OC.e(TAG, "Exception while getting capabilities", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,40 +24,41 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.status;
|
package com.owncloud.android.lib.resources.status;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.apache.commons.httpclient.params.HttpMethodParams;
|
|
||||||
import org.apache.commons.httpclient.params.HttpParams;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
import com.owncloud.android.lib.common.accounts.AccountUtils;
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the server is valid and if the server supports the Share API
|
* Checks if the server is valid and if the server supports the Share API
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
* @author masensio
|
* @author masensio
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GetRemoteStatusOperation extends RemoteOperation {
|
public class GetRemoteStatusOperation extends RemoteOperation<OwnCloudVersion> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum time to wait for a response from the server when the connection is being tested,
|
* Maximum time to wait for a response from the server when the connection is being tested,
|
||||||
* in MILLISECONDs.
|
* in MILLISECONDs.
|
||||||
*/
|
*/
|
||||||
public static final int TRY_CONNECTION_TIMEOUT = 5000;
|
public static final long TRY_CONNECTION_TIMEOUT = 5000;
|
||||||
|
|
||||||
private static final String TAG = GetRemoteStatusOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteStatusOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ public class GetRemoteStatusOperation extends RemoteOperation {
|
|||||||
private static final String HTTPS_PREFIX = "https://";
|
private static final String HTTPS_PREFIX = "https://";
|
||||||
private static final String HTTP_PREFIX = "http://";
|
private static final String HTTP_PREFIX = "http://";
|
||||||
|
|
||||||
private RemoteOperationResult mLatestResult;
|
private RemoteOperationResult<OwnCloudVersion> mLatestResult;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
public GetRemoteStatusOperation(Context context) {
|
public GetRemoteStatusOperation(Context context) {
|
||||||
@ -75,20 +76,25 @@ public class GetRemoteStatusOperation extends RemoteOperation {
|
|||||||
|
|
||||||
private boolean tryConnection(OwnCloudClient client) {
|
private boolean tryConnection(OwnCloudClient client) {
|
||||||
boolean retval = false;
|
boolean retval = false;
|
||||||
GetMethod get = null;
|
|
||||||
String baseUrlSt = client.getBaseUri().toString();
|
String baseUrlSt = client.getBaseUri().toString();
|
||||||
try {
|
try {
|
||||||
get = new GetMethod(baseUrlSt + OwnCloudClient.STATUS_PATH);
|
GetMethod getMethod = new GetMethod(new URL(baseUrlSt + OwnCloudClient.STATUS_PATH));
|
||||||
|
|
||||||
HttpParams params = get.getParams().getDefaultParams();
|
getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
params.setParameter(HttpMethodParams.USER_AGENT,
|
getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
OwnCloudClientManagerFactory.getUserAgent());
|
|
||||||
get.getParams().setDefaults(params);
|
|
||||||
|
|
||||||
client.setFollowRedirects(false);
|
client.setFollowRedirects(false);
|
||||||
boolean isRedirectToNonSecureConnection = false;
|
boolean isRedirectToNonSecureConnection = false;
|
||||||
int status = client.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
|
int status;
|
||||||
mLatestResult = new RemoteOperationResult((status == HttpStatus.SC_OK), get);
|
try {
|
||||||
|
status = client.executeHttpMethod(getMethod);
|
||||||
|
mLatestResult = isSuccess(status)
|
||||||
|
? new RemoteOperationResult<>(OK)
|
||||||
|
: new RemoteOperationResult<>(getMethod);
|
||||||
|
} catch (SSLException sslE) {
|
||||||
|
mLatestResult = new RemoteOperationResult(sslE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
String redirectedLocation = mLatestResult.getRedirectedLocation();
|
String redirectedLocation = mLatestResult.getRedirectedLocation();
|
||||||
while (redirectedLocation != null && redirectedLocation.length() > 0
|
while (redirectedLocation != null && redirectedLocation.length() > 0
|
||||||
@ -98,61 +104,53 @@ public class GetRemoteStatusOperation extends RemoteOperation {
|
|||||||
baseUrlSt.startsWith(HTTPS_PREFIX) &&
|
baseUrlSt.startsWith(HTTPS_PREFIX) &&
|
||||||
redirectedLocation.startsWith(HTTP_PREFIX)
|
redirectedLocation.startsWith(HTTP_PREFIX)
|
||||||
);
|
);
|
||||||
get.releaseConnection();
|
|
||||||
get = new GetMethod(redirectedLocation);
|
getMethod = new GetMethod(new URL(redirectedLocation));
|
||||||
status = client.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
|
getMethod.setReadTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
mLatestResult = new RemoteOperationResult(
|
getMethod.setConnectionTimeout(TRY_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
|
||||||
(status == HttpStatus.SC_OK),
|
|
||||||
get
|
status = client.executeHttpMethod(getMethod);
|
||||||
);
|
mLatestResult = new RemoteOperationResult<>(getMethod);
|
||||||
redirectedLocation = mLatestResult.getRedirectedLocation();
|
redirectedLocation = mLatestResult.getRedirectedLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
String response = get.getResponseBodyAsString();
|
if (isSuccess(status)) {
|
||||||
if (status == HttpStatus.SC_OK) {
|
|
||||||
JSONObject json = new JSONObject(response);
|
JSONObject respJSON = new JSONObject(getMethod.getResponseBodyAsString());
|
||||||
if (!json.getBoolean(NODE_INSTALLED)) {
|
if (!respJSON.getBoolean(NODE_INSTALLED)) {
|
||||||
mLatestResult = new RemoteOperationResult(
|
mLatestResult = new RemoteOperationResult(
|
||||||
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
||||||
} else {
|
} else {
|
||||||
String version = json.getString(NODE_VERSION);
|
String version = respJSON.getString(NODE_VERSION);
|
||||||
OwnCloudVersion ocVersion = new OwnCloudVersion(version);
|
OwnCloudVersion ocVersion = new OwnCloudVersion(version);
|
||||||
/// the version object will be returned even if the version is invalid, no error code;
|
/// the version object will be returned even if the version is invalid, no error code;
|
||||||
/// every app will decide how to act if (ocVersion.isVersionValid() == false)
|
/// every app will decide how to act if (ocVersion.isVersionValid() == false)
|
||||||
|
|
||||||
if (isRedirectToNonSecureConnection) {
|
if (isRedirectToNonSecureConnection) {
|
||||||
mLatestResult = new RemoteOperationResult(
|
mLatestResult = new RemoteOperationResult<>(
|
||||||
RemoteOperationResult.ResultCode.
|
RemoteOperationResult.ResultCode.
|
||||||
OK_REDIRECT_TO_NON_SECURE_CONNECTION
|
OK_REDIRECT_TO_NON_SECURE_CONNECTION);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
mLatestResult = new RemoteOperationResult(
|
mLatestResult = new RemoteOperationResult<>(
|
||||||
baseUrlSt.startsWith(HTTPS_PREFIX) ?
|
baseUrlSt.startsWith(HTTPS_PREFIX) ?
|
||||||
RemoteOperationResult.ResultCode.OK_SSL :
|
RemoteOperationResult.ResultCode.OK_SSL :
|
||||||
RemoteOperationResult.ResultCode.OK_NO_SSL
|
RemoteOperationResult.ResultCode.OK_NO_SSL);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Object> data = new ArrayList<Object>();
|
mLatestResult.setData(ocVersion);
|
||||||
data.add(ocVersion);
|
|
||||||
mLatestResult.setData(data);
|
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mLatestResult = new RemoteOperationResult(false, get);
|
mLatestResult = new RemoteOperationResult<>(getMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
mLatestResult = new RemoteOperationResult(
|
mLatestResult = new RemoteOperationResult<>(
|
||||||
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
mLatestResult = new RemoteOperationResult(e);
|
mLatestResult = new RemoteOperationResult<>(e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null)
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLatestResult.isSuccess()) {
|
if (mLatestResult.isSuccess()) {
|
||||||
@ -177,9 +175,9 @@ public class GetRemoteStatusOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<OwnCloudVersion> run(OwnCloudClient client) {
|
||||||
if (!isOnline()) {
|
if (!isOnline()) {
|
||||||
return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
|
return new RemoteOperationResult<>(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION);
|
||||||
}
|
}
|
||||||
String baseUriStr = client.getBaseUri().toString();
|
String baseUriStr = client.getBaseUri().toString();
|
||||||
if (baseUriStr.startsWith(HTTP_PREFIX) || baseUriStr.startsWith(HTTPS_PREFIX)) {
|
if (baseUriStr.startsWith(HTTP_PREFIX) || baseUriStr.startsWith(HTTPS_PREFIX)) {
|
||||||
@ -197,4 +195,7 @@ public class GetRemoteStatusOperation extends RemoteOperation {
|
|||||||
return mLatestResult;
|
return mLatestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private boolean isSuccess(int status) {
|
||||||
|
return (status == HttpConstants.HTTP_OK);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
*
|
*
|
||||||
* @author David A. Velasco
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -26,33 +25,32 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.users;
|
package com.owncloud.android.lib.resources.users;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.Header;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets avatar about the user logged in, if available
|
* Gets avatar about the user logged in, if available
|
||||||
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
public class GetRemoteUserAvatarOperation extends RemoteOperation<GetRemoteUserAvatarOperation.ResultData> {
|
||||||
public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|
||||||
|
|
||||||
private static final String TAG = GetRemoteUserAvatarOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteUserAvatarOperation.class.getSimpleName();
|
||||||
|
|
||||||
private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/";
|
private static final String NON_OFFICIAL_AVATAR_PATH = "/index.php/avatar/";
|
||||||
private static final String IF_NONE_MATCH_HEADER = "If-None-Match";
|
|
||||||
|
|
||||||
/** Desired size in pixels of the squared image */
|
/** Desired size in pixels of the squared image */
|
||||||
private int mDimension;
|
private int mDimension;
|
||||||
@ -63,67 +61,54 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|||||||
*/
|
*/
|
||||||
private String mCurrentEtag;
|
private String mCurrentEtag;
|
||||||
|
|
||||||
|
|
||||||
public GetRemoteUserAvatarOperation(int dimension, String currentEtag) {
|
public GetRemoteUserAvatarOperation(int dimension, String currentEtag) {
|
||||||
mDimension = dimension;
|
mDimension = dimension;
|
||||||
mCurrentEtag = currentEtag;
|
mCurrentEtag = currentEtag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<ResultData> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
GetMethod getMethod = null;
|
||||||
GetMethod get = null;
|
RemoteOperationResult<ResultData> result;
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
BufferedInputStream bis = null;
|
BufferedInputStream bis = null;
|
||||||
ByteArrayOutputStream bos = null;
|
ByteArrayOutputStream bos = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String uri =
|
final String url =
|
||||||
client.getBaseUri() + NON_OFFICIAL_AVATAR_PATH +
|
client.getBaseUri() + NON_OFFICIAL_AVATAR_PATH +
|
||||||
client.getCredentials().getUsername() + "/" + mDimension;
|
client.getCredentials().getUsername() + "/" + mDimension;
|
||||||
;
|
Log_OC.d(TAG, "avatar URI: " + url);
|
||||||
Log_OC.d(TAG, "avatar URI: " + uri);
|
|
||||||
get = new GetMethod(uri);
|
|
||||||
/* Conditioned call is corrupting the input stream of the connection.
|
|
||||||
Seems that response with 304 is also including the avatar in the response body,
|
|
||||||
though it's forbidden by HTTPS specification. Besides, HTTPClient library
|
|
||||||
assumes there is nothing in the response body, but the bytes are read
|
|
||||||
by the next request, resulting in an exception due to a corrupt status line
|
|
||||||
|
|
||||||
Maybe when we have a real API we can enable this again.
|
getMethod = new GetMethod(new URL(url));
|
||||||
|
|
||||||
if (mCurrentEtag != null && mCurrentEtag.length() > 0) {
|
int status = client.executeHttpMethod(getMethod);
|
||||||
get.addRequestHeader(IF_NONE_MATCH_HEADER, "\"" + mCurrentEtag + "\"");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
int status = client.executeMethod(get);
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
|
|
||||||
// find out size of file to read
|
// find out size of file to read
|
||||||
int totalToTransfer = 0;
|
int totalToTransfer = 0;
|
||||||
Header contentLength = get.getResponseHeader("Content-Length");
|
String contentLength = getMethod.getResponseHeader(HttpConstants.CONTENT_LENGTH_HEADER);
|
||||||
if (contentLength != null && contentLength.getValue().length() > 0) {
|
|
||||||
totalToTransfer = Integer.parseInt(contentLength.getValue());
|
if (contentLength != null && contentLength.length() > 0) {
|
||||||
|
totalToTransfer = Integer.parseInt(contentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find out MIME-type!
|
// find out MIME-type!
|
||||||
String mimeType;
|
String mimeType;
|
||||||
Header contentType = get.getResponseHeader("Content-Type");
|
String contentType = getMethod.getResponseHeader(HttpConstants.CONTENT_TYPE_HEADER);
|
||||||
if (contentType == null || !contentType.getValue().startsWith("image")) {
|
|
||||||
|
if (contentType == null || !contentType.startsWith("image")) {
|
||||||
Log_OC.e(
|
Log_OC.e(
|
||||||
TAG, "Not an image, failing with no avatar"
|
TAG, "Not an image, failing with no avatar"
|
||||||
);
|
);
|
||||||
result = new RemoteOperationResult(
|
result = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.FILE_NOT_FOUND);
|
||||||
RemoteOperationResult.ResultCode.FILE_NOT_FOUND
|
|
||||||
);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
mimeType = contentType.getValue();
|
|
||||||
|
mimeType = contentType;
|
||||||
|
|
||||||
/// download will be performed to a buffer
|
/// download will be performed to a buffer
|
||||||
inputStream = get.getResponseBodyAsStream();
|
inputStream = getMethod.getResponseBodyAsStream();
|
||||||
bis = new BufferedInputStream(inputStream);
|
bis = new BufferedInputStream(inputStream);
|
||||||
bos = new ByteArrayOutputStream(totalToTransfer);
|
bos = new ByteArrayOutputStream(totalToTransfer);
|
||||||
|
|
||||||
@ -137,29 +122,26 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|||||||
// TODO check total bytes transferred?
|
// TODO check total bytes transferred?
|
||||||
|
|
||||||
// find out etag
|
// find out etag
|
||||||
String etag = WebdavUtils.getEtagFromResponse(get);
|
String etag = WebdavUtils.getEtagFromResponse(getMethod);
|
||||||
if (etag.length() == 0) {
|
if (etag.length() == 0) {
|
||||||
Log_OC.w(TAG, "Could not read Etag from avatar");
|
Log_OC.w(TAG, "Could not read Etag from avatar");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
result = new RemoteOperationResult(true, get);
|
result = new RemoteOperationResult<>(OK);
|
||||||
ResultData resultData = new ResultData(bos.toByteArray(), mimeType, etag);
|
result.setData(new ResultData(bos.toByteArray(), mimeType, etag));
|
||||||
ArrayList<Object> data = new ArrayList<Object>();
|
|
||||||
data.add(resultData);
|
|
||||||
result.setData(data);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
client.exhaustResponse(get.getResponseBodyAsStream());
|
client.exhaustResponse(getMethod.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting OC user avatar", e);
|
Log_OC.e(TAG, "Exception while getting OC user avatar", e);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (get != null) {
|
if (getMethod != null) {
|
||||||
try {
|
try {
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
client.exhaustResponse(inputStream);
|
client.exhaustResponse(inputStream);
|
||||||
@ -179,7 +161,6 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|||||||
} catch (IOException o) {
|
} catch (IOException o) {
|
||||||
Log_OC.e(TAG, "Unexpected exception closing output stream ", o);
|
Log_OC.e(TAG, "Unexpected exception closing output stream ", o);
|
||||||
}
|
}
|
||||||
get.releaseConnection();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +168,7 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResultData {
|
public static class ResultData {
|
||||||
@ -213,5 +194,4 @@ public class GetRemoteUserAvatarOperation extends RemoteOperation {
|
|||||||
return mAvatarData;
|
return mAvatarData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2016 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,26 +24,28 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.resources.users;
|
package com.owncloud.android.lib.resources.users;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets information (id, display name, and e-mail address) about the user logged in.
|
* Gets information (id, display name, and e-mail address) about the user logged in.
|
||||||
*
|
*
|
||||||
* @author masensio
|
* @author masensio
|
||||||
* @author David A. Velasco
|
* @author David A. Velasco
|
||||||
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GetRemoteUserInfoOperation extends RemoteOperation {
|
public class GetRemoteUserInfoOperation extends RemoteOperation<GetRemoteUserInfoOperation.UserInfo> {
|
||||||
|
|
||||||
private static final String TAG = GetRemoteUserInfoOperation.class.getSimpleName();
|
private static final String TAG = GetRemoteUserInfoOperation.class.getSimpleName();
|
||||||
|
|
||||||
@ -61,22 +63,19 @@ public class GetRemoteUserInfoOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<UserInfo> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<UserInfo> result;
|
||||||
int status = -1;
|
|
||||||
GetMethod get = null;
|
|
||||||
|
|
||||||
//Get the user
|
//Get the user
|
||||||
try {
|
try {
|
||||||
get = new GetMethod(client.getBaseUri() + OCS_ROUTE);
|
GetMethod getMethod = new GetMethod(new URL(client.getBaseUri() + OCS_ROUTE));
|
||||||
get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE);
|
|
||||||
status = client.executeMethod(get);
|
int status = client.executeHttpMethod(getMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log_OC.d(TAG, "Successful response");
|
Log_OC.d(TAG, "Successful response");
|
||||||
|
|
||||||
// Parse the response
|
JSONObject respJSON = new JSONObject(getMethod.getResponseBodyAsString());
|
||||||
JSONObject respJSON = new JSONObject(response);
|
|
||||||
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
|
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
|
||||||
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
|
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
|
||||||
|
|
||||||
@ -85,41 +84,32 @@ public class GetRemoteUserInfoOperation extends RemoteOperation {
|
|||||||
userInfo.mDisplayName = respData.getString(NODE_DISPLAY_NAME);
|
userInfo.mDisplayName = respData.getString(NODE_DISPLAY_NAME);
|
||||||
userInfo.mEmail = respData.getString(NODE_EMAIL);
|
userInfo.mEmail = respData.getString(NODE_EMAIL);
|
||||||
|
|
||||||
// Result
|
result = new RemoteOperationResult<>(OK);
|
||||||
result = new RemoteOperationResult(true, get);
|
|
||||||
// Username in result.data
|
result.setData(userInfo);
|
||||||
ArrayList<Object> data = new ArrayList<Object>();
|
|
||||||
data.add(userInfo);
|
|
||||||
result.setData(data);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result = new RemoteOperationResult(false, get);
|
result = new RemoteOperationResult<>(getMethod);
|
||||||
String response = get.getResponseBodyAsString();
|
String response = getMethod.getResponseBodyAsString();
|
||||||
Log_OC.e(TAG, "Failed response while getting user information ");
|
Log_OC.e(TAG, "Failed response while getting user information ");
|
||||||
if (response != null) {
|
if (getMethod != null) {
|
||||||
Log_OC.e(TAG, "*** status code: " + status + " ; response message: " + response);
|
Log_OC.e(TAG, "*** status code: " + status + " ; response message: " + response);
|
||||||
} else {
|
} else {
|
||||||
Log_OC.e(TAG, "*** status code: " + status);
|
Log_OC.e(TAG, "*** status code: " + status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
Log_OC.e(TAG, "Exception while getting OC user information", e);
|
Log_OC.e(TAG, "Exception while getting OC user information", e);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (get != null) {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return (status == HttpStatus.SC_OK);
|
return (status == HttpConstants.HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class UserInfo {
|
public static class UserInfo {
|
||||||
public String mId = "";
|
public String mId = "";
|
||||||
public String mDisplayName = "";
|
public String mDisplayName = "";
|
||||||
|
@ -28,42 +28,36 @@
|
|||||||
package com.owncloud.android.lib.resources.users;
|
package com.owncloud.android.lib.resources.users;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.network.WebdavEntry;
|
import com.owncloud.android.lib.common.http.HttpConstants;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
|
||||||
|
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
|
||||||
import com.owncloud.android.lib.common.network.WebdavUtils;
|
import com.owncloud.android.lib.common.network.WebdavUtils;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
import java.net.URL;
|
||||||
import org.apache.jackrabbit.webdav.DavConstants;
|
import java.util.List;
|
||||||
import org.apache.jackrabbit.webdav.MultiStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import at.bitfire.dav4android.Property;
|
||||||
import java.math.RoundingMode;
|
import at.bitfire.dav4android.property.QuotaAvailableBytes;
|
||||||
import java.util.ArrayList;
|
import at.bitfire.dav4android.property.QuotaUsedBytes;
|
||||||
|
|
||||||
|
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
|
||||||
|
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author marcello
|
* @author marcello
|
||||||
* @author David González Verdugo
|
* @author David González Verdugo
|
||||||
*/
|
*/
|
||||||
public class GetRemoteUserQuotaOperation extends RemoteOperation {
|
public class GetRemoteUserQuotaOperation extends RemoteOperation<GetRemoteUserQuotaOperation.RemoteQuota> {
|
||||||
|
|
||||||
static public class Quota {
|
static public class RemoteQuota {
|
||||||
|
|
||||||
// Not computed yet, e.g. external storage mounted but folder sizes need scanning
|
|
||||||
public static final int PENDING_FREE_QUOTA = -1;
|
|
||||||
|
|
||||||
// Storage not accessible, e.g. external storage with no API to ask for the free space
|
|
||||||
public static final int UNKNOWN_FREE_QUOTA = -2;
|
|
||||||
|
|
||||||
// Quota using all the storage
|
|
||||||
public static final int UNLIMITED_FREE_QUOTA = -3;
|
|
||||||
|
|
||||||
long mFree, mUsed, mTotal;
|
long mFree, mUsed, mTotal;
|
||||||
double mRelative;
|
double mRelative;
|
||||||
|
|
||||||
public Quota(long free, long used, long total, double relative) {
|
public RemoteQuota(long free, long used, long total, double relative) {
|
||||||
mFree = free;
|
mFree = free;
|
||||||
mUsed = used;
|
mUsed = used;
|
||||||
mTotal = total;
|
mTotal = total;
|
||||||
@ -90,45 +84,36 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
protected RemoteOperationResult<RemoteQuota> run(OwnCloudClient client) {
|
||||||
RemoteOperationResult result = null;
|
RemoteOperationResult<RemoteQuota> result = null;
|
||||||
PropFindMethod query = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// remote request
|
PropfindMethod propfindMethod = new PropfindMethod(
|
||||||
query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath),
|
new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
|
||||||
WebdavUtils.getQuotaPropSet(),
|
DEPTH_0,
|
||||||
DavConstants.DEPTH_0);
|
DavUtils.getQuotaPropSet());
|
||||||
|
|
||||||
int status = client.executeMethod(query);
|
int status = client.executeHttpMethod(propfindMethod);
|
||||||
|
|
||||||
if (isSuccess(status)) {
|
if (isSuccess(status)) {
|
||||||
// get data from remote folder
|
RemoteQuota remoteQuota = readData(propfindMethod.getRoot().getProperties());
|
||||||
MultiStatus dataInServer = query.getResponseBodyAsMultiStatus();
|
|
||||||
Quota quota = readData(dataInServer, client);
|
|
||||||
|
|
||||||
// Result of the operation
|
result = new RemoteOperationResult<>(OK);
|
||||||
result = new RemoteOperationResult(true, query);
|
|
||||||
|
|
||||||
ArrayList<Object> data = new ArrayList<>();
|
|
||||||
data.add(quota);
|
|
||||||
|
|
||||||
// Add data to the result
|
// Add data to the result
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
result.setData(data);
|
result.setData(remoteQuota);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// synchronization failed
|
} else { // synchronization failed
|
||||||
result = new RemoteOperationResult(false, query);
|
result = new RemoteOperationResult<>(propfindMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
result = new RemoteOperationResult(e);
|
result = new RemoteOperationResult<>(e);
|
||||||
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (query != null)
|
|
||||||
query.releaseConnection(); // let the connection available for other methods
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage());
|
Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage());
|
||||||
} else {
|
} else {
|
||||||
@ -145,47 +130,48 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
private boolean isSuccess(int status) {
|
||||||
return status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK;
|
return status == HttpConstants.HTTP_MULTI_STATUS || status == HttpConstants.HTTP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the data retrieved from the server about the quota
|
* Read the data retrieved from the server about the quota
|
||||||
*
|
*
|
||||||
* @param remoteData Full response got from the server with the data of the quota
|
* @param properties WebDAV properties containing quota data
|
||||||
* @param client Client instance to the remote server where the data were retrieved
|
* @return new {@link RemoteQuota} instance representing the data read from the server
|
||||||
* @return new Quota instance representing the data read from the server
|
|
||||||
*/
|
*/
|
||||||
private Quota readData(MultiStatus remoteData, OwnCloudClient client) {
|
private RemoteQuota readData(List<Property> properties) {
|
||||||
|
long quotaAvailable = 0;
|
||||||
|
long quotaUsed = 0;
|
||||||
|
|
||||||
// parse data from remote folder
|
for(Property property : properties) {
|
||||||
WebdavEntry we = new WebdavEntry(remoteData.getResponses()[0], client.getWebdavUri().getPath());
|
if(property instanceof QuotaAvailableBytes)
|
||||||
|
quotaAvailable = ((QuotaAvailableBytes) property).getQuotaAvailableBytes();
|
||||||
|
if(property instanceof QuotaUsedBytes)
|
||||||
|
quotaUsed = ((QuotaUsedBytes) property).getQuotaUsedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
// If there's a special case, available bytes will contain a negative code
|
// If there's a special case, quota available will contain a negative code
|
||||||
// -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning
|
// -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning
|
||||||
// -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space
|
// -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space
|
||||||
// -3, UNLIMITED: Quota using all the storage
|
// -3, UNLIMITED: Quota using all the storage
|
||||||
if (we.quotaAvailableBytes().compareTo(new BigDecimal(1)) == -1) {
|
if (quotaAvailable < 0) {
|
||||||
return new Quota(
|
return new RemoteQuota(
|
||||||
we.quotaAvailableBytes().longValue(),
|
quotaAvailable,
|
||||||
we.quotaUsedBytes().longValue(),
|
quotaUsed,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
long totalQuota = quotaAvailable + quotaUsed;
|
||||||
|
double relativeQuota = (double)(quotaUsed * 100)/totalQuota;
|
||||||
|
double roundedRelativeQuota = Math.round(relativeQuota * 100)/100.0d;
|
||||||
|
|
||||||
BigDecimal totalQuota = we.quotaAvailableBytes().add(we.quotaUsedBytes());
|
return new RemoteQuota(
|
||||||
|
quotaAvailable,
|
||||||
BigDecimal relativeQuota = we.quotaUsedBytes()
|
quotaUsed,
|
||||||
.multiply(new BigDecimal(100))
|
totalQuota,
|
||||||
.divide(totalQuota, 2, RoundingMode.HALF_UP);
|
roundedRelativeQuota
|
||||||
|
|
||||||
return new Quota(
|
|
||||||
we.quotaAvailableBytes().longValue(),
|
|
||||||
we.quotaUsedBytes().longValue(),
|
|
||||||
totalQuota.longValue(),
|
|
||||||
relativeQuota.doubleValue()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,4 +43,8 @@ android {
|
|||||||
packagingOptions {
|
packagingOptions {
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,193 +0,0 @@
|
|||||||
/* 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.test_project;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertStoreException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.ConnectTimeoutException;
|
|
||||||
import org.apache.commons.httpclient.params.HttpConnectionParams;
|
|
||||||
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.network.AdvancedSslSocketFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SelfSignedConfidentSslSocketFactory allows to create SSL {@link Socket}s
|
|
||||||
* that accepts self-signed server certificates.
|
|
||||||
*
|
|
||||||
* WARNING: this SHOULD NOT be used in productive environments.
|
|
||||||
*
|
|
||||||
* @author David A. Velasco
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class SelfSignedConfidentSslSocketFactory implements SecureProtocolSocketFactory {
|
|
||||||
|
|
||||||
|
|
||||||
//private SSLContext mSslContext = null;
|
|
||||||
private AdvancedSslSocketFactory mWrappedSslSocketFactory = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for SelfSignedConfidentSslSocketFactory.
|
|
||||||
* @throws GeneralSecurityException
|
|
||||||
*/
|
|
||||||
public SelfSignedConfidentSslSocketFactory() throws GeneralSecurityException {
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
sslContext.init(
|
|
||||||
null,
|
|
||||||
new TrustManager[] { new SelfSignedConfidentX509TrustManager() },
|
|
||||||
null
|
|
||||||
);
|
|
||||||
mWrappedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
|
||||||
return mWrappedSslSocketFactory.createSocket(host, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
return mWrappedSslSocketFactory.createSocket(host, port, clientHost, clientPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to get a new socket connection to the given host within the given time limit.
|
|
||||||
*
|
|
||||||
* @param host The host name/IP
|
|
||||||
* @param port The port on the host
|
|
||||||
* @param clientHost The local host name/IP to bind the socket to
|
|
||||||
* @param clientPort The port on the local machine
|
|
||||||
* @param params {@link HttpConnectionParams} HTTP connection parameters.
|
|
||||||
*
|
|
||||||
* @return Socket A new socket
|
|
||||||
*
|
|
||||||
* @throws IOException if an I/O error occurs while creating the socket
|
|
||||||
* @throws UnknownHostException if the IP address of the host cannot be determined
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(String host, int port, InetAddress localAddress, int localPort,
|
|
||||||
HttpConnectionParams params) throws IOException, UnknownHostException,
|
|
||||||
ConnectTimeoutException {
|
|
||||||
|
|
||||||
return mWrappedSslSocketFactory.createSocket(host, port, localAddress, localPort, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
return mWrappedSslSocketFactory.createSocket(socket, host, port, autoClose);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class SelfSignedConfidentX509TrustManager implements X509TrustManager {
|
|
||||||
|
|
||||||
private X509TrustManager mStandardTrustManager = null;
|
|
||||||
|
|
||||||
public SelfSignedConfidentX509TrustManager()
|
|
||||||
throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
|
|
||||||
super();
|
|
||||||
TrustManagerFactory factory = TrustManagerFactory
|
|
||||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
factory.init((KeyStore)null);
|
|
||||||
mStandardTrustManager = findX509TrustManager(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
|
||||||
throws CertificateException {
|
|
||||||
mStandardTrustManager.checkClientTrusted(chain, authType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
|
|
||||||
* String authType)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
|
||||||
throws CertificateException {
|
|
||||||
if (chain != null && chain.length == 1) {
|
|
||||||
chain[0].checkValidity();
|
|
||||||
} else {
|
|
||||||
mStandardTrustManager.checkServerTrusted(chain, authType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
|
|
||||||
*/
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return mStandardTrustManager.getAcceptedIssuers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locates the first X509TrustManager provided by a given TrustManagerFactory
|
|
||||||
* @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
|
|
||||||
* @return The first X509TrustManager found in factory.
|
|
||||||
* @throws CertStoreException When no X509TrustManager instance was found in factory
|
|
||||||
*/
|
|
||||||
private X509TrustManager findX509TrustManager(TrustManagerFactory factory)
|
|
||||||
throws CertStoreException {
|
|
||||||
TrustManager tms[] = factory.getTrustManagers();
|
|
||||||
for (int i = 0; i < tms.length; i++) {
|
|
||||||
if (tms[i] instanceof X509TrustManager) {
|
|
||||||
return (X509TrustManager) tms[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +1,22 @@
|
|||||||
/* ownCloud Android Library is available under MIT license
|
/* ownCloud Android Library is available under MIT license
|
||||||
* Copyright (C) 2018 ownCloud GmbH.
|
* Copyright (C) 2018 ownCloud GmbH.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*
|
*
|
||||||
@ -24,15 +24,6 @@
|
|||||||
|
|
||||||
package com.owncloud.android.lib.test_project;
|
package com.owncloud.android.lib.test_project;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -41,12 +32,8 @@ import android.util.Log;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
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.authentication.OwnCloudCredentialsFactory;
|
||||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.resources.files.ChunkedUploadRemoteFileOperation;
|
|
||||||
import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation;
|
import com.owncloud.android.lib.resources.files.CreateRemoteFolderOperation;
|
||||||
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
|
||||||
@ -54,12 +41,18 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
|
|||||||
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.files.RenameRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.RenameRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
|
||||||
|
import com.owncloud.android.lib.resources.files.chunks.ChunkedUploadRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
|
import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
|
||||||
import com.owncloud.android.lib.resources.shares.GetRemoteSharesOperation;
|
import com.owncloud.android.lib.resources.shares.GetRemoteSharesOperation;
|
||||||
import com.owncloud.android.lib.resources.shares.RemoveRemoteShareOperation;
|
import com.owncloud.android.lib.resources.shares.RemoveRemoteShareOperation;
|
||||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||||
import com.owncloud.android.lib.resources.users.GetRemoteUserQuotaOperation;
|
|
||||||
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation;
|
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation;
|
||||||
|
import com.owncloud.android.lib.resources.users.GetRemoteUserQuotaOperation;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity to test OC framework
|
* Activity to test OC framework
|
||||||
@ -69,59 +62,43 @@ import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class TestActivity extends Activity {
|
public class TestActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = null;
|
private static final String TAG = null;
|
||||||
// This account must exists on the server side
|
// This account must exists on the server side
|
||||||
private String mServerUri;
|
private String mServerUri;
|
||||||
private String mUser;
|
private String mUser;
|
||||||
private String mPass;
|
private String mPass;
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 1024;
|
private static final int BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
public static final String ASSETS__TEXT_FILE_NAME = "textFile.txt";
|
public static final String ASSETS__TEXT_FILE_NAME = "textFile.txt";
|
||||||
public static final String ASSETS__IMAGE_FILE_NAME = "imageFile.png";
|
public static final String ASSETS__IMAGE_FILE_NAME = "imageFile.png";
|
||||||
public static final String ASSETS__VIDEO_FILE_NAME = "videoFile.MP4";
|
public static final String ASSETS__VIDEO_FILE_NAME = "videoFile.MP4";
|
||||||
|
|
||||||
//private Account mAccount = null;
|
//private Account mAccount = null;
|
||||||
private OwnCloudClient mClient;
|
private OwnCloudClient mClient;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_test);
|
setContentView(R.layout.activity_test);
|
||||||
|
|
||||||
mServerUri = getString(R.string.server_base_url);
|
mServerUri = getString(R.string.server_base_url);
|
||||||
mUser = getString(R.string.username);
|
mUser = getString(R.string.username);
|
||||||
mPass = getString(R.string.password);
|
mPass = getString(R.string.password);
|
||||||
|
|
||||||
Protocol pr = Protocol.getProtocol("https");
|
mClient = new OwnCloudClient(Uri.parse(mServerUri));
|
||||||
if (pr == null || !(pr.getSocketFactory() instanceof SelfSignedConfidentSslSocketFactory)) {
|
|
||||||
try {
|
|
||||||
ProtocolSocketFactory psf = new SelfSignedConfidentSslSocketFactory();
|
|
||||||
Protocol.registerProtocol(
|
|
||||||
"https",
|
|
||||||
new Protocol("https", psf, 443));
|
|
||||||
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
Log.e(TAG, "Self-signed confident SSL context could not be loaded");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mClient = new OwnCloudClient(Uri.parse(mServerUri), NetworkUtils.getMultiThreadedConnManager());
|
|
||||||
mClient.setDefaultTimeouts(
|
|
||||||
OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT,
|
|
||||||
OwnCloudClientFactory.DEFAULT_CONNECTION_TIMEOUT);
|
|
||||||
mClient.setFollowRedirects(true);
|
mClient.setFollowRedirects(true);
|
||||||
mClient.setCredentials(
|
mClient.setCredentials(
|
||||||
OwnCloudCredentialsFactory.newBasicCredentials(
|
OwnCloudCredentialsFactory.newBasicCredentials(
|
||||||
mUser,
|
mUser,
|
||||||
mPass
|
mPass
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
mClient.setBaseUri(Uri.parse(mServerUri));
|
mClient.setBaseUri(Uri.parse(mServerUri));
|
||||||
|
|
||||||
Log.v(TAG, "onCreate finished, ownCloud client ready");
|
Log.v(TAG, "onCreate finished, ownCloud client ready");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,57 +111,57 @@ public class TestActivity extends Activity {
|
|||||||
/**
|
/**
|
||||||
* Access to the library method to Create a Folder
|
* Access to the library method to Create a Folder
|
||||||
* @param remotePath Full path to the new directory to create in the remote server.
|
* @param remotePath Full path to the new directory to create in the remote server.
|
||||||
* @param createFullPath 'True' means that all the ancestor folders should be created if
|
* @param createFullPath 'True' means that all the ancestor folders should be created if
|
||||||
* don't exist yet.
|
* don't exist yet.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult createFolder(String remotePath, boolean createFullPath) {
|
public RemoteOperationResult createFolder(String remotePath, boolean createFullPath) {
|
||||||
|
|
||||||
return TestActivity.createFolder(remotePath, createFullPath, mClient);
|
return TestActivity.createFolder(remotePath, createFullPath, mClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Create a Folder
|
* Access to the library method to Create a Folder
|
||||||
* @param remotePath Full path to the new directory to create in the remote server.
|
* @param remotePath Full path to the new directory to create in the remote server.
|
||||||
* @param createFullPath 'True' means that all the ancestor folders should be created if
|
* @param createFullPath 'True' means that all the ancestor folders should be created if
|
||||||
* don't exist yet.
|
* don't exist yet.
|
||||||
* @param client Client instance configured to access the target OC server.
|
* @param client Client instance configured to access the target OC server.
|
||||||
*
|
*
|
||||||
* @return Result of the operation
|
* @return Result of the operation
|
||||||
*/
|
*/
|
||||||
public static RemoteOperationResult createFolder(
|
public static RemoteOperationResult createFolder(
|
||||||
String remotePath, boolean createFullPath, OwnCloudClient client
|
String remotePath, boolean createFullPath, OwnCloudClient client
|
||||||
) {
|
) {
|
||||||
|
|
||||||
CreateRemoteFolderOperation createOperation =
|
CreateRemoteFolderOperation createOperation =
|
||||||
new CreateRemoteFolderOperation(remotePath, createFullPath);
|
new CreateRemoteFolderOperation(remotePath, createFullPath);
|
||||||
RemoteOperationResult result = createOperation.execute(client);
|
RemoteOperationResult result = createOperation.execute(client);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Rename a File or Folder
|
* Access to the library method to Rename a File or Folder
|
||||||
* @param oldName Old name of the file.
|
* @param oldName Old name of the file.
|
||||||
* @param oldRemotePath Old remote path of the file. For folders it starts and ends by "/"
|
* @param oldRemotePath Old remote path of the file. For folders it starts and ends by "/"
|
||||||
* @param newName New name to set as the name of file.
|
* @param newName New name to set as the name of file.
|
||||||
* @param isFolder 'true' for folder and 'false' for files
|
* @param isFolder 'true' for folder and 'false' for files
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public RemoteOperationResult renameFile(String oldName, String oldRemotePath, String newName, boolean isFolder) {
|
public RemoteOperationResult renameFile(String oldName, String oldRemotePath, String newName, boolean isFolder) {
|
||||||
|
|
||||||
RenameRemoteFileOperation renameOperation = new RenameRemoteFileOperation(oldName, oldRemotePath, newName, isFolder);
|
RenameRemoteFileOperation renameOperation = new RenameRemoteFileOperation(oldName, oldRemotePath, newName, isFolder);
|
||||||
RemoteOperationResult result = renameOperation.execute(mClient);
|
RemoteOperationResult result = renameOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Remove a File or Folder
|
* Access to the library method to Remove a File or Folder
|
||||||
*
|
*
|
||||||
* @param remotePath Remote path of the file or folder in the server.
|
* @param remotePath Remote path of the file or folder in the server.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -193,10 +170,10 @@ public class TestActivity extends Activity {
|
|||||||
RemoteOperationResult result = removeOperation.execute(mClient);
|
RemoteOperationResult result = removeOperation.execute(mClient);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Remove a File or Folder
|
* Access to the library method to Remove a File or Folder
|
||||||
*
|
*
|
||||||
* @param remotePath Remote path of the file or folder in the server.
|
* @param remotePath Remote path of the file or folder in the server.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -205,46 +182,46 @@ public class TestActivity extends Activity {
|
|||||||
RemoteOperationResult result = removeOperation.execute(client);
|
RemoteOperationResult result = removeOperation.execute(client);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Read a Folder (PROPFIND DEPTH 1)
|
* Access to the library method to Read a Folder (PROPFIND DEPTH 1)
|
||||||
* @param remotePath
|
* @param remotePath
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult readFile(String remotePath) {
|
public RemoteOperationResult readFile(String remotePath) {
|
||||||
|
|
||||||
ReadRemoteFolderOperation readOperation= new ReadRemoteFolderOperation(remotePath);
|
ReadRemoteFolderOperation readOperation= new ReadRemoteFolderOperation(remotePath);
|
||||||
RemoteOperationResult result = readOperation.execute(mClient);
|
RemoteOperationResult result = readOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Download a File
|
* Access to the library method to Download a File
|
||||||
* @param remotePath
|
* @param remotePath
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult downloadFile(RemoteFile remoteFile, String temporalFolder) {
|
public RemoteOperationResult downloadFile(RemoteFile remoteFile, String temporalFolder) {
|
||||||
// Create folder
|
// Create folder
|
||||||
String path = "/owncloud/tmp/" + temporalFolder;
|
String path = "/owncloud/tmp/" + temporalFolder;
|
||||||
File privateFolder = getFilesDir();
|
File privateFolder = getFilesDir();
|
||||||
File folder = new File(privateFolder.getAbsolutePath() + "/" + path);
|
File folder = new File(privateFolder.getAbsolutePath() + "/" + path);
|
||||||
folder.mkdirs();
|
folder.mkdirs();
|
||||||
|
|
||||||
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remoteFile.getRemotePath(), folder.getAbsolutePath());
|
DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remoteFile.getRemotePath(), folder.getAbsolutePath());
|
||||||
RemoteOperationResult result = downloadOperation.execute(mClient);
|
RemoteOperationResult result = downloadOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access to the library method to Upload a File
|
/** Access to the library method to Upload a File
|
||||||
* @param storagePath
|
* @param storagePath
|
||||||
* @param remotePath
|
* @param remotePath
|
||||||
* @param mimeType
|
* @param mimeType
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult uploadFile(
|
public RemoteOperationResult uploadFile(
|
||||||
@ -253,13 +230,13 @@ public class TestActivity extends Activity {
|
|||||||
|
|
||||||
return TestActivity.uploadFile(storagePath, remotePath, mimeType, mClient);
|
return TestActivity.uploadFile(storagePath, remotePath, mimeType, mClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access to the library method to Upload a File
|
/** Access to the library method to Upload a File
|
||||||
* @param storagePath
|
* @param storagePath
|
||||||
* @param remotePath
|
* @param remotePath
|
||||||
* @param mimeType
|
* @param mimeType
|
||||||
* @param client Client instance configured to access the target OC server.
|
* @param client Client instance configured to access the target OC server.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static RemoteOperationResult uploadFile(
|
public static RemoteOperationResult uploadFile(
|
||||||
@ -271,31 +248,31 @@ public class TestActivity extends Activity {
|
|||||||
UploadRemoteFileOperation uploadOperation;
|
UploadRemoteFileOperation uploadOperation;
|
||||||
|
|
||||||
if ((new File(storagePath)).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
|
if ((new File(storagePath)).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
|
||||||
uploadOperation = new ChunkedUploadRemoteFileOperation(
|
uploadOperation = new ChunkedUploadRemoteFileOperation("1",
|
||||||
storagePath, remotePath, mimeType, fileLastModifTimestamp
|
storagePath, remotePath, mimeType, TAG, fileLastModifTimestamp
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
uploadOperation = new UploadRemoteFileOperation(
|
uploadOperation = new UploadRemoteFileOperation(
|
||||||
storagePath, remotePath, mimeType, fileLastModifTimestamp
|
storagePath, remotePath, mimeType, fileLastModifTimestamp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteOperationResult result = uploadOperation.execute(client);
|
RemoteOperationResult result = uploadOperation.execute(client);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access to the library method to Get Shares
|
/** Access to the library method to Get Shares
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult getShares(){
|
public RemoteOperationResult getShares(){
|
||||||
|
|
||||||
GetRemoteSharesOperation getOperation = new GetRemoteSharesOperation();
|
GetRemoteSharesOperation getOperation = new GetRemoteSharesOperation();
|
||||||
RemoteOperationResult result = getOperation.execute(mClient);
|
RemoteOperationResult result = getOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access to the library method to Create Share
|
/** Access to the library method to Create Share
|
||||||
* @param path Full path of the file/folder being shared. Mandatory argument
|
* @param path Full path of the file/folder being shared. Mandatory argument
|
||||||
* @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument
|
* @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument
|
||||||
@ -310,33 +287,33 @@ public class TestActivity extends Activity {
|
|||||||
* 16- Re-share
|
* 16- Re-share
|
||||||
* 31- All above Default for private shares
|
* 31- All above Default for private shares
|
||||||
* For user or group shares.
|
* For user or group shares.
|
||||||
* To obtain combinations, add the desired values together.
|
* To obtain combinations, add the desired values together.
|
||||||
* For instance, for Re-Share, delete, read, update add 16+8+2+1 = 27.
|
* For instance, for Re-Share, delete, read, update add 16+8+2+1 = 27.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public RemoteOperationResult createShare(String path, ShareType shareType, String shareWith, boolean publicUpload,
|
public RemoteOperationResult createShare(String path, ShareType shareType, String shareWith, boolean publicUpload,
|
||||||
String password, int permissions){
|
String password, int permissions){
|
||||||
|
|
||||||
CreateRemoteShareOperation createOperation = new CreateRemoteShareOperation(path, shareType, shareWith, publicUpload, password, permissions);
|
CreateRemoteShareOperation createOperation = new CreateRemoteShareOperation(path, shareType, shareWith, publicUpload, password, permissions);
|
||||||
RemoteOperationResult result = createOperation.execute(mClient);
|
RemoteOperationResult result = createOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to the library method to Remove Share
|
* Access to the library method to Remove Share
|
||||||
*
|
*
|
||||||
* @param idShare Share ID
|
* @param idShare Share ID
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public RemoteOperationResult removeShare(int idShare) {
|
public RemoteOperationResult removeShare(int idShare) {
|
||||||
RemoveRemoteShareOperation removeOperation = new RemoveRemoteShareOperation(idShare);
|
RemoveRemoteShareOperation removeOperation = new RemoveRemoteShareOperation(idShare);
|
||||||
RemoteOperationResult result = removeOperation.execute(mClient);
|
RemoteOperationResult result = removeOperation.execute(mClient);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteOperationResult getQuota(String remotePath) {
|
public RemoteOperationResult getQuota(String remotePath) {
|
||||||
@ -349,20 +326,20 @@ public class TestActivity extends Activity {
|
|||||||
GetRemoteUserAvatarOperation getUserAvatarOperation = new GetRemoteUserAvatarOperation(dimension, etag);
|
GetRemoteUserAvatarOperation getUserAvatarOperation = new GetRemoteUserAvatarOperation(dimension, etag);
|
||||||
return getUserAvatarOperation.execute(mClient);
|
return getUserAvatarOperation.execute(mClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts file from AssetManager to cache folder.
|
* Extracts file from AssetManager to cache folder.
|
||||||
*
|
*
|
||||||
* @param fileName Name of the asset file to extract.
|
* @param fileName Name of the asset file to extract.
|
||||||
* @return File instance of the extracted file.
|
* @return File instance of the extracted file.
|
||||||
*/
|
*/
|
||||||
public File extractAsset(String fileName) throws IOException {
|
public File extractAsset(String fileName) throws IOException {
|
||||||
return TestActivity.extractAsset(fileName, this);
|
return TestActivity.extractAsset(fileName, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts file from AssetManager to cache folder.
|
* Extracts file from AssetManager to cache folder.
|
||||||
*
|
*
|
||||||
* @param fileName Name of the asset file to extract.
|
* @param fileName Name of the asset file to extract.
|
||||||
* @param context Android context to access assets and file system.
|
* @param context Android context to access assets and file system.
|
||||||
* @return File instance of the extracted file.
|
* @return File instance of the extracted file.
|
||||||
@ -391,4 +368,4 @@ public class TestActivity extends Activity {
|
|||||||
Long timeStampLong = file.lastModified()/1000;
|
Long timeStampLong = file.lastModified()/1000;
|
||||||
return timeStampLong.toString();
|
return timeStampLong.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,14 +37,13 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.test_project.R;
|
import com.owncloud.android.lib.test_project.R;
|
||||||
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
|
|
||||||
import com.owncloud.android.lib.test_project.TestActivity;
|
import com.owncloud.android.lib.test_project.TestActivity;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@ -373,7 +372,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2<TestActivity>
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
result = copyOperation.execute(mClient);
|
result = copyOperation.execute(mClient);
|
||||||
assertTrue(result.getHttpCode() == HttpStatus.SC_CONFLICT);
|
assertTrue(result.getHttpCode() == HttpConstants.HTTP_CONFLICT);
|
||||||
|
|
||||||
// target location (renaming) has invalid characters
|
// target location (renaming) has invalid characters
|
||||||
copyOperation = new CopyRemoteFileOperation(
|
copyOperation = new CopyRemoteFileOperation(
|
||||||
|
@ -29,8 +29,8 @@ import java.security.GeneralSecurityException;
|
|||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -43,7 +43,6 @@ import com.owncloud.android.lib.common.network.NetworkUtils;
|
|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation;
|
import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation;
|
||||||
import com.owncloud.android.lib.test_project.R;
|
import com.owncloud.android.lib.test_project.R;
|
||||||
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to test GetRemoteCapabilitiesOperation
|
* Class to test GetRemoteCapabilitiesOperation
|
||||||
|
@ -29,9 +29,9 @@ import java.security.GeneralSecurityException;
|
|||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@ -43,7 +43,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|||||||
import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation;
|
import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation;
|
||||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||||
import com.owncloud.android.lib.test_project.R;
|
import com.owncloud.android.lib.test_project.R;
|
||||||
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -184,11 +183,11 @@ public class GetShareesTest extends RemoteTest {
|
|||||||
// search for sharees including wrong page values
|
// search for sharees including wrong page values
|
||||||
getShareesOperation = new GetRemoteShareesOperation("a", 0, 50);
|
getShareesOperation = new GetRemoteShareesOperation("a", 0, 50);
|
||||||
result = getShareesOperation.execute(mClient);
|
result = getShareesOperation.execute(mClient);
|
||||||
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST);
|
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpConstants.HTTP_BAD_REQUEST);
|
||||||
|
|
||||||
getShareesOperation = new GetRemoteShareesOperation("a", 1, 0);
|
getShareesOperation = new GetRemoteShareesOperation("a", 1, 0);
|
||||||
result = getShareesOperation.execute(mClient);
|
result = getShareesOperation.execute(mClient);
|
||||||
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST);
|
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpConstants.HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,11 +236,11 @@ public class GetShareesTest extends RemoteTest {
|
|||||||
// search for sharees including wrong page values
|
// search for sharees including wrong page values
|
||||||
getShareesOperation = new GetRemoteShareesOperation("@", 0, 50);
|
getShareesOperation = new GetRemoteShareesOperation("@", 0, 50);
|
||||||
result = getShareesOperation.execute(mClient);
|
result = getShareesOperation.execute(mClient);
|
||||||
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST);
|
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpConstants.HTTP_BAD_REQUEST);
|
||||||
|
|
||||||
getShareesOperation = new GetRemoteShareesOperation("@", 1, 0);
|
getShareesOperation = new GetRemoteShareesOperation("@", 1, 0);
|
||||||
result = getShareesOperation.execute(mClient);
|
result = getShareesOperation.execute(mClient);
|
||||||
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST);
|
assertTrue(!result.isSuccess() && result.getHttpCode() == HttpConstants.HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +31,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|||||||
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation.ResultData;
|
import com.owncloud.android.lib.resources.users.GetRemoteUserAvatarOperation.ResultData;
|
||||||
import com.owncloud.android.lib.test_project.TestActivity;
|
import com.owncloud.android.lib.test_project.TestActivity;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to test {@link GetRemoteUserAvatarOperation}
|
* Class to test {@link GetRemoteUserAvatarOperation}
|
||||||
@ -81,7 +81,7 @@ public class GetUserAvatarTest extends RemoteTest {
|
|||||||
// request again, with the just received etag
|
// request again, with the just received etag
|
||||||
result = mActivity.getUserAvatar(AVATAR_DIMENSION, etag);
|
result = mActivity.getUserAvatar(AVATAR_DIMENSION, etag);
|
||||||
assertFalse(result.isSuccess());
|
assertFalse(result.isSuccess());
|
||||||
assertTrue(result.getHttpCode() == HttpStatus.SC_NOT_MODIFIED);
|
assertTrue(result.getHttpCode() == HttpConstants.HTTP_NOT_MODIFIED);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -29,9 +29,9 @@ import java.security.GeneralSecurityException;
|
|||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
||||||
@ -41,7 +41,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
import com.owncloud.android.lib.resources.files.MoveRemoteFileOperation;
|
import com.owncloud.android.lib.resources.files.MoveRemoteFileOperation;
|
||||||
import com.owncloud.android.lib.test_project.R;
|
import com.owncloud.android.lib.test_project.R;
|
||||||
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
|
|
||||||
import com.owncloud.android.lib.test_project.TestActivity;
|
import com.owncloud.android.lib.test_project.TestActivity;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -373,7 +372,7 @@ public class MoveFileTest extends RemoteTest {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
result = moveOperation.execute(mClient);
|
result = moveOperation.execute(mClient);
|
||||||
assertTrue(result.getHttpCode() == HttpStatus.SC_CONFLICT);
|
assertTrue(result.getHttpCode() == HttpConstants.HTTP_CONFLICT);
|
||||||
|
|
||||||
// target location (renaming) has invalid characters
|
// target location (renaming) has invalid characters
|
||||||
moveOperation = new MoveRemoteFileOperation(
|
moveOperation = new MoveRemoteFileOperation(
|
||||||
|
@ -27,12 +27,12 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import org.apache.commons.httpclient.ConnectTimeoutException;
|
|
||||||
import org.apache.commons.httpclient.HttpException;
|
|
||||||
import org.apache.commons.httpclient.methods.HeadMethod;
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
import org.apache.commons.httpclient.HttpStatus;
|
|
||||||
import org.apache.jackrabbit.webdav.DavConstants;
|
import org.apache.jackrabbit.webdav.DavConstants;
|
||||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
||||||
|
|
||||||
@ -48,7 +48,6 @@ import com.owncloud.android.lib.common.authentication.OwnCloudCredentials;
|
|||||||
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
import com.owncloud.android.lib.common.authentication.OwnCloudCredentialsFactory;
|
||||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||||
import com.owncloud.android.lib.test_project.R;
|
import com.owncloud.android.lib.test_project.R;
|
||||||
import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,7 +313,7 @@ public class OwnCloudClientTest extends AndroidTestCase {
|
|||||||
DavConstants.DEPTH_0);
|
DavConstants.DEPTH_0);
|
||||||
int status = client.executeMethod(propfind);
|
int status = client.executeMethod(propfind);
|
||||||
assertEquals("WebDAV request did not work on WebDAV URI",
|
assertEquals("WebDAV request did not work on WebDAV URI",
|
||||||
HttpStatus.SC_MULTI_STATUS, status);
|
HttpConstants.HTTP_MULTI_STATUS, status);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Exception in PROPFIND method execution", e);
|
Log.e(TAG, "Exception in PROPFIND method execution", e);
|
||||||
|
@ -25,8 +25,8 @@ package com.owncloud.android.lib.test_project.test;
|
|||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
import org.apache.commons.httpclient.protocol.Protocol;
|
|
||||||
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user