diff --git a/app/build.gradle b/app/build.gradle index c93eb509511055cacde6495a8b826e2845631a45..366043642065fa70a75cb26e3b80420ed68c0fa0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,10 +23,12 @@ def getTestProp(String propName) { android { - compileSdkVersion 26 + compileSdkVersion 28 + defaultConfig { applicationId "foundation.e.drive" minSdkVersion 26 + versionCode 1 //versionName "1.0" versionName "beta-${versionMajor}-build-o-${buildTime()}" @@ -34,6 +36,8 @@ android { buildConfigField "String", "testAccountName", "\""+getTestProp("testAccountName")+"\"" buildConfigField "String", "testAccountPWd", "\""+getTestProp("testAccountPwd")+"\"" buildConfigField "String", "testServerUrl", "\""+getTestProp("testServerUrl")+"\"" + + multiDexEnabled true } buildTypes { release { @@ -54,8 +58,17 @@ android { } } -} + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + configurations.all { + exclude group: "org.slf4j", module: "slf4j-log4j12" + exclude group: "log4j", module: "log4j" + } + +} dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') @@ -66,7 +79,13 @@ dependencies { androidTestImplementation 'com.android.support:support-annotations:27.1.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' api 'com.android.support:support-annotations:27.1.1' - api project(':NextcloudLib') + //api project(':NextcloudLib') + implementation 'androidx.multidex:multidex:2.0.1' +// implementation project('nextcloud-android-library') + implementation ("com.github.nextcloud:android-library:master-SNAPSHOT") { + exclude group: 'org.ogce', module: 'xpp3' // unused in Android and brings wrong Junit version + } + //start to add lib for test - 1/4/21 //@TODO: add junit runner as lib for testImplementation @@ -81,4 +100,13 @@ dependencies { //testImplementation Libs.AndroidX.Test.archCoreTesting //TODO: replace by not android X version //implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' androidTestImplementation 'junit:junit:4.12' + + implementation "commons-httpclient:commons-httpclient:3.1@jar" + + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.annotation:annotation:1.3.0' + + // for NC Lib + api 'org.apache.jackrabbit:jackrabbit-webdav:2.12.6+' + api 'com.squareup.moshi:moshi:1.8.0' } diff --git a/app/src/main/java/foundation/e/drive/operations/CreateInitialFolderRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/CreateInitialFolderRemoteOperation.java index 72b837a343873c06cbdf1af74186c1979b947eb2..269f6d84d7e8252c24f85f8237b98ae3d965feca 100644 --- a/app/src/main/java/foundation/e/drive/operations/CreateInitialFolderRemoteOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/CreateInitialFolderRemoteOperation.java @@ -48,7 +48,7 @@ public class CreateInitialFolderRemoteOperation extends RemoteOperation { //Perfom request CreateFolderRemoteOperation createFolderOperation = new CreateFolderRemoteOperation(mRemotePath, mCreateFullPath); - RemoteOperationResult createOperationResult = createFolderOperation.execute(client, true); + RemoteOperationResult createOperationResult = createFolderOperation.execute(client); if(createOperationResult.isSuccess() || createOperationResult.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS ){ if(DbHelper.insertSyncedFolder(mSyncedFolder, mContext) >= 0 ) { diff --git a/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java index dce9dff620ad4ab620450b046dcd50eb94fb49e5..364e9484b493b4ecbf265f24807f226388e9e7f6 100644 --- a/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java @@ -92,7 +92,7 @@ class DownloadFileRemoteOperation extends RemoteOperation { private int downloadFile(OwnCloudClient client, File targetFile) throws IOException, OperationCancelledException { int status = -1; boolean savedFile = false; - mGet = new GetMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath)); + mGet = new GetMethod(client.getDavUri() + WebdavUtils.encodePath(mRemotePath)); FileOutputStream fos = null; try { diff --git a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java index ffde62e895fbb87477aaed727c39cc5784a376cf..5854ae0e183a165f5034fe73ba195c7d2035aab0 100644 --- a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java @@ -14,7 +14,7 @@ import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.model.RemoteFile; -import com.owncloud.android.lib.resources.files.LightReadFolderRemoteOperation; +//import com.owncloud.android.lib.resources.files.LightReadFolderRemoteOperation; import java.io.File; import java.util.ArrayList; import java.util.List; @@ -22,6 +22,7 @@ import java.util.ListIterator; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.utils.CommonUtils; +import foundation.e.drive.utils.ncLib.LightReadFolderRemoteOperation; import static org.apache.jackrabbit.webdav.DavConstants.DEPTH_1; diff --git a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java index 515ce35f4ab8a548244d5f63d48b85f740e1561b..29f1d3f8a4cbd0fe387f9ef19a7eba392479b5de 100644 --- a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java @@ -11,8 +11,11 @@ package foundation.e.drive.operations; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.VisibleForTesting; + import android.util.Log; + +import androidx.annotation.VisibleForTesting; + import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.UserInfo; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -20,13 +23,14 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; -import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; +//import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import java.io.File; import java.util.ArrayList; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFileState; import foundation.e.drive.utils.CommonUtils; +import foundation.e.drive.utils.ncLib.resources.users.GetRemoteUserInfoOperation; /** * @author Vincent Bourgmayer @@ -209,7 +213,7 @@ public class UploadFileOperation extends RemoteOperation implements ComparableOp CommonUtils.getMimeType( file ), ( !checkEtag || mSyncedState.getLastETAG().isEmpty() )? null : mSyncedState.getLastETAG(), //If not null, This can cause error 412; that means remote file has change timeStamp ); - uploadRemoteFileOperation.askResultEtag(true); + //uploadRemoteFileOperation.askResultEtag(true); return uploadRemoteFileOperation; } diff --git a/app/src/main/java/foundation/e/drive/providers/MediasSyncProvider.java b/app/src/main/java/foundation/e/drive/providers/MediasSyncProvider.java index 1d49d76db961c13ee54e0b969cd45b57c615eb14..f5dcb689d3bbbe5dc3e193975e8dbf6c8328184c 100644 --- a/app/src/main/java/foundation/e/drive/providers/MediasSyncProvider.java +++ b/app/src/main/java/foundation/e/drive/providers/MediasSyncProvider.java @@ -12,8 +12,8 @@ import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** diff --git a/app/src/main/java/foundation/e/drive/providers/SettingsSyncProvider.java b/app/src/main/java/foundation/e/drive/providers/SettingsSyncProvider.java index 46804b986a96bb3083356023e9cea7a746522851..fa0437df27d6153b554afd8791f311a9c384f7ba 100644 --- a/app/src/main/java/foundation/e/drive/providers/SettingsSyncProvider.java +++ b/app/src/main/java/foundation/e/drive/providers/SettingsSyncProvider.java @@ -12,8 +12,10 @@ import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * diff --git a/app/src/main/java/foundation/e/drive/services/InitializerService.java b/app/src/main/java/foundation/e/drive/services/InitializerService.java index 607edf9d813afa30631a4ad6c3cc7bad87daf2b6..0551e3fccd00c7ddcbfd2031dedefd26e8b88ff8 100644 --- a/app/src/main/java/foundation/e/drive/services/InitializerService.java +++ b/app/src/main/java/foundation/e/drive/services/InitializerService.java @@ -19,7 +19,8 @@ import android.os.Build; import android.os.Environment; import android.os.Handler; import android.os.IBinder; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; diff --git a/app/src/main/java/foundation/e/drive/services/ObserverService.java b/app/src/main/java/foundation/e/drive/services/ObserverService.java index 0cadf83c6381f3af6a8f861c12b9b59a78716d9b..7bff30cdbe01461fe679b0bd553edfcc766b0997 100644 --- a/app/src/main/java/foundation/e/drive/services/ObserverService.java +++ b/app/src/main/java/foundation/e/drive/services/ObserverService.java @@ -19,7 +19,8 @@ import android.os.Handler; import android.os.IBinder; import android.os.Parcelable; import android.provider.MediaStore; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; diff --git a/app/src/main/java/foundation/e/drive/services/OperationManagerService.java b/app/src/main/java/foundation/e/drive/services/OperationManagerService.java index 7054df66db0bd165d717dd49c69309ba94625c32..8f6127d2b83704b189572750d1c26d5ed4593a3d 100644 --- a/app/src/main/java/foundation/e/drive/services/OperationManagerService.java +++ b/app/src/main/java/foundation/e/drive/services/OperationManagerService.java @@ -20,7 +20,8 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; diff --git a/app/src/main/java/foundation/e/drive/services/ResetService.java b/app/src/main/java/foundation/e/drive/services/ResetService.java index ce3f541007efb737a1c89aa915db2f05fbb442c8..54b437ee9b1d1a9848106d42ff4b1f09e0f45c0e 100644 --- a/app/src/main/java/foundation/e/drive/services/ResetService.java +++ b/app/src/main/java/foundation/e/drive/services/ResetService.java @@ -14,7 +14,8 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.IBinder; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import java.io.File; diff --git a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java index b6de97e44b0d2ea228d2db038c3e039357f6de12..dfcce4b7bf48f17f8b68a32a56f75aa5f752338a 100644 --- a/app/src/main/java/foundation/e/drive/utils/CommonUtils.java +++ b/app/src/main/java/foundation/e/drive/utils/CommonUtils.java @@ -20,7 +20,8 @@ import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkInfo; import android.net.Uri; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import android.webkit.MimeTypeMap; diff --git a/app/src/main/java/foundation/e/drive/utils/ncLib/LightReadFolderRemoteOperation.java b/app/src/main/java/foundation/e/drive/utils/ncLib/LightReadFolderRemoteOperation.java new file mode 100644 index 0000000000000000000000000000000000000000..5a0509306704def4ed9038ea0d1a484581a310b8 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/utils/ncLib/LightReadFolderRemoteOperation.java @@ -0,0 +1,155 @@ +package foundation.e.drive.utils.ncLib; + +import com.owncloud.android.lib.common.OwnCloudClient; +//import com.owncloud.android.lib.common.method.GzipedPropfind; +import com.owncloud.android.lib.common.network.WebdavEntry; +import com.owncloud.android.lib.common.network.WebdavUtils; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.files.model.RemoteFile; + +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 java.util.ArrayList; + +import foundation.e.drive.utils.ncLib.common.method.Common; +import foundation.e.drive.utils.ncLib.common.method.GzipedPropfind; + + +public class LightReadFolderRemoteOperation extends RemoteOperation { + + private static final String TAG = LightReadFolderRemoteOperation.class.getSimpleName(); + + private String mRemotePath; + private ArrayList mFolderAndFiles; + private int depth; + private boolean allowGzip; + + /** + * Constructor + * @param remotePath remothe path of folder + * @param depth depth to reach. Value should be in DavConstants (DEPTH_0, DEPTH_1 or DEPTH_INFINITY). DEPTH_0 by default + */ + public LightReadFolderRemoteOperation(String remotePath, int depth, boolean allowGzip){ + mRemotePath = remotePath; + if(depth == DavConstants.DEPTH_0 || depth == DavConstants.DEPTH_1 || depth == DavConstants.DEPTH_INFINITY) { + this.depth = depth; + }else{ + this.depth = DavConstants.DEPTH_0; + } + this.allowGzip = allowGzip; + } + + + /** + * Performs the read operation. + * + * @param client Client object to communicate with the remote ownCloud server. + */ + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + PropFindMethod propfind = null; + String userAgent =""; + try { + // remote request + if(allowGzip){ + propfind = new GzipedPropfind(client.getDavUri() + WebdavUtils.encodePath(mRemotePath), + WebdavUtils.getAllPropSet(), // PropFind Properties + this.depth); + propfind.setRequestHeader("Accept-Encoding", "gzip"); + userAgent = "gzipUserAgent"; + }else{ + propfind = new PropFindMethod(client.getDavUri() + WebdavUtils.encodePath(mRemotePath), + WebdavUtils.getAllPropSet(), // PropFind Properties + this.depth); + } + int status = client.executeMethod(propfind); + // check and process response + boolean isSuccess = (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK); + + if (isSuccess) { + + // get data from remote folder + MultiStatus dataInServer = propfind.getResponseBodyAsMultiStatus(); + readData(dataInServer, client); + // Result of the operation + result = new RemoteOperationResult(true, propfind); + // Add data to the result + if (result.isSuccess()) { + result.setData(mFolderAndFiles); + } + } else { + // synchronization failed + + client.exhaustResponse( ( (GzipedPropfind) propfind).getDecompressedResponseBodyasStream() ); + result = new RemoteOperationResult(false, propfind); + } + } catch (Exception e) { + result = new RemoteOperationResult(e); + } finally { + if (propfind != null) + propfind.releaseConnection(); // let the connection available for other methods + + if (result == null) { + result = new RemoteOperationResult(new Exception("unknown error")); + Log_OC.e(TAG, "Synchronized " + mRemotePath + ": failed"); + } + } + + return result; + } + + public boolean isMultiStatus(int status) { + return (status == HttpStatus.SC_MULTI_STATUS); + } + + /** + * Read the data retrieved from the server about the contents of the target folder + * + * @param 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<>(); + + // parse data from remote folder + WebdavEntry we = new WebdavEntry(remoteData.getResponses()[0], client.getDavUri().getPath()); + mFolderAndFiles.add(fillOCFile(we)); + + // loop to update every child + RemoteFile remoteFile; + for (int i =0 ; ++i < remoteData.getResponses().length;) { + /// new OCFile instance with the data from the server + we = new WebdavEntry(remoteData.getResponses()[i], client.getDavUri().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.setLength(we.getContentLength()); + file.setMimeType(we.getContentType()); + file.setModifiedTimestamp(we.getModifiedTimestamp()); + file.setEtag(we.getETag()); + file.setPermissions(we.getPermissions()); + file.setRemoteId(we.getRemoteId()); + file.setSize(we.getSize()); + return file; + } +} diff --git a/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/Common.java b/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/Common.java new file mode 100644 index 0000000000000000000000000000000000000000..aa8eda98e00e3968f3108fd7a60c0713b992b9a1 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/Common.java @@ -0,0 +1,23 @@ +package foundation.e.drive.utils.ncLib.common.method; + +import android.net.Uri; +import android.util.Log; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.utils.Log_OC; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.params.HttpParams; + +import java.io.IOException; + +public class Common { + + private int mInstanceNumber = 0; + private static final String TAG = Common.class.getSimpleName(); + + +} diff --git a/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/GzipedPropfind.java b/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/GzipedPropfind.java new file mode 100644 index 0000000000000000000000000000000000000000..359e3d24f623c9a56b8c6fbd5067e7017419a7d5 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/utils/ncLib/common/method/GzipedPropfind.java @@ -0,0 +1,113 @@ +package foundation.e.drive.utils.ncLib.common.method; + +import org.apache.commons.httpclient.Header; +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; +import org.apache.jackrabbit.webdav.xml.DomUtil; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.zip.GZIPInputStream; +import javax.xml.parsers.ParserConfigurationException; + +public class GzipedPropfind extends PropFindMethod { + + public GzipedPropfind(String uri) throws IOException { + super(uri); + } + + + public boolean isResponseGzipped(){ + Header contentEncodingHeader= getResponseHeader("Content-Encoding"); + + if(contentEncodingHeader != null && contentEncodingHeader.getValue().contains("gzip") ) { + return true; + } + return false; + } + + + public InputStream getDecompressedResponseBodyasStream() throws IOException{ + if(!isResponseGzipped() ) return super.getResponseBodyAsStream(); + + //@TOdo: look for potential optimisation like pipe gzipInputStream directly in InputStream in + StringBuilder s = new StringBuilder(); + String line; + try{ + GZIPInputStream gzipis = new GZIPInputStream(getResponseBodyAsStream()); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipis)); + + while ((line = bufferedReader.readLine()) != null) { + s.append(line); + } + bufferedReader.close(); + return new ByteArrayInputStream(s.toString().getBytes()); + }catch(IOException e){ + throw e; + } + } + + /* + * Uncompress the gzipSteam before to parse it with SAX + * In the case of no "Content-Encoding:gzip" headers is found, the + * + */ + @Override + public Document getResponseBodyAsDocument() throws IOException { + if(!isResponseGzipped() ) return super.getResponseBodyAsDocument(); + + //@TOdo: look for potential optimisation like pipe gzipInputStream directly in InputStream in + StringBuilder s = new StringBuilder(); + String line; + try{ + GZIPInputStream gzipis = new GZIPInputStream(getResponseBodyAsStream()); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipis)); + + while ((line = bufferedReader.readLine()) != null) { + s.append(line); + } + bufferedReader.close(); + + }catch(IOException e){ + throw e; + } + + InputStream in = new ByteArrayInputStream(s.toString().getBytes()); + if (in != null) { + // read response and try to build a xml document + try { + return DomUtil.parseDocument(in); + } catch (ParserConfigurationException e) { + IOException exception = + new IOException("XML parser configuration error"); + exception.initCause(e); + throw exception; + } catch (SAXException e) { + IOException exception = new IOException("XML parsing error"); + exception.initCause(e); + throw exception; + } finally { + in.close(); + } + } + // no body or no parseable. + return null; + } + + public GzipedPropfind(String uri, DavPropertyNameSet propNameSet, int depth) throws IOException { + super(uri, propNameSet, depth); + } + + public GzipedPropfind(String uri, int propfindType, int depth) throws IOException { + super(uri, propfindType, depth); + } + + public GzipedPropfind(String uri, int propfindType, DavPropertyNameSet propNameSet, int depth) throws IOException { + super(uri, propfindType, propNameSet, depth); + } +} diff --git a/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/GetRemoteUserInfoOperation.java b/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/GetRemoteUserInfoOperation.java new file mode 100644 index 0000000000000000000000000000000000000000..6077c60e65f168e8ca9497337210595e691f7f82 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/GetRemoteUserInfoOperation.java @@ -0,0 +1,142 @@ +package foundation.e.drive.utils.ncLib.resources.users; +import android.text.TextUtils; + +import com.nextcloud.android.lib.resources.profile.HoverCard; +import com.owncloud.android.lib.common.OwnCloudBasicCredentials; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.Quota; +import com.owncloud.android.lib.common.UserInfo; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.ocs.ServerResponse; +//import com.owncloud.android.lib.resources.OCSRemoteOperation; +import com.owncloud.android.lib.resources.status.OwnCloudVersion; +import com.squareup.moshi.Types; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; + +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; + +public class GetRemoteUserInfoOperation extends OCSRemoteOperation { + + private static final String TAG = GetRemoteUserInfoOperation.class.getSimpleName(); + + // OCS Route + private static final String OCS_ROUTE_SELF = "/ocs/v1.php/cloud/user"; + private static final String OCS_ROUTE_SEARCH = "/ocs/v1.php/cloud/users/"; + + /** + * Quota return value for a not computed space value. + */ + public static final long SPACE_NOT_COMPUTED = -1; + + /** + * Quota return value for unknown space value. + */ + public static final long SPACE_UNKNOWN = -2; + + /** + * Quota return value for unlimited space. + */ + public static final long SPACE_UNLIMITED = -3; + + /** + * Quota return value for quota information not available. + */ + public static final long QUOTA_LIMIT_INFO_NOT_AVAILABLE = Long.MIN_VALUE; + + private String userID; + + public GetRemoteUserInfoOperation() { + } + + public GetRemoteUserInfoOperation(String userID) { + this.userID = userID; + } + + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + int status = -1; + GetMethod get = null; + +// OwnCloudVersion version = client.getOwnCloudVersion(); +// boolean versionWithSelfAPI = version != null && version.isSelfSupported(); + + String url = ""; + + if (!TextUtils.isEmpty(userID)) { + url = client.getBaseUri() + OCS_ROUTE_SEARCH + userID; + } else { + url = client.getBaseUri() + OCS_ROUTE_SELF; + } + + + OwnCloudBasicCredentials credentials = (OwnCloudBasicCredentials) client.getCredentials(); + + //Get the user + try { + + get = new GetMethod(url); + get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + get.setQueryString(new NameValuePair[]{new NameValuePair("format", "json")}); + status = client.executeMethod(get); +// val hoverCard: HoverCard = getServerResponse>( +// getMethod, +// object : TypeToken?>() {} +// ) + if (isSuccess(status)) { + ServerResponse ocsResponse = (ServerResponse) getServerResponse(get, Types.newParameterizedType(ServerResponse.class, UserInfo.class)); + + UserInfo userInfo = ocsResponse.getOcs().getData(); + + if (userInfo.getId() == null) { + if (TextUtils.isEmpty(userID)) + userInfo.setId(credentials.getUsername()); + else + userInfo.setId(userID); + } + + if (userInfo.getQuota() == null) { + userInfo.setQuota(new Quota()); + userInfo.getQuota().setQuota(QUOTA_LIMIT_INFO_NOT_AVAILABLE); + } + + if (userInfo.getQuota().getQuota() == 0) { + userInfo.getQuota().setQuota(QUOTA_LIMIT_INFO_NOT_AVAILABLE); + } + + result = new RemoteOperationResult(true, get); + // Username in result.data + ArrayList data = new ArrayList<>(); + data.add(userInfo); + result.setData(data); + } else { + result = new RemoteOperationResult(false, get); + String response = get.getResponseBodyAsString(); + Log_OC.e(TAG, "Failed response while getting user information "); + if (response != null) { + Log_OC.e(TAG, "*** status code: " + status + " ; response message: " + response); + } else { + Log_OC.e(TAG, "*** status code: " + status); + } + } + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log_OC.e(TAG, "Exception while getting OC user information", e); + } finally { + if (get != null) { + get.releaseConnection(); + } + } + return result; + } + + + private boolean isSuccess(int status) { + return (status == HttpStatus.SC_OK); + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/OCSRemoteOperation.java b/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/OCSRemoteOperation.java new file mode 100644 index 0000000000000000000000000000000000000000..6e2001ccf1800f0605fda778ce7ac467393bf1e5 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/utils/ncLib/resources/users/OCSRemoteOperation.java @@ -0,0 +1,59 @@ +/* Nextcloud Android Library is available under MIT license + * + * @author Bartosz Przybylski + * Copyright (C) 2018 Bartosz Przybylski + * Copyright (C) 2018 Nextcloud GmbH + * Copyright (C) 2018 Vincent Bourgmayer (/e/ foundation) + * + * 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 foundation.e.drive.utils.ncLib.resources.users; + +import com.owncloud.android.lib.common.UserInfo; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.ocs.ServerResponse; +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.Moshi; + +import org.apache.commons.httpclient.HttpMethodBase; + +import java.io.IOException; +import java.lang.reflect.Type; + +/** + * + * Base class for OCS remote operations with convenient methods + * + * @author Bartosz Przybylski + */ +public abstract class OCSRemoteOperation extends RemoteOperation { + + public ServerResponse getServerResponse(HttpMethodBase method, Type type) throws IOException { + String response = method.getResponseBodyAsString(); + + Moshi moshi = new Moshi.Builder().build(); + JsonAdapter> jsonAdapter = moshi.adapter(type); + + return jsonAdapter.fromJson(response); + + } +} diff --git a/build.gradle b/build.gradle index 3378f0cd90a587b6f781e45f221ba00f97f51ebf..3aa50def518a5dc2a02f5d64affa007e14756150 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.6.0-RC2' repositories { google() @@ -8,6 +9,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.1.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -19,6 +21,7 @@ allprojects { repositories { google() jcenter() + maven { url "https://jitpack.io" } } } diff --git a/gradle.properties b/gradle.properties index aac7c9b4614ccfde6c721f24994cf30885a791d0..f6faafa8e6aa7e0f76ef2d857411a3698b43d0a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,16 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit +## For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html - +# # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m - +# Default value: -Xmx1024m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true +#Mon Nov 08 18:56:33 IST 2021 +org.gradle.jvmargs=-Xmx1536m +android.useAndroidX=true +android.enableJetifier=true diff --git a/nextcloud-android-lib b/nextcloud-android-lib deleted file mode 160000 index 353568a74c0708496b36614b3ff69b9fafe9af0b..0000000000000000000000000000000000000000 --- a/nextcloud-android-lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 353568a74c0708496b36614b3ff69b9fafe9af0b