Merge remote-tracking branch 'origin/master' into dev
2
.github/workflows/analysis.yml
vendored
|
@ -33,7 +33,7 @@ jobs:
|
|||
echo "pr=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
|
||||
echo "repo=${{ github.event.pull_request.head.repo.full_name }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
repository: ${{ steps.get-vars.outputs.repo }}
|
||||
ref: ${{ steps.get-vars.outputs.branch }}
|
||||
|
|
2
.github/workflows/codeql.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
|||
language: [ 'java' ]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- name: Set Swap Space
|
||||
uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0
|
||||
with:
|
||||
|
|
|
@ -18,5 +18,5 @@ jobs:
|
|||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # v1.1.0
|
||||
|
|
2
.github/workflows/scorecard.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
16
README.md
|
@ -15,11 +15,17 @@ height="80">](https://f-droid.org/packages/com.nextcloud.client/)
|
|||
|
||||
## How to contribute :rocket:
|
||||
|
||||
If you want to [contribute](https://nextcloud.com/contribute/) to Nextcloud, you are very welcome:
|
||||
If you want to [contribute](https://nextcloud.com/contribute/) to the Nextcloud Android client app, there are many ways to help whether or not you are a coder:
|
||||
|
||||
* our forum at https://help.nextcloud.com
|
||||
* for translations of the app on [Transifex](https://app.transifex.com/nextcloud/nextcloud/android/)
|
||||
* opening issues and PRs (including a corresponding issue)
|
||||
* helping out other users on our forum at https://help.nextcloud.com
|
||||
* providing translations of the app on [Transifex](https://app.transifex.com/nextcloud/nextcloud/android/)
|
||||
* reporting problems / suggesting enhancements by [opening new issues](https://github.com/nextcloud/android/issues/new/choose)
|
||||
* implementing proposed bug fixes and enhancement ideas by submitting PRs (associated with a corresponding issue preferably)
|
||||
* reviewing [pull requests](https://github.com/nextcloud/android/pulls) and providing feedback on code, implementation, and functionality
|
||||
* installing and testing [pull request builds](https://github.com/nextcloud/android/pulls), [daily/dev builds](https://github.com/nextcloud/android#development-version-hammer), or [RCs/release candidate builds](https://github.com/nextcloud/android/releases)
|
||||
* enhancing Admin, User, or Developer [documentation](https://github.com/nextcloud/documentation/)
|
||||
* hitting hard on the latest stable release by testing fundamental features and evaluating the user experience
|
||||
* proactively getting familiar with [how to gather debug logs](https://github.com/nextcloud/android#getting-debug-info-via-logcat-mag) from your devices (so that you are prepared to provide a detailed report if you encounter a problem with the app in the future)
|
||||
|
||||
## Contribution Guidelines & License :scroll:
|
||||
|
||||
|
@ -38,7 +44,7 @@ More information on how to contribute: <https://nextcloud.com/contribute/>
|
|||
## Start contributing :hammer\_and\_wrench:
|
||||
|
||||
Make sure you read [SETUP.md](https://github.com/nextcloud/android/blob/master/SETUP.md) and [CONTRIBUTING.md](https://github.com/nextcloud/android/blob/master/CONTRIBUTING.md) before you start working on this project. But basically: fork this repository and contribute back using pull requests to the master branch.
|
||||
Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/android/pulls) and working on [starter issues](https://github.com/nextcloud/android/issues?q=is%3Aopen+is%3Aissue+label%3A%22starter+issue%22).
|
||||
Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/android/pulls) and working on [starter issues](https://github.com/nextcloud/android/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
||||
|
||||
### Getting debug info via logcat :mag:
|
||||
|
||||
|
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 14 KiB |
|
@ -25,6 +25,7 @@ package com.owncloud.android.ui.dialog;
|
|||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
|
@ -59,7 +60,11 @@ public class AccountRemovalConfirmationDialog extends DialogFragment implements
|
|||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
user = getArguments().getParcelable(KEY_USER);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
user = arguments.getParcelable(KEY_USER);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,9 +72,18 @@ public class AccountRemovalConfirmationDialog extends DialogFragment implements
|
|||
super.onStart();
|
||||
|
||||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
if (alertDialog != null) {
|
||||
|
||||
viewThemeUtils.platform.colorTextButtons(alertDialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
|
||||
MaterialButton positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
if (positiveButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
|
||||
}
|
||||
|
||||
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
|
||||
if (negativeButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -82,7 +96,7 @@ public class AccountRemovalConfirmationDialog extends DialogFragment implements
|
|||
.setPositiveButton(R.string.common_ok,
|
||||
(dialogInterface, i) -> backgroundJobManager.startAccountRemovalJob(user.getAccountName(),
|
||||
false))
|
||||
.setNeutralButton(R.string.common_cancel, null);
|
||||
.setNegativeButton(R.string.common_cancel, null);
|
||||
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(requireActivity(), builder);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.nextcloud.client.account.CurrentAccountProvider;
|
||||
|
@ -99,7 +100,7 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
private RichDocumentsTemplateAdapter adapter;
|
||||
private OCFile parentFolder;
|
||||
private OwnCloudClient client;
|
||||
private Button positiveButton;
|
||||
private MaterialButton positiveButton;
|
||||
private DialogFragment waitDialog;
|
||||
|
||||
public enum Type {
|
||||
|
@ -126,11 +127,18 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
|
||||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
|
||||
positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
viewThemeUtils.platform.colorTextButtons(positiveButton,
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
|
||||
positiveButton.setOnClickListener(this);
|
||||
positiveButton.setEnabled(false);
|
||||
if (alertDialog != null) {
|
||||
positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
|
||||
|
||||
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
|
||||
if (negativeButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
|
||||
}
|
||||
|
||||
positiveButton.setOnClickListener(this);
|
||||
positiveButton.setEnabled(false);
|
||||
}
|
||||
|
||||
checkEnablingCreateButton();
|
||||
}
|
||||
|
@ -205,12 +213,14 @@ public class ChooseRichDocumentsTemplateDialogFragment extends DialogFragment im
|
|||
}
|
||||
});
|
||||
|
||||
int titleTextId = getTitle(type);
|
||||
|
||||
// Build the dialog
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity);
|
||||
builder.setView(view)
|
||||
.setPositiveButton(R.string.create, null)
|
||||
.setNeutralButton(R.string.common_cancel, null)
|
||||
.setTitle(getTitle(type));
|
||||
.setNegativeButton(R.string.common_cancel, null)
|
||||
.setTitle(titleTextId);
|
||||
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(activity, builder);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import android.os.Bundle;
|
|||
import android.text.format.DateUtils;
|
||||
import android.widget.DatePicker;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils;
|
||||
|
@ -81,12 +82,24 @@ public class ExpirationDatePickerDialogFragment
|
|||
public void onStart() {
|
||||
super.onStart();
|
||||
final Dialog currentDialog = getDialog();
|
||||
|
||||
if (currentDialog != null) {
|
||||
final DatePickerDialog dialog = (DatePickerDialog) currentDialog;
|
||||
|
||||
viewThemeUtils.platform.colorTextButtons(dialog.getButton(DatePickerDialog.BUTTON_NEUTRAL),
|
||||
dialog.getButton(DatePickerDialog.BUTTON_NEGATIVE),
|
||||
dialog.getButton(DatePickerDialog.BUTTON_POSITIVE));
|
||||
MaterialButton positiveButton = (MaterialButton) dialog.getButton(DatePickerDialog.BUTTON_POSITIVE);
|
||||
if (positiveButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
|
||||
}
|
||||
|
||||
MaterialButton negativeButton = (MaterialButton) dialog.getButton(DatePickerDialog.BUTTON_NEGATIVE);
|
||||
if (negativeButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
|
||||
}
|
||||
|
||||
MaterialButton neutralButton = (MaterialButton) dialog.getButton(DatePickerDialog.BUTTON_NEUTRAL);
|
||||
if (neutralButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(neutralButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +131,7 @@ public class ExpirationDatePickerDialogFragment
|
|||
//show unset button only when date is already selected
|
||||
if (chosenDateInMillis > 0) {
|
||||
dialog.setButton(
|
||||
Dialog.BUTTON_NEUTRAL,
|
||||
Dialog.BUTTON_NEGATIVE,
|
||||
getText(R.string.share_via_link_unset_password),
|
||||
(dialog1, which) -> {
|
||||
if (onExpiryDateListener != null) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.app.Dialog;
|
|||
import android.os.Bundle;
|
||||
import android.view.ActionMode;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
|
@ -96,15 +97,20 @@ public class RemoveFilesDialogFragment extends ConfirmationDialogFragment implem
|
|||
R.string.confirmation_remove_files_alert;
|
||||
}
|
||||
|
||||
int localRemoveButton = (containsFolder || containsDown) ? R.string.confirmation_remove_local : -1;
|
||||
|
||||
args.putInt(ARG_MESSAGE_RESOURCE_ID, messageStringId);
|
||||
if (files.size() == SINGLE_SELECTION) {
|
||||
args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[]{files.get(0).getFileName()});
|
||||
args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[] { files.get(0).getFileName() } );
|
||||
}
|
||||
|
||||
args.putInt(ARG_POSITIVE_BTN_RES, R.string.file_delete);
|
||||
args.putInt(ARG_NEUTRAL_BTN_RES, R.string.file_keep);
|
||||
args.putInt(ARG_NEGATIVE_BTN_RES, localRemoveButton);
|
||||
|
||||
if (containsFolder || containsDown) {
|
||||
args.putInt(ARG_NEGATIVE_BTN_RES, R.string.confirmation_remove_local);
|
||||
args.putInt(ARG_NEUTRAL_BTN_RES, R.string.file_keep);
|
||||
} else {
|
||||
args.putInt(ARG_NEGATIVE_BTN_RES, R.string.file_keep);
|
||||
}
|
||||
|
||||
args.putParcelableArrayList(ARG_TARGET_FILES, files);
|
||||
frag.setArguments(args);
|
||||
|
||||
|
@ -131,9 +137,16 @@ public class RemoveFilesDialogFragment extends ConfirmationDialogFragment implem
|
|||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
|
||||
if (alertDialog != null) {
|
||||
viewThemeUtils.platform.colorTextButtons(alertDialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE),
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
|
||||
MaterialButton positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
|
||||
|
||||
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
|
||||
|
||||
MaterialButton neutralButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
|
||||
if (neutralButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(neutralButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,10 +154,14 @@ public class RemoveFilesDialogFragment extends ConfirmationDialogFragment implem
|
|||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
mTargetFiles = getArguments().getParcelableArrayList(ARG_TARGET_FILES);
|
||||
Bundle arguments = getArguments();
|
||||
|
||||
if (arguments == null) {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
mTargetFiles = arguments.getParcelableArrayList(ARG_TARGET_FILES);
|
||||
setOnConfirmationListener(this);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
@ -154,9 +171,7 @@ public class RemoveFilesDialogFragment extends ConfirmationDialogFragment implem
|
|||
*/
|
||||
@Override
|
||||
public void onConfirmation(String callerTag) {
|
||||
ComponentsGetter cg = (ComponentsGetter) getActivity();
|
||||
cg.getFileOperationsHelper().removeFiles(mTargetFiles, false, false);
|
||||
finishActionMode();
|
||||
removeFiles(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,8 +179,14 @@ public class RemoveFilesDialogFragment extends ConfirmationDialogFragment implem
|
|||
*/
|
||||
@Override
|
||||
public void onCancel(String callerTag) {
|
||||
removeFiles(true);
|
||||
}
|
||||
|
||||
private void removeFiles(boolean onlyLocalCopy) {
|
||||
ComponentsGetter cg = (ComponentsGetter) getActivity();
|
||||
cg.getFileOperationsHelper().removeFiles(mTargetFiles, true, false);
|
||||
if (cg != null) {
|
||||
cg.getFileOperationsHelper().removeFiles(mTargetFiles, onlyLocalCopy, false);
|
||||
}
|
||||
finishActionMode();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.text.TextUtils;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.owncloud.android.R;
|
||||
|
@ -52,8 +53,6 @@ public class RenamePublicShareDialogFragment
|
|||
|
||||
private static final String ARG_PUBLIC_SHARE = "PUBLIC_SHARE";
|
||||
|
||||
public static final String RENAME_PUBLIC_SHARE_FRAGMENT = "RENAME_PUBLIC_SHARE_FRAGMENT";
|
||||
|
||||
@Inject ViewThemeUtils viewThemeUtils;
|
||||
@Inject KeyboardUtils keyboardUtils;
|
||||
|
||||
|
@ -75,8 +74,10 @@ public class RenamePublicShareDialogFragment
|
|||
AlertDialog alertDialog = (AlertDialog) getDialog();
|
||||
|
||||
if (alertDialog != null) {
|
||||
viewThemeUtils.platform.colorTextButtons(alertDialog.getButton(AlertDialog.BUTTON_POSITIVE),
|
||||
alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL));
|
||||
MaterialButton positiveButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
MaterialButton negativeButton = (MaterialButton) alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton);
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +105,7 @@ public class RenamePublicShareDialogFragment
|
|||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(view.getContext());
|
||||
builder.setView(view)
|
||||
.setPositiveButton(R.string.file_rename, this)
|
||||
.setNeutralButton(R.string.common_cancel, this)
|
||||
.setNegativeButton(R.string.common_cancel, this)
|
||||
.setTitle(R.string.public_share_name);
|
||||
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.userInput.getContext(), builder);
|
||||
|
|
|
@ -1,329 +0,0 @@
|
|||
/**
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author David A. Velasco
|
||||
* Copyright (C) 2015 ownCloud Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.databinding.SslValidatorLayoutBinding;
|
||||
import com.owncloud.android.lib.common.network.CertificateCombinedException;
|
||||
import com.owncloud.android.lib.common.network.NetworkUtils;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
/**
|
||||
* Dialog to request the user about a certificate that could not be validated with the certificates store in the system.
|
||||
*/
|
||||
public class SslValidatorDialog extends Dialog {
|
||||
|
||||
private final static String TAG = SslValidatorDialog.class.getSimpleName();
|
||||
|
||||
private OnSslValidatorListener mListener;
|
||||
private CertificateCombinedException mException;
|
||||
private SslValidatorLayoutBinding binding;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new SslValidatorDialog to ask the user if an untrusted certificate from a server should
|
||||
* be trusted.
|
||||
*
|
||||
* @param context Android context where the dialog will live.
|
||||
* @param result Result of a failed remote operation.
|
||||
* @param listener Object to notice when the server certificate was added to the local certificates store.
|
||||
* @return A new SslValidatorDialog instance. NULL if the operation can not be recovered
|
||||
* by setting the certificate as reliable.
|
||||
*/
|
||||
public static SslValidatorDialog newInstance(Context context, RemoteOperationResult result, OnSslValidatorListener listener) {
|
||||
if (result != null && result.isSslRecoverableException()) {
|
||||
return new SslValidatorDialog(context, listener);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
* Instances have to be created through static {@link SslValidatorDialog#newInstance}.
|
||||
*
|
||||
* @param context Android context where the dialog will live
|
||||
* @param listener Object to notice when the server certificate was added to the local certificates store.
|
||||
*/
|
||||
private SslValidatorDialog(Context context, OnSslValidatorListener listener) {
|
||||
super(context);
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
binding = SslValidatorLayoutBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
binding.ok.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
saveServerCert();
|
||||
dismiss();
|
||||
if (mListener != null) {
|
||||
mListener.onSavedCertificate();
|
||||
} else {
|
||||
Log_OC.d(TAG, "Nobody there to notify the certificate was saved");
|
||||
}
|
||||
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
dismiss();
|
||||
if (mListener != null) {
|
||||
mListener.onFailedSavingCertificate();
|
||||
}
|
||||
Log_OC.e(TAG, "Server certificate could not be saved in the known servers trust store ", e);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
binding.cancel.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
cancel();
|
||||
}
|
||||
});
|
||||
|
||||
binding.detailsBtn.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
View detailsScroll = findViewById(R.id.details_scroll);
|
||||
if (detailsScroll.getVisibility() == View.VISIBLE) {
|
||||
detailsScroll.setVisibility(View.GONE);
|
||||
((Button) v).setText(R.string.ssl_validator_btn_details_see);
|
||||
} else {
|
||||
detailsScroll.setVisibility(View.VISIBLE);
|
||||
((Button) v).setText(R.string.ssl_validator_btn_details_hide);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void updateResult(RemoteOperationResult result) {
|
||||
if (result.isSslRecoverableException()) {
|
||||
mException = (CertificateCombinedException) result.getException();
|
||||
|
||||
/// clean
|
||||
binding.reasonCertNotTrusted.setVisibility(View.GONE);
|
||||
binding.reasonCertExpired.setVisibility(View.GONE);
|
||||
binding.reasonCertNotYetValid.setVisibility(View.GONE);
|
||||
binding.reasonHostnameNotVerified.setVisibility(View.GONE);
|
||||
binding.detailsScroll.setVisibility(View.GONE);
|
||||
|
||||
/// refresh
|
||||
if (mException.getCertPathValidatorException() != null) {
|
||||
binding.reasonCertNotTrusted.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (mException.getCertificateExpiredException() != null) {
|
||||
binding.reasonCertExpired.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (mException.getCertificateNotYetValidException() != null) {
|
||||
binding.reasonCertNotYetValid.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (mException.getSslPeerUnverifiedException() != null ) {
|
||||
binding.reasonHostnameNotVerified.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
showCertificateData(mException.getServerCertificate());
|
||||
}
|
||||
}
|
||||
|
||||
private void showCertificateData(X509Certificate cert) {
|
||||
|
||||
if (cert != null) {
|
||||
showSubject(cert.getSubjectX500Principal());
|
||||
showIssuer(cert.getIssuerX500Principal());
|
||||
showValidity(cert.getNotBefore(), cert.getNotAfter());
|
||||
showSignature(cert);
|
||||
|
||||
} else {
|
||||
// this should not happen, TODO
|
||||
Log_OC.d("certNull", "This should not happen");
|
||||
}
|
||||
}
|
||||
|
||||
private void showSignature(X509Certificate cert) {
|
||||
binding.valueSignature.setText(getHex(cert.getSignature()));
|
||||
binding.valueSignatureAlgorithm.setText(cert.getSigAlgName());
|
||||
}
|
||||
|
||||
public String getHex(final byte [] raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
final StringBuilder hex = new StringBuilder(2 * raw.length);
|
||||
for (final byte b : raw) {
|
||||
final int hiVal = (b & 0xF0) >> 4;
|
||||
final int loVal = b & 0x0F;
|
||||
hex.append((char) ('0' + (hiVal + (hiVal / 10 * 7))));
|
||||
hex.append((char) ('0' + (loVal + (loVal / 10 * 7))));
|
||||
}
|
||||
return hex.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void showValidity(Date notBefore, Date notAfter) {
|
||||
binding.valueValidityFrom.setText(notBefore.toLocaleString());
|
||||
binding.valueValidityTo.setText(notAfter.toLocaleString());
|
||||
}
|
||||
|
||||
private void showSubject(X500Principal subject) {
|
||||
Map<String, String> s = parsePrincipal(subject);
|
||||
|
||||
if (s.get("CN") != null) {
|
||||
binding.valueSubjectCN.setText(s.get("CN"));
|
||||
binding.valueSubjectCN.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectCN.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("O") != null) {
|
||||
binding.valueSubjectO.setText(s.get("O"));
|
||||
binding.valueSubjectO.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectO.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("OU") != null) {
|
||||
binding.valueSubjectOU.setText(s.get("OU"));
|
||||
binding.valueSubjectOU.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectOU.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("C") != null) {
|
||||
binding.valueSubjectC.setText(s.get("C"));
|
||||
binding.valueSubjectC.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectC.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("ST") != null) {
|
||||
binding.valueSubjectST.setText(s.get("ST"));
|
||||
binding.valueSubjectST.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectST.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("L") != null) {
|
||||
binding.valueSubjectL.setText(s.get("L"));
|
||||
binding.valueSubjectL.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueSubjectL.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showIssuer(X500Principal issuer) {
|
||||
Map<String, String> s = parsePrincipal(issuer);
|
||||
|
||||
if (s.get("CN") != null) {
|
||||
binding.valueIssuerCN.setText(s.get("CN"));
|
||||
binding.valueIssuerCN.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerCN.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("O") != null) {
|
||||
binding.valueIssuerO.setText(s.get("O"));
|
||||
binding.valueIssuerO.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerO.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("OU") != null) {
|
||||
binding.valueIssuerOU.setText(s.get("OU"));
|
||||
binding.valueIssuerOU.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerOU.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("C") != null) {
|
||||
binding.valueIssuerC.setText(s.get("C"));
|
||||
binding.valueIssuerC.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerC.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("ST") != null) {
|
||||
binding.valueIssuerST.setText(s.get("ST"));
|
||||
binding.valueIssuerST.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerST.setVisibility(View.GONE);
|
||||
}
|
||||
if (s.get("L") != null) {
|
||||
binding.valueIssuerL.setText(s.get("L"));
|
||||
binding.valueIssuerL.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.valueIssuerL.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> parsePrincipal(X500Principal principal) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
String toParse = principal.getName();
|
||||
String[] pieces = toParse.split(",");
|
||||
String[] tokens = {"CN", "O", "OU", "C", "ST", "L"};
|
||||
for (String piece : pieces) {
|
||||
for (String token : tokens) {
|
||||
if (piece.startsWith(token + "=")) {
|
||||
result.put(token, piece.substring(token.length() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void saveServerCert() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
|
||||
if (mException.getServerCertificate() != null) {
|
||||
// TODO make this asynchronously, it can take some time
|
||||
NetworkUtils.addCertToKnownServersStore(mException.getServerCertificate(), getContext());
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnSslValidatorListener {
|
||||
public void onSavedCertificate();
|
||||
public void onFailedSavingCertificate();
|
||||
}
|
||||
}
|
|
@ -24,15 +24,14 @@ import android.app.Dialog
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.nextcloud.client.di.Injectable
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.databinding.StoragePermissionDialogBinding
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import javax.inject.Inject
|
||||
|
@ -43,10 +42,7 @@ import javax.inject.Inject
|
|||
* Allows choosing "full access" (MANAGE_ALL_FILES) or "read-only media" (READ_EXTERNAL_STORAGE)
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
class StoragePermissionDialogFragment :
|
||||
DialogFragment(), Injectable {
|
||||
|
||||
private lateinit var binding: StoragePermissionDialogBinding
|
||||
class StoragePermissionDialogFragment : DialogFragment(), Injectable {
|
||||
|
||||
private var permissionRequired = false
|
||||
|
||||
|
@ -64,51 +60,48 @@ class StoragePermissionDialogFragment :
|
|||
super.onStart()
|
||||
dialog?.let {
|
||||
val alertDialog = it as AlertDialog
|
||||
viewThemeUtils.platform.colorTextButtons(alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE))
|
||||
|
||||
val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton)
|
||||
|
||||
val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
|
||||
|
||||
val neutralButton = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL) as MaterialButton
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(neutralButton)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
// Inflate the layout for the dialog
|
||||
val inflater = requireActivity().layoutInflater
|
||||
binding = StoragePermissionDialogBinding.inflate(inflater, null, false)
|
||||
|
||||
val view: View = binding.root
|
||||
val title = when {
|
||||
permissionRequired -> R.string.file_management_permission
|
||||
else -> R.string.file_management_permission_optional
|
||||
}
|
||||
val explanationResource = when {
|
||||
permissionRequired -> R.string.file_management_permission_text
|
||||
else -> R.string.file_management_permission_optional_text
|
||||
}
|
||||
binding.storagePermissionExplanation.text = getString(explanationResource, getString(R.string.app_name))
|
||||
val message = getString(explanationResource, getString(R.string.app_name))
|
||||
|
||||
// Setup layout
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.btnFullAccess)
|
||||
binding.btnFullAccess.setOnClickListener {
|
||||
setResult(Result.FULL_ACCESS)
|
||||
dismiss()
|
||||
}
|
||||
viewThemeUtils.platform.colorTextButtons(binding.btnReadOnly)
|
||||
binding.btnReadOnly.setOnClickListener {
|
||||
setResult(Result.MEDIA_READ_ONLY)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// Build the dialog
|
||||
val titleResource = when {
|
||||
permissionRequired -> R.string.file_management_permission
|
||||
else -> R.string.file_management_permission_optional
|
||||
}
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(binding.btnReadOnly.context)
|
||||
.setTitle(titleResource)
|
||||
.setView(view)
|
||||
.setNegativeButton(R.string.common_cancel) { _, _ ->
|
||||
val dialogBuilder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.storage_permission_full_access) { _, _ ->
|
||||
setResult(Result.FULL_ACCESS)
|
||||
dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.storage_permission_media_read_only) { _, _ ->
|
||||
setResult(Result.MEDIA_READ_ONLY)
|
||||
dismiss()
|
||||
}
|
||||
.setNeutralButton(R.string.common_cancel) { _, _ ->
|
||||
setResult(Result.CANCEL)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.btnReadOnly.context, builder)
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(requireContext(), dialogBuilder)
|
||||
|
||||
return builder.create()
|
||||
return dialogBuilder.create()
|
||||
}
|
||||
|
||||
private fun setResult(result: Result) {
|
||||
|
|
|
@ -1,443 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
ownCloud Android client application
|
||||
|
||||
Copyright (C) 2015 ownCloud Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2,
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_header"
|
||||
android:paddingBottom="@dimen/standard_padding"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_color"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reason_cert_not_trusted"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:paddingStart="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/ssl_validator_reason_cert_not_trusted"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reason_cert_expired"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:paddingStart="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/ssl_validator_reason_cert_expired"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reason_cert_not_yet_valid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:paddingStart="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/ssl_validator_reason_cert_not_yet_valid"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reason_hostname_not_verified"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:paddingStart="@dimen/standard_half_padding"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/ssl_validator_reason_hostname_not_verified"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/details_scroll"
|
||||
android:visibility="gone"
|
||||
android:padding="@dimen/standard_half_padding"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/scroll_view_height">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/details_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text="@string/ssl_validator_label_subject"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_CN"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_CN"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_CN"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_O"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_O"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_O"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_OU"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_OU"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_OU"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_ST"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_ST"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_ST"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_C"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_C"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_C"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_subject_L"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_L"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_subject_L"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text="@string/ssl_validator_label_issuer"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_CN"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_CN"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_CN"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_O"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_O"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_O"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_OU"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_OU"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_OU"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_ST"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_ST"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_ST"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_C"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_C"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_C"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_issuer_L"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_L"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_issuer_L"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_validity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text="@string/ssl_validator_label_validity"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_validity_from"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_validity_from"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_validity_from"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_validity_to"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_validity_to"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_validity_to"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_signature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text="@string/ssl_validator_label_signature"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label_signature_algorithm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ssl_validator_label_signature_algorithm"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_signature_algorithm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_signature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/alternate_half_padding"
|
||||
android:text=""
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/question"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/standard_padding"
|
||||
android:text="@string/ssl_validator_question"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
>
|
||||
</TextView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center" >
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancel"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/common_no" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/details_btn"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:text="@string/ssl_validator_btn_details_see" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/ok"
|
||||
style="@style/Button.Borderless"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/common_yes" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,58 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Nextcloud Android client application
|
||||
~
|
||||
~ @author Álvaro Brey Vilas
|
||||
~ Copyright (C) 2022 Álvaro Brey Vilas
|
||||
~ Copyright (C) 2022 Nextcloud GmbH
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="?dialogPreferredPadding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/storage_permission_explanation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/file_management_permission_optional_text" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_marginTop="@dimen/standard_padding"
|
||||
android:id="@+id/btn_full_access"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/storage_permission_full_access"
|
||||
android:theme="@style/Button.Primary"
|
||||
app:cornerRadius="@dimen/button_corner_radius"
|
||||
app:layout_constraintTop_toBottomOf="@id/storage_permission_explanation" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_read_only"
|
||||
style="@style/OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/storage_permission_media_read_only"
|
||||
app:cornerRadius="@dimen/button_corner_radius"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_full_access" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -79,7 +79,6 @@
|
|||
<dimen name="search_users_groups_layout_list_view_margin">20dp</dimen>
|
||||
<dimen name="share_file_layout_text_size">12sp</dimen>
|
||||
<dimen name="ssl_untrusted_cert_layout_padding">20dp</dimen>
|
||||
<dimen name="scroll_view_height">180dp</dimen>
|
||||
<dimen name="upload_list_item_frame_layout_width">60dp</dimen>
|
||||
<dimen name="upload_list_item_text_size">12sp</dimen>
|
||||
<dimen name="uploader_list_item_layout_image_margin">12dp</dimen>
|
||||
|
|
|
@ -800,8 +800,6 @@
|
|||
<string name="permission_deny">Deny</string>
|
||||
<string name="permission_allow">Allow</string>
|
||||
<string name="share_send_note">Note to recipient</string>
|
||||
<string name="note_confirm">Send</string>
|
||||
<string name="send_note">Send note to recipient</string>
|
||||
<string name="note_could_not_sent">Could not send note</string>
|
||||
<string name="hint_note">Note</string>
|
||||
<string name="no_browser_available">No app available to handle links</string>
|
||||
|
|