Skip to content

Commit 9dcefff

Browse files
committed
fix(session-mixing): capabilities npe
Signed-off-by: alperozturk96 <alper_ozturk@proton.me> # Conflicts: # app/src/main/java/com/nextcloud/ui/composeActivity/ComposeActivity.kt # app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java # app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.kt
1 parent e7e15b6 commit 9dcefff

8 files changed

Lines changed: 105 additions & 46 deletions

File tree

app/src/androidTest/java/com/owncloud/android/ui/dialog/DialogFragmentIT.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import com.owncloud.android.utils.theme.CapabilityUtils
7272
import com.owncloud.android.utils.theme.ViewThemeUtils
7373
import io.mockk.mockk
7474
import org.junit.After
75+
import org.junit.Assert.fail
7576
import org.junit.Rule
7677
import org.junit.Test
7778
import java.net.URI
@@ -490,7 +491,12 @@ class DialogFragmentIT : AbstractIT() {
490491
json
491492
)
492493

493-
val capability = fda.capabilities.apply {
494+
val optionalCapability = fda.capabilities
495+
if (optionalCapability.isEmpty) {
496+
fail("capabilities is empty")
497+
}
498+
499+
val capability = optionalCapability.get().apply {
494500
richDocuments = CapabilityBooleanType.TRUE
495501
richDocumentsDirectEditing = CapabilityBooleanType.TRUE
496502
richDocumentsTemplatesAvailable = CapabilityBooleanType.TRUE

app/src/main/java/com/nextcloud/client/mixins/SessionMixin.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import android.os.Bundle
1414
import com.nextcloud.client.account.User
1515
import com.nextcloud.client.account.UserAccountManager
1616
import com.nextcloud.utils.extensions.isAnonymous
17+
import com.owncloud.android.lib.common.utils.Log_OC
1718
import com.owncloud.android.lib.resources.status.OCCapability
1819
import com.owncloud.android.utils.theme.CapabilityUtils
1920
import java.util.Optional
@@ -29,10 +30,21 @@ class SessionMixin(private val activity: Activity, private val accountManager: U
2930
var currentAccount: Account = getDefaultAccount()
3031
private set
3132

32-
val capabilities: OCCapability?
33-
get() = getUser()
34-
.map { CapabilityUtils.getCapability(it, activity) }
35-
.orElse(null)
33+
companion object {
34+
private const val TAG = "SessionMixin"
35+
}
36+
37+
fun getCapabilities(): Optional<OCCapability> {
38+
val optionalUser = getUser()
39+
if (optionalUser.isEmpty) {
40+
Log_OC.e(TAG, "user is empty, returning empty capabilities")
41+
return Optional.empty()
42+
}
43+
44+
val user = optionalUser.get()
45+
val capability = CapabilityUtils.getCapability(user, activity)
46+
return Optional.of(capability)
47+
}
3648

3749
fun setAccount(account: Account) {
3850
val validAccount = (accountManager.setCurrentOwnCloudAccount(account.name))

app/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ protected void startAccountCreation() {
164164
* @return Capabilities of the server where the current OC account lives. Null if the account is not
165165
* set yet.
166166
*/
167-
public OCCapability getCapabilities() {
167+
public Optional<OCCapability> getCapabilities() {
168168
return sessionMixin.getCapabilities();
169169
}
170170

app/src/main/java/com/owncloud/android/ui/activity/FileActivity.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
8989
import com.owncloud.android.ui.events.DialogEvent;
9090
import com.owncloud.android.ui.events.DialogEventType;
91-
import com.owncloud.android.ui.events.FavoriteEvent;
9291
import com.owncloud.android.ui.fragment.FileDetailFragment;
9392
import com.owncloud.android.ui.fragment.FileDetailSharingFragment;
9493
import com.owncloud.android.ui.fragment.OCFileListFragment;
@@ -887,20 +886,20 @@ private void onCreateShareViaLinkOperationFinish(CreateShareViaLinkOperation ope
887886
} else {
888887
// Detect Failure (403) --> maybe needs password
889888
String password = operation.getPassword();
890-
if (result.getCode() == RemoteOperationResult.ResultCode.SHARE_FORBIDDEN &&
891-
TextUtils.isEmpty(password) &&
892-
getCapabilities().getFilesSharingPublicEnabled().isUnknown()) {
893-
// Was tried without password, but not sure that it's optional.
894-
895-
// Try with password before giving up; see also ShareFileFragment#OnShareViaLinkListener
896-
if (sharingFragment != null && sharingFragment.isAdded()) {
897-
// only if added to the view hierarchy
898-
899-
sharingFragment.requestPasswordForShareViaLink(true,
900-
getCapabilities().getFilesSharingPublicAskForOptionalPassword()
901-
.isTrue());
889+
final var optionalCapabilities = getCapabilities();
890+
891+
if (result.getCode() == RemoteOperationResult.ResultCode.SHARE_FORBIDDEN && TextUtils.isEmpty(password)) {
892+
if (optionalCapabilities.isPresent()) {
893+
final var capabilities = optionalCapabilities.get();
894+
if (capabilities.getFilesSharingPublicEnabled().isUnknown()) {
895+
// Was tried without password, but not sure that it's optional.
896+
// Try with password before giving up; see also ShareFileFragment#OnShareViaLinkListener
897+
if (sharingFragment != null && sharingFragment.isAdded()) {
898+
// only if added to the view hierarchy
899+
sharingFragment.requestPasswordForShareViaLink(true, capabilities.getFilesSharingPublicAskForOptionalPassword().isTrue());
900+
}
901+
}
902902
}
903-
904903
} else {
905904
if (sharingFragment != null) {
906905
sharingFragment.refreshSharesFromDB();

app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -448,13 +448,16 @@ class FileDisplayActivity :
448448

449449
private fun checkOutdatedServer() {
450450
val user = getUser()
451+
val optionalCapability = capabilities
452+
451453
// show outdated warning
452454
if (user.isPresent &&
455+
optionalCapability.isPresent &&
453456
CapabilityUtils.checkOutdatedWarning(
454457
getResources(),
455458
user.get().server.version,
456-
capabilities.extendedSupport.isTrue,
457-
capabilities.hasValidSubscription.isTrue
459+
optionalCapability.get().extendedSupport.isTrue,
460+
optionalCapability.get().hasValidSubscription.isTrue
458461
)
459462
) {
460463
DisplayUtils.showServerOutdatedSnackbar(this, Snackbar.LENGTH_LONG)
@@ -1084,28 +1087,38 @@ class FileDisplayActivity :
10841087

10851088
connectivityService.isNetworkAndServerAvailable { result: Boolean? ->
10861089
if (result == true) {
1087-
val isValidFolderPath = remotePathBase?.let { checkFolderPath(it, capabilities, this) }
1088-
if (isValidFolderPath == false) {
1089-
DisplayUtils.showSnackMessage(
1090-
this,
1091-
R.string.file_name_validator_error_contains_reserved_names_or_invalid_characters
1090+
val optionalCapabilities = capabilities
1091+
if (optionalCapabilities.isPresent) {
1092+
val isValidFolderPath =
1093+
remotePathBase?.let {
1094+
checkFolderPath(
1095+
it,
1096+
optionalCapabilities.get(),
1097+
this
1098+
)
1099+
}
1100+
if (isValidFolderPath == false) {
1101+
DisplayUtils.showSnackMessage(
1102+
this,
1103+
R.string.file_name_validator_error_contains_reserved_names_or_invalid_characters
1104+
)
1105+
return@isNetworkAndServerAvailable
1106+
}
1107+
1108+
FileUploadHelper.instance().uploadNewFiles(
1109+
user.orElseThrow(
1110+
Supplier { RuntimeException() }
1111+
),
1112+
filePaths,
1113+
decryptedRemotePaths,
1114+
behaviour,
1115+
true,
1116+
UploadFileOperation.CREATED_BY_USER,
1117+
false,
1118+
false,
1119+
NameCollisionPolicy.ASK_USER
10921120
)
1093-
return@isNetworkAndServerAvailable
10941121
}
1095-
1096-
FileUploadHelper.Companion.instance().uploadNewFiles(
1097-
user.orElseThrow(
1098-
Supplier { RuntimeException() }
1099-
),
1100-
filePaths,
1101-
decryptedRemotePaths,
1102-
behaviour,
1103-
true,
1104-
UploadFileOperation.CREATED_BY_USER,
1105-
false,
1106-
false,
1107-
NameCollisionPolicy.ASK_USER
1108-
)
11091122
} else {
11101123
fileDataStorageManager.addCreateFileOfflineOperation(filePaths, decryptedRemotePaths)
11111124
}
@@ -2450,7 +2463,12 @@ class FileDisplayActivity :
24502463
}
24512464

24522465
private fun fetchRecommendedFilesIfNeeded(ignoreETag: Boolean, folder: OCFile?) {
2453-
if (folder?.isRootDirectory == false || capabilities == null || capabilities.recommendations.isFalse) {
2466+
val optionalCapabilities = capabilities
2467+
if (optionalCapabilities.isEmpty) {
2468+
return
2469+
}
2470+
2471+
if (folder?.isRootDirectory == false || optionalCapabilities.get().recommendations.isFalse) {
24542472
return
24552473
}
24562474

app/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,24 @@ open class FolderPickerActivity :
376376
updateNavigationElementsInActionBar()
377377
}
378378

379+
@Suppress("ReturnCount")
379380
private fun toggleChooseEnabled() {
380381
if (this is FilePickerActivity) {
381382
return
382383
}
383384

384385
val selectedFolderPathTitle = getSelectedFolderPathTitle()
386+
val optionalCapabilities = capabilities
387+
if (optionalCapabilities.isEmpty) {
388+
return
389+
}
390+
385391
val isFolderPathValid = if (selectedFolderPathTitle != null) {
386-
FileNameValidator.checkFolderPath(selectedFolderPathTitle, capabilities, this)
392+
FileNameValidator.checkFolderPath(
393+
selectedFolderPathTitle,
394+
optionalCapabilities.get(),
395+
this
396+
)
387397
} else {
388398
true
389399
}

app/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,12 @@ public void onSortingOrderChosen(FileSortOrder newSortOrder) {
310310
@Override
311311
public void selectFile(OCFile file) {
312312
if (file.isFolder()) {
313-
String filenameErrorMessage = FileNameValidator.INSTANCE.checkFileName(file.getFileName(), getCapabilities(), this, null);
313+
final var optionalCapabilities = getCapabilities();
314+
if (optionalCapabilities.isEmpty()) {
315+
return;
316+
}
317+
318+
String filenameErrorMessage = FileNameValidator.INSTANCE.checkFileName(file.getFileName(), optionalCapabilities.get(), this, null);
314319
if (filenameErrorMessage != null) {
315320
DisplayUtils.showSnackMessage(this, filenameErrorMessage);
316321
return;

app/src/main/java/com/owncloud/android/ui/asynctasks/FetchRemoteFileTask.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.owncloud.android.datamodel.OCFile;
1919
import com.owncloud.android.lib.common.operations.RemoteOperation;
2020
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
21+
import com.owncloud.android.lib.common.utils.Log_OC;
2122
import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation;
2223
import com.owncloud.android.lib.resources.files.SearchRemoteOperation;
2324
import com.owncloud.android.lib.resources.files.model.RemoteFile;
@@ -28,6 +29,7 @@
2829
import static com.owncloud.android.lib.resources.files.SearchRemoteOperation.SearchType.FILE_ID_SEARCH;
2930

3031
public class FetchRemoteFileTask extends AsyncTask<Void, Void, String> {
32+
private static final String TAG = "FetchRemoteFileTask";
3133
private final User user;
3234
private final String fileId;
3335
private final FileDataStorageManager storageManager;
@@ -46,10 +48,17 @@ public FetchRemoteFileTask(User user,
4648

4749
@Override
4850
protected String doInBackground(Void... voids) {
51+
final var optionalCapabilities = fileDisplayActivity.getCapabilities();
52+
if (optionalCapabilities.isEmpty()) {
53+
Log_OC.e(TAG, "cannot fetch remote file capability is null");
54+
return "";
55+
}
56+
57+
4958
SearchRemoteOperation searchRemoteOperation = new SearchRemoteOperation(fileId,
5059
FILE_ID_SEARCH,
5160
false,
52-
fileDisplayActivity.getCapabilities());
61+
optionalCapabilities.get());
5362
RemoteOperationResult remoteOperationResult = searchRemoteOperation.execute(user, fileDisplayActivity);
5463

5564
if (remoteOperationResult.isSuccess() && remoteOperationResult.getData() != null) {

0 commit comments

Comments
 (0)