Zhiting cloud disk - development guide android side: folder decryption logic

1. Description of folder decryption

Only the encrypted folder needs to be decrypted. When the same user views the same encrypted folder or the files / folders in it, he / she can view the same encrypted folder or the files / folders in it again after checking the password successfully every time. There is no need to enter the password. The password needs to be entered after 72 hours; (unless the password is changed, if the password is changed, it needs to be re entered. After the password is successfully verified for the first time, the calculation will start for 72 hours).

Note: check whether 72 hours is implemented on the client

2. Folder decryption process

1) Decryption process description

When accessing encrypted files:

First, go to the local database (sqlite) according to the scopeToken and path to find out whether the file has previously saved the decryption password
If it exists, it will check whether the data exceeds 72 hours. If not, take the password access interface Get:/api/plugin/wangpan/folders/:path of the data to check whether the password is correct:
If correct, enter the folder details and update the locally saved password and modification time of the folder;
Error: you need to re-enter the password and access the interface to verify whether the password is correct;
If the verification data is more than 72 hours, you need to enter the password and access the interface to verify whether the password is correct:
Update the locally saved password and modification time of the folder under correct conditions, and insert the password cache information of the file into the database;
Otherwise, the user will be prompted with the wrong password and re-enter it;

2) Main code implementation

/**
 * file
 */
public class HomeFragment extends BaseMVPDBFragment<FragmentHomeBinding, HomeContract.View, HomePresenter> implements HomeContract.View {
    ...
         /**
     * Initialization list
     */
    private void initRv() {
        homeFileAdapter = new HomeFileAdapter(1, true);
        binding.rrv.setAdapter(homeFileAdapter)
                .setOnRefreshAndLoadMoreListener(refreshLoadMoreListener);
        homeFileAdapter.setOnItemClickListener((adapter, view, position) -> {
            mFileBean = homeFileAdapter.getItem(position);
            if (mFileBean.getType() == 0 && homeFileAdapter.getSelectedSize() <= 0) { // If it is a folder and is not in editing status
                if (mFileBean.getRead() == 1) {  // Have read permission
                    if (mFileBean.getIs_encrypt() == 1) { // Encrypted file
                        mPresenter.getFolderPwdByScopeTokenAndPath(Constant.scope_token, mFileBean.getPath());
                    } else {  // Unencrypted file
                        filePwd = "";
                        toFolderDetail(false);
                    }
                } else {  // No read permission
                    ToastUtil.show(UiUtil.getString(R.string.mine_without_read_permission));
                }
            }
        });

        ...
    }
    ...
        
     /**
     * Decrypt file successfully
     */
    @Override
    public void decryptPwdSuccess() {
        if (inputPwdDialog != null && inputPwdDialog.isShowing()) {
            inputPwdDialog.dismiss();
        }
        if (mFolderPwd == null) {
            mFolderPwd = new FolderPassword(Constant.USER_ID, mFileBean.getPath(), filePwd, Constant.scope_token, TimeUtil.getCurrentTimeMillis());
            mPresenter.insertFolderPwd(mFolderPwd);
        } else {
            updateFolderPwd();
        }
        toFolderDetail(true);
    }

    /**
     * Update folder password
     */
    private void updateFolderPwd(){
        mFolderPwd.setPassword(filePwd);
        mFolderPwd.setModifyTime(TimeUtil.getCurrentTimeMillis());
        mPresenter.updateFolderPwd(mFolderPwd);
    }

    /**
     * Failed to decrypt file
     *
     * @param errorCode
     * @param msg
     */
    @Override
    public void decryptPwdFail(int errorCode, String msg) {
        if (errorCode == ErrorConstant.PWD_ERROR) { // Folder password error
            if (inputPwdDialog != null && !inputPwdDialog.isShowing()) {
                filePwd = "";
                updateFolderPwd();
                inputPwdDialog.show(this);
            }
        }
    }
     /**
     * Password obtained successfully
     *
     * @param folderPassword
     */
    @Override
    public void getFolderPwdByScopeTokenAndPathSuccess(FolderPassword folderPassword) {
        LogUtil.e("Query folder password succeeded");
        if (folderPassword != null) {
            filePwd = folderPassword.getPassword();
            long modifyTime = folderPassword.getModifyTime();
            long distinct = TimeUtil.getCurrentTimeMillis() - modifyTime;
            mFolderPwd = folderPassword;
            if (TimeUtil.over72hour(distinct) || TextUtils.isEmpty(filePwd)) {  // More than 72 hours
                showInputPwdDialog();
            } else {
                checkFilePwd();
            }

        } else {
            showInputPwdDialog();
        }
    }

    /**
     * Failed to get password
     */
    @Override
    public void getFolderPwdByScopeTokenAndPathFail() {
        LogUtil.e("Failed to query folder password");
        showInputPwdDialog();
    }
}



/**
 * presenter layer of file
 */
public class HomePresenter extends BasePresenter<HomeModel, HomeContract.View> implements HomeContract.Presenter {
    ...
    /**
     * Decrypt folder
     * @param scopeToken
     * @param path
     * @param checkPwdRequest
     */
    @Override
    public void decryptFile(String scopeToken, String path, CheckPwdRequest checkPwdRequest) {
        executeObservable(mModel.decryptFile(scopeToken, path, checkPwdRequest), new RequestDataCallback<Object>(false) {
            @Override
            public void onSuccess(Object response) {
                super.onSuccess(response);
                if (mView!=null){
                    mView.decryptPwdSuccess();
                }
            }

            @Override
            public void onFailed(int errorCode, String errorMessage) {
                super.onFailed(errorCode, errorMessage);
                if (mView!=null){
                    mView.decryptPwdFail(errorCode, errorMessage);
                }
            }
        });
    }

    /**
     * Get locally saved folder password
     * @param scopeToken
     * @param path
     */
    @Override
    public void getFolderPwdByScopeTokenAndPath(String scopeToken, String path) {
        executeDBObservable(mModel.getFolderPwdByScopeTokenAndPath(scopeToken, path), new RequestDataCallback<FolderPassword>() {
            @Override
            public void onSuccess(FolderPassword response) {
                super.onSuccess(response);
                if (mView!=null){
                    mView.getFolderPwdByScopeTokenAndPathSuccess(response);
                }
            }

            @Override
            public void onFailed() {
                super.onFailed();
                if (mView!=null){
                    mView.getFolderPwdByScopeTokenAndPathFail();
                }
            }
        });
    }

    /**
     * Insert folder password
     * @param folderPassword
     */
    @Override
    public void insertFolderPwd(FolderPassword folderPassword) {
        executeDBObservable(mModel.insertFolderPwd(folderPassword), new RequestDataCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean response) {
                super.onSuccess(response);
                if (mView!=null){
                    if (response) {
                        mView.insertFolderPwdSuccess(true);
                    }else {
                        mView.insertFolderFail();
                    }
                }

            }

            @Override
            public void onFailed() {
                super.onFailed();
                if (mView!=null){
                    mView.insertFolderFail();
                }
            }
        });
        
        ...
        /**
        * Verify that the folder password is correct
        */
        private void checkFilePwd() {
            if (mFileBean != null) {
                if (TextUtils.isEmpty(filePwd)){ // If the password is blank, enter
                    inputPwdDialog.show(this);
                }else { // The password is not empty. Please verify the password
                    CheckPwdRequest checkPwdRequest = new CheckPwdRequest(filePwd);
                    mPresenter.decryptFile(Constant.scope_token, mFileBean.getPath(), checkPwdRequest);
                }
            }
        }
    }

    /**
     * Modify folder password
     * @param folderPassword
     */
    @Override
    public void updateFolderPwd(FolderPassword folderPassword) {
        executeDBObservable(mModel.updateFolderPwd(folderPassword), new RequestDataCallback<Boolean>() {
            @Override
            public void onSuccess(Boolean response) {
                super.onSuccess(response);
                if (mView!=null) {
                    if (response) {
                        mView.updateFolderPwdSuccess();
                    } else {
                        mView.updateFolderPwdFail();
                    }
                }
            }

            @Override
            public void onFailed() {
                super.onFailed();
                if (mView!=null){
                    mView.updateFolderPwdFail();
                }
            }
        });
    }
}

3) Database

Zhiting cloud disk stores folder password related information by using the Android local database SqLite. The database framework used is greendao (please refer to the official document for the use of greendao, which will not be repeated here). When searching for folder password, it is through the path and voucher of the folder. The following is the design of folder password related information table.

Table namedescribe
idPrimary key id
userIdUser id
pathFolder path
passwordFolder password
scopeTokenvoucher
modifyTimeCreation / modification time

The following is the model class of the folder password related information table:

@Entity
public class FolderPassword {

    @Id(autoincrement = true)
    private Long id;  // Primary key id
    private int userId;  // User id
    private String path;  // Folder path
    private String password; // Folder password
    private String scopeToken;  // scopeToken
    private Long modifyTime;  // Creation / modification time
    ...
        
}

Keywords: Android

Added by yogibear333 on Mon, 21 Feb 2022 10:05:04 +0200