mirror of
https://gitee.com/openharmony/applications_settings
synced 2024-11-26 16:10:49 +00:00
add system vpn
Signed-off-by: xiaohui.xie <xiexiaohui15@h-partners.com>
This commit is contained in:
parent
6d48d4dfb3
commit
d020d021ec
@ -4,7 +4,7 @@
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "release",
|
||||
"compileSdkVersion": 11,
|
||||
"compileSdkVersion": 12,
|
||||
"compatibleSdkVersion": 10
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2021-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -38,6 +38,14 @@ export default class MainAbility extends Ability {
|
||||
let url = 'pages/settingList';
|
||||
if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'volumeControl') {
|
||||
url = 'pages/volumeControl';
|
||||
} else if (this.funcAbilityWant?.uri === "wifi") {
|
||||
url = 'pages/wifi';
|
||||
} else if (this.funcAbilityWant?.uri === "bluetooth") {
|
||||
url = 'pages/bluetooth';
|
||||
} else if (this.funcAbilityWant?.uri === "volumeControl") {
|
||||
url = 'pages/volumeControl';
|
||||
} else if (this.funcAbilityWant?.uri === "locationServices") {
|
||||
url = 'pages/locationServices';
|
||||
}
|
||||
windowStage.setUIContent(this.context, url, null);
|
||||
GlobalContext.getContext().setObject(GlobalContext.globalKeySettingsAbilityContext, this.context);
|
||||
|
250
product/phone/src/main/ets/model/vpnImpl/SwanCtlModel.ts
Normal file
250
product/phone/src/main/ets/model/vpnImpl/SwanCtlModel.ts
Normal file
@ -0,0 +1,250 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import common from '@ohos.app.ability.common';
|
||||
import HashMap from '@ohos.util.HashMap';
|
||||
import { util } from '@kit.ArkTS';
|
||||
import { IpsecVpnConfig } from './VpnConfig';
|
||||
import { VpnConfigModel } from './VpnConfigModel';
|
||||
import { VpnTypeModel } from '../../model/vpnImpl/VpnTypeModel';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:SwanCtlModel:';
|
||||
//param
|
||||
const KEY_VPN_ADDRESS: string = 'vpn_address_value';
|
||||
const KEY_VPN_USERNAME: string = 'vpn_username_value';
|
||||
const KEY_VPN_IPSEC_IDENTIFIER: string = 'vpn_ipsec_identifier_value';
|
||||
const KEY_VPN_PASSWORD: string = 'vpn_password_value';
|
||||
const KEY_VPN_IPSEC_SHAREDKEY: string = 'vpn_ipsec_sharedKey_value';
|
||||
|
||||
//file path
|
||||
const SWANCTL_IKE2_IPSEC_MSCHAPV2_PATH: string = 'vpn/ike2_ipsec_mschapv2/swanctl.conf';
|
||||
const STRONGSWAN_IKE2_IPSEC_MSCHAPV2_PATH: string = 'vpn/ike2_ipsec_mschapv2/strongswan.conf';
|
||||
const SWANCTL_IKE2_IPSEC_RSA_PATH: string = 'vpn/ike2_ipsec_rsa/swanctl.conf';
|
||||
const STRONGSWAN_IKE2_IPSEC_RSA_PATH: string = 'vpn/ike2_ipsec_rsa/strongswan.conf';
|
||||
const SWANCTL_IKE2_IPSEC_PSK_PATH: string = 'vpn/ike2_ipsec_psk/swanctl.conf';
|
||||
const STRONGSWAN_IKE2_IPSEC_PSK_PATH: string = 'vpn/ike2_ipsec_psk/strongswan.conf';
|
||||
|
||||
const SWANCTL_IPSEC_XAUTH_PSK_PATH: string = 'vpn/ipsec_xauth_psk/swanctl.conf';
|
||||
const STRONGSWAN_IPSEC_XAUTH_PSK_PATH: string = 'vpn/ipsec_xauth_psk/strongswan.conf';
|
||||
const SWANCTL_IPSEC_XAUTH_RSA_PATH: string = 'vpn/ipsec_xauth_rsa/swanctl.conf';
|
||||
const STRONGSWAN_IPSEC_XAUTH_RSA_PATH: string = 'vpn/ipsec_xauth_rsa/strongswan.conf';
|
||||
|
||||
const STRONGSWAN_L2TP_IPSEC_RSA_PATH: string = 'vpn/l2tp_ipsec_rsa/strongswan.conf';
|
||||
const STRONGSWAN_L2TP_IPSEC_PSK_PATH: string = 'vpn/l2tp_ipsec_psk/strongswan.conf';
|
||||
|
||||
const CLIENT_L2TP_IPSEC_PSK_PATH: string = 'vpn/l2tp_ipsec_psk/options.l2tpd.client.conf';
|
||||
const CLIENT_L2TP_IPSEC_RSA_PATH: string = 'vpn/l2tp_ipsec_rsa/options.l2tpd.client.conf';
|
||||
const XL2TPD_L2TP_IPSEC_PSK_PATH: string = 'vpn/l2tp_ipsec_psk/xl2tpd.conf';
|
||||
const XL2TPD_L2TP_IPSEC_RSA_PATH: string = 'vpn/l2tp_ipsec_rsa/xl2tpd.conf';
|
||||
|
||||
const IPSECCONF_L2TP_IPSEC_PSK_PATH: string = 'vpn/l2tp_ipsec_psk/ipsec.conf';
|
||||
const IPSECCONF_L2TP_IPSEC_RSA_PATH: string = 'vpn/l2tp_ipsec_rsa/ipsec.conf';
|
||||
|
||||
const IPSEC_SECRETS_L2TP_IPSEC_PSK_PATH: string = 'vpn/l2tp_ipsec_psk/ipsec.secrets.conf';
|
||||
const IPSEC_SECRETS_L2TP_IPSEC_RSA_PATH: string = 'vpn/l2tp_ipsec_rsa/ipsec.secrets.conf';
|
||||
|
||||
const SWANCTL_IPSEC_HYBRID_RSA_PATH: string = 'vpn/ipsec_hybrid_rsa/swanctl.conf';
|
||||
const STRONGSWAN_IPSEC_HYBRID_RSA_PATH: string = 'vpn/ipsec_hybrid_rsa/strongswan.conf';
|
||||
|
||||
export class SwanCtlModel {
|
||||
private context: common.UIAbilityContext = undefined;
|
||||
private swanCtlMap = new HashMap();
|
||||
private strongSwanMap = new HashMap();
|
||||
private l2tpdClientMap = new HashMap();
|
||||
private xl2tpdMap = new HashMap();
|
||||
private ipsecConfMap = new HashMap();
|
||||
private ipsecSecretsMap = new HashMap();
|
||||
|
||||
private static instance: SwanCtlModel;
|
||||
|
||||
public static getInstance(): SwanCtlModel {
|
||||
if (!this.instance) {
|
||||
this.instance = new SwanCtlModel();
|
||||
}
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
public async init(context: common.UIAbilityContext): Promise<void> {
|
||||
this.context = context;
|
||||
this.readTemplate();
|
||||
}
|
||||
|
||||
public buildConfig(ipsec: IpsecVpnConfig): IpsecVpnConfig {
|
||||
let helper: util.Base64Helper = new util.Base64Helper();
|
||||
if (ipsec.vpnType !== VpnTypeModel.TYPE_L2TP_IPSEC_PSK && ipsec.vpnType !== VpnTypeModel.TYPE_L2TP_IPSEC_RSA) {
|
||||
ipsec.swanctlConfig = helper.encodeToStringSync(this.ipsec2swanCtl(ipsec));
|
||||
}
|
||||
ipsec.strongSwanConfig = helper.encodeToStringSync(this.ipsec2strongSwan(ipsec));
|
||||
if (ipsec.vpnType === VpnTypeModel.TYPE_L2TP_IPSEC_PSK || ipsec.vpnType === VpnTypeModel.TYPE_L2TP_IPSEC_RSA) {
|
||||
ipsec.optionsL2tpdClient = helper.encodeToStringSync(this.ipsec2L2tpdClient(ipsec));
|
||||
ipsec.xl2tpdConfig = helper.encodeToStringSync(this.ipsec2Xl2tpd(ipsec));
|
||||
ipsec.ipsecConfig = helper.encodeToStringSync(this.ipsec2IpsecConf(ipsec));
|
||||
ipsec.ipsecSecrets = helper.encodeToStringSync(this.ipsec2IpsecSecrets(ipsec));
|
||||
}
|
||||
return ipsec;
|
||||
}
|
||||
|
||||
private ipsec2swanCtl(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.swanCtlMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.swanCtlMap.get(ipsec.vpnType);
|
||||
let vpnTemplate = String(template);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_ADDRESS, VpnConfigModel.getInstance().getAddress(ipsec));
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_IPSEC_IDENTIFIER, ipsec.ipsecIdentifier);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_IPSEC_SHAREDKEY, ipsec.ipsecPreSharedKey);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_USERNAME, ipsec.userName);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_PASSWORD, ipsec.password);
|
||||
|
||||
let swanCtl = this.stringToUint8Array(vpnTemplate);
|
||||
return swanCtl;
|
||||
}
|
||||
|
||||
private ipsec2strongSwan(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.strongSwanMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.strongSwanMap.get(ipsec.vpnType);
|
||||
let strongSwan = this.stringToUint8Array(String(template));
|
||||
return strongSwan;
|
||||
}
|
||||
|
||||
private ipsec2Xl2tpd(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.xl2tpdMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.xl2tpdMap.get(ipsec.vpnType);
|
||||
let vpnTemplate = String(template);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_ADDRESS, VpnConfigModel.getInstance().getAddress(ipsec));
|
||||
let xl2tpd = this.stringToUint8Array(vpnTemplate);
|
||||
return xl2tpd;
|
||||
}
|
||||
|
||||
private ipsec2L2tpdClient(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.l2tpdClientMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.l2tpdClientMap.get(ipsec.vpnType);
|
||||
let vpnTemplate = String(template);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_USERNAME, ipsec.userName);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_PASSWORD, ipsec.password);
|
||||
let xl2tpd = this.stringToUint8Array(vpnTemplate);
|
||||
return xl2tpd;
|
||||
}
|
||||
|
||||
private ipsec2IpsecConf(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.ipsecConfMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.ipsecConfMap.get(ipsec.vpnType);
|
||||
let vpnTemplate = String(template);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_ADDRESS, VpnConfigModel.getInstance().getAddress(ipsec));
|
||||
let ipsecConf = this.stringToUint8Array(vpnTemplate);
|
||||
return ipsecConf;
|
||||
}
|
||||
|
||||
private ipsec2IpsecSecrets(ipsec: IpsecVpnConfig): Uint8Array {
|
||||
if (this.ipsecSecretsMap.isEmpty()) {
|
||||
this.readTemplate();
|
||||
}
|
||||
let template = this.ipsecSecretsMap.get(ipsec.vpnType);
|
||||
let vpnTemplate = String(template);
|
||||
vpnTemplate = this.replaceConfigParam(vpnTemplate, KEY_VPN_IPSEC_SHAREDKEY, ipsec.ipsecPreSharedKey);
|
||||
let ipsecSecrets = this.stringToUint8Array(vpnTemplate);
|
||||
return ipsecSecrets;
|
||||
}
|
||||
|
||||
private readTemplate(): void {
|
||||
//swanctl.config
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2, SWANCTL_IKE2_IPSEC_MSCHAPV2_PATH);
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_RSA, SWANCTL_IKE2_IPSEC_RSA_PATH);
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_PSK, SWANCTL_IKE2_IPSEC_PSK_PATH);
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IPSEC_XAUTH_PSK, SWANCTL_IPSEC_XAUTH_PSK_PATH);
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IPSEC_XAUTH_RSA, SWANCTL_IPSEC_XAUTH_RSA_PATH);
|
||||
this.swanCtlMap.set(VpnTypeModel.TYPE_IPSEC_HYBRID_RSA, SWANCTL_IPSEC_HYBRID_RSA_PATH);
|
||||
this.swanCtlMap = this.readRawFile(this.swanCtlMap);
|
||||
//strongSwan.config
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2, STRONGSWAN_IKE2_IPSEC_MSCHAPV2_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_RSA, STRONGSWAN_IKE2_IPSEC_RSA_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IKEV2_IPSEC_PSK, STRONGSWAN_IKE2_IPSEC_PSK_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IPSEC_XAUTH_PSK, STRONGSWAN_IPSEC_XAUTH_PSK_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IPSEC_XAUTH_RSA, STRONGSWAN_IPSEC_XAUTH_RSA_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_IPSEC_HYBRID_RSA, STRONGSWAN_IPSEC_HYBRID_RSA_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_PSK, STRONGSWAN_L2TP_IPSEC_PSK_PATH);
|
||||
this.strongSwanMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_RSA, STRONGSWAN_L2TP_IPSEC_RSA_PATH);
|
||||
this.strongSwanMap = this.readRawFile(this.strongSwanMap);
|
||||
//xl2tpd.conf
|
||||
this.xl2tpdMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_PSK, XL2TPD_L2TP_IPSEC_PSK_PATH);
|
||||
this.xl2tpdMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_RSA, XL2TPD_L2TP_IPSEC_RSA_PATH);
|
||||
this.xl2tpdMap = this.readRawFile(this.xl2tpdMap);
|
||||
//options.l2tpd.client.conf
|
||||
this.l2tpdClientMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_PSK, CLIENT_L2TP_IPSEC_PSK_PATH);
|
||||
this.l2tpdClientMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_RSA, CLIENT_L2TP_IPSEC_RSA_PATH);
|
||||
this.l2tpdClientMap = this.readRawFile(this.l2tpdClientMap);
|
||||
//ipsec.conf
|
||||
this.ipsecConfMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_PSK, IPSECCONF_L2TP_IPSEC_PSK_PATH);
|
||||
this.ipsecConfMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_RSA, IPSECCONF_L2TP_IPSEC_RSA_PATH);
|
||||
this.ipsecConfMap = this.readRawFile(this.ipsecConfMap);
|
||||
//ipsec.secrets.conf
|
||||
this.ipsecSecretsMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_PSK, IPSEC_SECRETS_L2TP_IPSEC_PSK_PATH);
|
||||
this.ipsecSecretsMap.set(VpnTypeModel.TYPE_L2TP_IPSEC_RSA, IPSEC_SECRETS_L2TP_IPSEC_RSA_PATH);
|
||||
this.ipsecSecretsMap = this.readRawFile(this.ipsecSecretsMap);
|
||||
}
|
||||
|
||||
private readRawFile(pathMap): HashMap<number, string> {
|
||||
try {
|
||||
pathMap.forEach((path, key) => {
|
||||
this.context.resourceManager.getRawFileContent(path as string, (error, value) => {
|
||||
if (error !== null && error !== undefined) {
|
||||
LogUtil.log(MODULE_TAG + 'readRawFile faile, error:' + error);
|
||||
} else {
|
||||
pathMap.set(key, this.uint8ArrayToString(value));
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
LogUtil.error(MODULE_TAG + 'callback getRawfileContent failed, error:' + error);
|
||||
}
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
private replaceConfigParam(vpnTemplate: string, key: string, value: string): string {
|
||||
if (!value || !key) {
|
||||
LogUtil.warn(MODULE_TAG + 'replaceConfigParam failed, params is null or undefined');
|
||||
return vpnTemplate;
|
||||
}
|
||||
while (vpnTemplate.indexOf(key) !== -1) {
|
||||
vpnTemplate = vpnTemplate.replace(key, value.trim());
|
||||
}
|
||||
return vpnTemplate;
|
||||
}
|
||||
|
||||
private uint8ArrayToString(fileData): string {
|
||||
let dataString = '';
|
||||
for (let i = 0; i < fileData.length; i++) {
|
||||
dataString += String.fromCharCode(fileData[i]);
|
||||
}
|
||||
return dataString;
|
||||
}
|
||||
|
||||
private stringToUint8Array(str: string): Uint8Array {
|
||||
let arr: number[] = [];
|
||||
for (let i = 0, j = str.length; i < j; ++i) {
|
||||
arr.push(str.charCodeAt(i));
|
||||
}
|
||||
return new Uint8Array(arr);
|
||||
}
|
||||
}
|
94
product/phone/src/main/ets/model/vpnImpl/VpnConfig.ts
Normal file
94
product/phone/src/main/ets/model/vpnImpl/VpnConfig.ts
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import { VpnTypeModel } from './VpnTypeModel';
|
||||
|
||||
/**
|
||||
* extend system VpnConig
|
||||
*/
|
||||
export default class VpnConfig implements vpn.SysVpnConfig {
|
||||
// vpnConfig
|
||||
addresses: Array<vpn.LinkAddress> = [];
|
||||
routes?: Array<vpn.RouteInfo>;
|
||||
dnsAddresses?: Array<string>;
|
||||
searchDomains?: Array<string>;
|
||||
isLegacy: boolean = true;
|
||||
|
||||
// sysVpnConfig
|
||||
vpnId: string = '';
|
||||
vpnName: string = '';
|
||||
vpnType: vpn.SysVpnType = VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2;
|
||||
userName?: string;
|
||||
password?: string;
|
||||
saveLogin: boolean = false;
|
||||
userId?: number;
|
||||
forwardingRoutes?: string;
|
||||
}
|
||||
|
||||
export class OpenVpnConfig extends VpnConfig implements vpn.OpenVpnConfig {
|
||||
ovpnConfigFilePath?: string // openVpn file name
|
||||
ovpnConfigContent?: string // openVpn config
|
||||
ovpnConfig?: string // openVpn config base64
|
||||
ovpnAuthType: number = 0 // openvpn auth type
|
||||
ovpnProtocolFileRaw?: string // Protocol
|
||||
ovpnProtocol: number = 0 // 0:tcp 1:udp
|
||||
ovpnAddressPortFileRaw?: string // port
|
||||
ovpnPort?: string // openvpn port
|
||||
askpass: string // private key password
|
||||
ovpnCaCertFilePath?: string // openVpn CA FilePath
|
||||
ovpnUserCertFilePath?: string // openVpn USER FilePath
|
||||
ovpnPrivateKeyFilePath?: string // openVpn private key FilePath
|
||||
ovpnCaCertFileRaw?: string // ca raw data
|
||||
ovpnCaCert?: string // CA data
|
||||
ovpnUserCertFileRaw?: string //
|
||||
ovpnUserCert?: string //
|
||||
ovpnPrivateKeyFileRaw?: string // private key raw data
|
||||
ovpnPrivateKey?: string // private key data
|
||||
ovpnUserPassFileRaw?: string // userpass raw d
|
||||
ovpnProxyHostFileRaw?: string // host raw data
|
||||
ovpnProxyHost?: string //ovpn host
|
||||
ovpnProxyPort?: string //ovpn port
|
||||
ovpnProxyUserPassFileRaw?: string // userpass data
|
||||
ovpnProxyUser?: string //ovpn user
|
||||
ovpnProxyPass?: string //ovpn pass
|
||||
}
|
||||
|
||||
export class IpsecVpnConfig extends VpnConfig implements vpn.IpsecVpnConfig {
|
||||
ipsecIdentifier?: string // ipsec identifier
|
||||
ipsecPreSharedKey?: string // ipsec pre sharedKey
|
||||
l2tpSharedKey?: string // L2TP secret
|
||||
ipsecPublicUserCertConfig?: string // public userCert config
|
||||
ipsecPublicUserCertFilePath?: string // public userCert FilePath
|
||||
ipsecPrivateUserCertConfig?: string // private userCert config
|
||||
ipsecPrivateUserCertFilePath?: string // private userCert FilePath
|
||||
ipsecCaCertConfig?: string // ca config
|
||||
ipsecCaCertFilePath?: string // ca FilePath
|
||||
ipsecPublicServerCertConfig?: string // public serverCert config
|
||||
ipsecPublicServerCertFilePath?: string // public serverCert FilePath
|
||||
ipsecPrivateServerCertConfig?: string // private serverCert config
|
||||
ipsecPrivateServerCertFilePath?: string // private serverCert FilePath
|
||||
swanctlConfig?: string // swanctl config base64
|
||||
strongSwanConfig?: string // strongswan config base64
|
||||
optionsL2tpdClient?: string // optionsL2tpd Client base64
|
||||
xl2tpdConfig?: string // xl2tpd config base64
|
||||
ipsecConfig?: string // swanctl config base64
|
||||
ipsecSecrets?: string // swanctl config base64
|
||||
}
|
||||
|
||||
export class VpnListItem {
|
||||
vpnName: string //vpnName
|
||||
vpnId: string //UUID
|
||||
}
|
336
product/phone/src/main/ets/model/vpnImpl/VpnConfigModel.ts
Normal file
336
product/phone/src/main/ets/model/vpnImpl/VpnConfigModel.ts
Normal file
@ -0,0 +1,336 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import util from '@ohos.util';
|
||||
import { promptAction } from '@kit.ArkUI';
|
||||
import VpnConfig, { IpsecVpnConfig, OpenVpnConfig } from './VpnConfig';
|
||||
import VpnConstant from './VpnConstant';
|
||||
import { VpnTypeModel } from './VpnTypeModel';
|
||||
import { SwanCtlModel } from './SwanCtlModel';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnConnectModel:';
|
||||
const OVPN_PROTOCOL_TCP: number = 0;
|
||||
const OVPN_PROTOCOL_UDP: number = 1;
|
||||
|
||||
/**
|
||||
* system vpn config model
|
||||
*/
|
||||
export class VpnConfigModel {
|
||||
private static instance: VpnConfigModel;
|
||||
|
||||
private isNeedUpdateVpnList: boolean = false;
|
||||
|
||||
public static getInstance(): VpnConfigModel {
|
||||
if (!this.instance) {
|
||||
this.instance = new VpnConfigModel();
|
||||
}
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
isUpdateVpnList(): boolean {
|
||||
return this.isNeedUpdateVpnList;
|
||||
}
|
||||
|
||||
setNeedUpdateVpnList(isUpdate: boolean): void {
|
||||
this.isNeedUpdateVpnList = isUpdate;
|
||||
}
|
||||
|
||||
setAddress(vpnConfig: VpnConfig, vpnAddress: string): void {
|
||||
if (vpnConfig === undefined || vpnConfig === null) {
|
||||
LogUtil.error(MODULE_TAG + `setAddress failed, invalid config`);
|
||||
return;
|
||||
}
|
||||
vpnConfig.addresses = [{
|
||||
address: { address: vpnAddress },
|
||||
prefixLength: 1,
|
||||
}]
|
||||
}
|
||||
|
||||
getAddress(vpnConfig: VpnConfig): string | undefined {
|
||||
if (vpnConfig === undefined || vpnConfig === null) {
|
||||
LogUtil.error(MODULE_TAG + `setRoutes failed, invalid config`);
|
||||
return undefined;
|
||||
}
|
||||
if (vpnConfig.addresses?.length > 0) {
|
||||
return vpnConfig.addresses[0].address?.address;
|
||||
}
|
||||
LogUtil.error(MODULE_TAG + `getAddress invalid vpnConfig`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
stringToUint8Array(str: string): Uint8Array {
|
||||
let arr: number[] = [];
|
||||
for (let i = 0, j = str.length; i < j; ++i) {
|
||||
arr.push(str.charCodeAt(i));
|
||||
}
|
||||
return new Uint8Array(arr);
|
||||
}
|
||||
|
||||
uint8ArrayToString(data: Uint8Array): string {
|
||||
let resultStr: string = '';
|
||||
const charArray = data.map(value => Number(value));
|
||||
charArray.forEach((value) => {
|
||||
resultStr += String.fromCharCode(value);
|
||||
});
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
showToast(msg: string | Resource): void {
|
||||
if (!msg) {
|
||||
LogUtil.error(MODULE_TAG + `showToast failed, invalid msg`);
|
||||
return;
|
||||
}
|
||||
promptAction.showToast({
|
||||
message: msg,
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
|
||||
inflateConfigFromFileData(config: OpenVpnConfig, data: string[]): void {
|
||||
config.ovpnConfigFilePath = data[0];
|
||||
let content = data[1];
|
||||
config.ovpnConfigContent = content;
|
||||
|
||||
let regex = /proto\s+(tcp|udp)/;
|
||||
let match = regex.exec(content);
|
||||
if (match && match.length >= 1) {
|
||||
config.ovpnProtocolFileRaw = match[0];
|
||||
config.ovpnProtocol = match[1] === 'udp' ? OVPN_PROTOCOL_UDP : OVPN_PROTOCOL_TCP;
|
||||
}
|
||||
|
||||
regex = /remote\s+([^\s]+)\s+(\d+)/;
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 2) {
|
||||
config.ovpnAddressPortFileRaw = match[0];
|
||||
this.setAddress(config, match[1]);
|
||||
config.ovpnPort = match[2];
|
||||
}
|
||||
|
||||
regex = /<ca>([\s\S]*?)<\/ca>/
|
||||
match = regex.exec(content);
|
||||
if (match) {
|
||||
config.ovpnCaCertFileRaw = match[0];
|
||||
}
|
||||
|
||||
regex = /<cert>([\s\S]*?)<\/cert>/
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 1) {
|
||||
config.ovpnUserCertFileRaw = match[0];
|
||||
}
|
||||
|
||||
regex = /<key>([\s\S]*?)<\/key>/
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 1) {
|
||||
config.ovpnPrivateKeyFileRaw = match[0];
|
||||
}
|
||||
|
||||
regex = /<auth-user-pass>\s*([\s\S]+?)\s*(\r?\n|\r)\s*([\s\S]+?)\s*<\/auth-user-pass>/
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 4) {
|
||||
config.ovpnUserPassFileRaw = match[0];
|
||||
config.userName = match[1];
|
||||
config.password = match[3];
|
||||
}
|
||||
|
||||
regex = /http-proxy\s+([^\s]+)\s+(\d+)/;
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 3) {
|
||||
config.ovpnProxyHostFileRaw = match[0];
|
||||
config.ovpnProxyHost = match[1];
|
||||
config.ovpnProxyPort = match[2];
|
||||
}
|
||||
|
||||
regex = /<http-proxy-user-pass>\s*([\s\S]+?)\s*(\r?\n|\r)\s*([\s\S]+?)\s*<\/http-proxy-user-pass>/;
|
||||
match = regex.exec(content);
|
||||
if (match && match.length >= 4) {
|
||||
config.ovpnProxyUserPassFileRaw = match[0];
|
||||
config.ovpnProxyUser = match[1];
|
||||
config.ovpnProxyPass = match[3];
|
||||
}
|
||||
}
|
||||
|
||||
prepareAddSysVpnConfig(config: VpnConfig): void {
|
||||
switch (config?.vpnType) {
|
||||
case VpnTypeModel.TYPE_OPENVPN:
|
||||
this.prepareOvpnConfig(config as OpenVpnConfig);
|
||||
break;
|
||||
default:
|
||||
this.prepareIpsecConfig(config as IpsecVpnConfig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prepareIpsecConfig(config: IpsecVpnConfig): void {
|
||||
if (config === undefined || config === null) {
|
||||
LogUtil.error(MODULE_TAG + "prepareIpsecConfig faild, invalid param.")
|
||||
return;
|
||||
}
|
||||
SwanCtlModel.getInstance().buildConfig(config);
|
||||
}
|
||||
|
||||
prepareOvpnConfig(config: OpenVpnConfig): void {
|
||||
if (config === undefined || config === null) {
|
||||
LogUtil.error(MODULE_TAG + "prepareOvpnConfig faild, invalid param.")
|
||||
return;
|
||||
}
|
||||
let that = new util.Base64Helper();
|
||||
let content = '';
|
||||
if (config.ovpnConfig) {
|
||||
let data = that.decodeSync(config.ovpnConfig);
|
||||
content = this.uint8ArrayToString(data);
|
||||
} else {
|
||||
content = config.ovpnConfigContent ?? 'client\ndev tun';
|
||||
}
|
||||
|
||||
let protocolReplace: string = `proto ${config.ovpnProtocol === OVPN_PROTOCOL_TCP ? 'tcp' : 'udp'}`;
|
||||
if (protocolReplace === config.ovpnProtocolFileRaw) {
|
||||
content = content.replace(config.ovpnProtocolFileRaw, '\n' + protocolReplace);
|
||||
} else {
|
||||
content += '\n';
|
||||
content += protocolReplace;
|
||||
}
|
||||
|
||||
let vpnAddress: string = this.getAddress(config);
|
||||
if (vpnAddress && config.ovpnPort) {
|
||||
let addressPortReplace: string = `remote ${vpnAddress} ${config.ovpnPort}`;
|
||||
if (addressPortReplace === config.ovpnAddressPortFileRaw) {
|
||||
content = content.replace(config.ovpnAddressPortFileRaw, '\n' + addressPortReplace);
|
||||
} else {
|
||||
content += '\n';
|
||||
content += addressPortReplace;
|
||||
content += '\nlog \/data\/service\/el1\/public\/netmanager\/config.log\ndev-node \/dev\/tun' +
|
||||
'\nresolv-retry infinite\nnobind\npersist-key\npersist-tun\nverb 7\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnCaCert) {
|
||||
let caCert: string = config.ovpnCaCert;
|
||||
if (config.ovpnCaCertFileRaw) {
|
||||
if (config.ovpnCaCertFileRaw !== caCert) {
|
||||
content = content.replace(config.ovpnCaCertFileRaw, '\n' + caCert);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += caCert;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnAuthType === VpnConstant.OVPN_AUTH_TYPE_PWD) {
|
||||
config.ovpnUserCert = undefined;
|
||||
if (config.ovpnUserCertFileRaw) {
|
||||
content.replace(config.ovpnUserCertFileRaw, '');
|
||||
}
|
||||
config.ovpnUserCertFileRaw = undefined;
|
||||
config.ovpnUserCertFilePath = undefined;
|
||||
}
|
||||
|
||||
if (config.ovpnUserCert) {
|
||||
let userCert: string = config.ovpnUserCert;
|
||||
if (config.ovpnUserCertFileRaw) {
|
||||
if (config.ovpnUserCertFileRaw !== userCert) {
|
||||
content = content.replace(config.ovpnUserCertFileRaw, '\n' + userCert);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += userCert;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnAuthType === VpnConstant.OVPN_AUTH_TYPE_PWD) {
|
||||
config.ovpnPrivateKey = undefined;
|
||||
if (config.ovpnPrivateKeyFileRaw) {
|
||||
content.replace(config.ovpnPrivateKeyFileRaw, '');
|
||||
}
|
||||
config.ovpnPrivateKeyFileRaw = undefined;
|
||||
config.ovpnPrivateKeyFilePath = undefined;
|
||||
}
|
||||
|
||||
if (config.ovpnPrivateKey) {
|
||||
let privateKey: string = config.ovpnPrivateKey;
|
||||
if (config.ovpnPrivateKeyFileRaw) {
|
||||
if (config.ovpnPrivateKeyFileRaw !== privateKey) {
|
||||
content = content.replace(config.ovpnPrivateKeyFileRaw, '\n' + privateKey);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += privateKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnAuthType === VpnConstant.OVPN_AUTH_TYPE_TLS) {
|
||||
config.userName = undefined;
|
||||
config.password = undefined;
|
||||
if (config.ovpnUserPassFileRaw) {
|
||||
content = content.replace(config.ovpnUserPassFileRaw, '');
|
||||
}
|
||||
}
|
||||
|
||||
if (config.userName) {
|
||||
let userPass: string = '<auth-user-pass>';
|
||||
userPass += '\n';
|
||||
userPass += config.userName;
|
||||
userPass += '\n';
|
||||
userPass += config.password;
|
||||
userPass += '\n';
|
||||
userPass += '</auth-user-pass>'
|
||||
|
||||
if (config.userName) {
|
||||
if (config.ovpnUserPassFileRaw) {
|
||||
if (config.ovpnUserPassFileRaw !== userPass) {
|
||||
content = content.replace(config.ovpnUserPassFileRaw, '\n' + userPass);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += userPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnProxyHost) {
|
||||
let proxyHostPort: string = `http-proxy ${config.ovpnProxyHost} ${config.ovpnProxyPort ?? ''}`;
|
||||
if (config.ovpnProxyHostFileRaw) {
|
||||
if (config.ovpnProxyHostFileRaw !== proxyHostPort) {
|
||||
content = content.replace(config.ovpnProxyHostFileRaw, '\n' + proxyHostPort);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += proxyHostPort;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ovpnProxyUser) {
|
||||
let proxyUserPass: string = '<http-proxy-user-pass>';
|
||||
proxyUserPass += '\n';
|
||||
proxyUserPass += config.ovpnProxyUser;
|
||||
proxyUserPass += '\n';
|
||||
proxyUserPass += config.ovpnProxyPass;
|
||||
proxyUserPass += '\n';
|
||||
proxyUserPass += '</http-proxy-user-pass>'
|
||||
if (config.ovpnProxyUserPassFileRaw) {
|
||||
if (config.ovpnProxyUserPassFileRaw !== proxyUserPass) {
|
||||
content = content.replace(config.ovpnProxyUserPassFileRaw, '\n' + proxyUserPass);
|
||||
}
|
||||
} else {
|
||||
content += '\n';
|
||||
content += proxyUserPass;
|
||||
}
|
||||
}
|
||||
|
||||
let regex = /^\s*$\n/gm;
|
||||
content = content.replace(regex, '');
|
||||
config.ovpnConfig = that.encodeToStringSync(this.stringToUint8Array(content));
|
||||
}
|
||||
}
|
198
product/phone/src/main/ets/model/vpnImpl/VpnConnectModel.ts
Normal file
198
product/phone/src/main/ets/model/vpnImpl/VpnConnectModel.ts
Normal file
@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import type common from '@ohos.app.ability.common';
|
||||
import VpnConfig from './VpnConfig';
|
||||
import VpnConstant from './VpnConstant';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnConnectModel:';
|
||||
AppStorage.setOrCreate(VpnConstant.STORAGE_KEY_CONNECT_STATE, VpnConstant.VPN_STATE_NONE);
|
||||
|
||||
/**
|
||||
* app management service class
|
||||
*/
|
||||
export class VpnConnectModel {
|
||||
private static instance: VpnConnectModel;
|
||||
|
||||
private connection: vpn.VpnConnection | undefined = undefined;
|
||||
private timeoutId: number = undefined;
|
||||
private connectedVpnId: string = undefined;
|
||||
private connectState: number = VpnConstant.VPN_STATE_NONE;
|
||||
private replaceConnectVpnConfig: VpnConfig = undefined;
|
||||
|
||||
public static getInstance(): VpnConnectModel {
|
||||
if (!this.instance) {
|
||||
this.instance = new VpnConnectModel();
|
||||
}
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
setReplaceConnectVpn(vpnConfig: VpnConfig): void {
|
||||
this.replaceConnectVpnConfig = vpnConfig;
|
||||
}
|
||||
|
||||
setConnectState(state: number, id?: string): void {
|
||||
if (id) {
|
||||
this.connectedVpnId = id;
|
||||
}
|
||||
LogUtil.info(MODULE_TAG + `setConnectState: ${this.connectState} -> ${state} id:${this.connectedVpnId}`);
|
||||
this.connectState = state;
|
||||
AppStorage.setOrCreate(VpnConstant.STORAGE_KEY_CONNECT_STATE, state);
|
||||
}
|
||||
|
||||
getConnectedVpnId(): string {
|
||||
return this.connectedVpnId;
|
||||
}
|
||||
|
||||
isConnecting(vpnId: string): boolean {
|
||||
return (vpnId === this.connectedVpnId) &&
|
||||
(this.connectState === VpnConstant.VPN_STATE_CONNECTING);
|
||||
}
|
||||
|
||||
isConnectedOrConnecting(vpnId: string): boolean {
|
||||
let connectState = this.connectState;
|
||||
return (vpnId === this.connectedVpnId) &&
|
||||
((connectState === VpnConstant.VPN_STATE_CONNECTING) ||
|
||||
(connectState === VpnConstant.VPN_STATE_CONNECTED));
|
||||
}
|
||||
|
||||
onConnectStateChange(isConnected: boolean): void {
|
||||
LogUtil.info(MODULE_TAG + `onConnectStateChange isConnected=` + isConnected);
|
||||
this.removeTimeout();
|
||||
if (isConnected) {
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECTED);
|
||||
return;
|
||||
}
|
||||
if (this.replaceConnectVpnConfig) {
|
||||
let config = this.replaceConnectVpnConfig;
|
||||
this.replaceConnectVpnConfig = undefined;
|
||||
this.setUp(config);
|
||||
return;
|
||||
}
|
||||
if (this.connectState === VpnConstant.VPN_STATE_CONNECTING) {
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECT_FAILED);
|
||||
return;
|
||||
}
|
||||
if (this.connectState === VpnConstant.VPN_STATE_DISCONNECTING) {
|
||||
this.setConnectState(VpnConstant.VPN_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
init(context: common.UIAbilityContext): void {
|
||||
this.connection = vpn.createVpnConnection(context);
|
||||
try {
|
||||
LogUtil.info(MODULE_TAG + `vpn on start`);
|
||||
vpn.on('connect', (data) => {
|
||||
this.onConnectStateChange(data?.isConnected);
|
||||
})
|
||||
} catch (error) {
|
||||
LogUtil.error(MODULE_TAG + `vpn on error = ${JSON.stringify(error)}`);
|
||||
}
|
||||
this.getConnectedVpn();
|
||||
}
|
||||
|
||||
release(): void {
|
||||
try {
|
||||
LogUtil.info(MODULE_TAG + `vpnConnection on subscribe off start`);
|
||||
vpn.off('connect', (data) => {
|
||||
LogUtil.info(MODULE_TAG + `vpnConnection off data = ${data}`);
|
||||
})
|
||||
} catch (error) {
|
||||
LogUtil.error(MODULE_TAG + `vpnConnection off error = ${JSON.stringify(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
removeTimeout(): void {
|
||||
if (this.timeoutId !== undefined) {
|
||||
LogUtil.info(MODULE_TAG + `removeTimeout timeoutId = ${this.timeoutId}`);
|
||||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
}
|
||||
|
||||
async setUp(vpnConfig: VpnConfig): Promise<void> {
|
||||
if (vpnConfig === undefined || vpnConfig === null) {
|
||||
LogUtil.info(MODULE_TAG + `setUp failed, invalid param.`);
|
||||
return;
|
||||
}
|
||||
LogUtil.info(MODULE_TAG + `setUp start`);
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECTING, vpnConfig.vpnId);
|
||||
this.removeTimeout();
|
||||
this.timeoutId = setTimeout(() => {
|
||||
LogUtil.info(MODULE_TAG + `setUp timeout vpnId=` + vpnConfig.vpnId);
|
||||
this.setConnectState(VpnConstant.VPN_STATE_DISCONNECTING, vpnConfig.vpnId);
|
||||
this.destroy((error: string) => {
|
||||
if (error) {
|
||||
LogUtil.error(MODULE_TAG + `vpn destroy failed, error:` + error);
|
||||
}
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECT_FAILED, vpnConfig.vpnId);
|
||||
});
|
||||
}, VpnConstant.VPN_CONNECT_TIME_OUT_DURATION);
|
||||
try {
|
||||
await this.connection.setUp(vpnConfig);
|
||||
} catch (err) {
|
||||
LogUtil.error(MODULE_TAG + `setUp error = ${JSON.stringify(err)}`);
|
||||
this.removeTimeout();
|
||||
VpnConfigModel.getInstance().showToast($r('app.string.vpn_error_operation_failed') + ' error:' + err);
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECT_FAILED, vpnConfig.vpnId);
|
||||
// destroy connection
|
||||
this.destroy((error: string) => {
|
||||
if (error) {
|
||||
LogUtil.info(MODULE_TAG + `vpn destroy failed, error:` + error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getConnectedVpn(): void {
|
||||
try {
|
||||
LogUtil.info(MODULE_TAG + `getConnectedVpn start`);
|
||||
vpn.getConnectedSysVpnConfig().then((data) => {
|
||||
if (data && data.addresses && data.vpnId) {
|
||||
this.setConnectState(VpnConstant.VPN_STATE_CONNECTED, data.vpnId);
|
||||
} else {
|
||||
this.setConnectState(VpnConstant.VPN_STATE_NONE);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
LogUtil.error(MODULE_TAG + `getConnectedVpn error: ${JSON.stringify(error)}`);
|
||||
this.setConnectState(VpnConstant.VPN_STATE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
isHapAvailable(): boolean {
|
||||
return this.timeoutId !== undefined;
|
||||
}
|
||||
|
||||
destroy(callback): void {
|
||||
this.connection?.destroy((error: BusinessError) => {
|
||||
if (error) {
|
||||
LogUtil.info(MODULE_TAG + `destroy error = ${JSON.stringify(error)}`);
|
||||
}
|
||||
callback(error?.message);
|
||||
});
|
||||
}
|
||||
|
||||
uint8ArrayToString(u8a: Uint8Array): string {
|
||||
let dataStr = "";
|
||||
for (let i = 0; i < u8a.length; i++) {
|
||||
dataStr += String.fromCharCode(u8a[i])
|
||||
}
|
||||
return dataStr;
|
||||
}
|
||||
}
|
39
product/phone/src/main/ets/model/vpnImpl/VpnConstant.ts
Normal file
39
product/phone/src/main/ets/model/vpnImpl/VpnConstant.ts
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export default class VpnConstant {
|
||||
static readonly VPN_NAME_MAX_LENGTH: number = 30;
|
||||
static readonly VPN_USER_NAME_MAX_LENGTH: number = 30;
|
||||
static readonly VPN_PASSWORD_MAX_LENGTH: number = 30;
|
||||
static readonly INPUT_MAX_LENGTH: number = 100;
|
||||
|
||||
static readonly STORAGE_KEY_CONNECT_STATE: string = 'vpnConnectState';
|
||||
|
||||
static readonly VPN_STATE_NONE: number = 0;
|
||||
static readonly VPN_STATE_CONNECTING: number = 1; // connecting
|
||||
static readonly VPN_STATE_CONNECTED: number = 2; // connect success
|
||||
static readonly VPN_STATE_DISCONNECTING: number = 3; // not connect
|
||||
static readonly VPN_STATE_DISCONNECTED: number = 4; // not connect
|
||||
static readonly VPN_STATE_CONNECT_FAILED: number = 5; // connect failed
|
||||
|
||||
static readonly VPN_CONNECT_TIME_OUT_DURATION: number = 60000;
|
||||
|
||||
static readonly REGEX_IP: RegExp = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
static readonly REGEX_PORT: RegExp = /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
|
||||
|
||||
static readonly OVPN_AUTH_TYPE_TLS: number = 0;
|
||||
static readonly OVPN_AUTH_TYPE_PWD: number = 1;
|
||||
static readonly OVPN_AUTH_TYPE_TLS_PWD: number = 2;
|
||||
}
|
100
product/phone/src/main/ets/model/vpnImpl/VpnTypeModel.ts
Normal file
100
product/phone/src/main/ets/model/vpnImpl/VpnTypeModel.ts
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import parameter from '@ohos.systemParameterEnhance';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnTypeModel:';
|
||||
|
||||
/**
|
||||
* support vpn type & displayname
|
||||
*/
|
||||
export class VpnTypeModel {
|
||||
static readonly TYPE_IKEV2_IPSEC_MSCHAPv2: number = 1; // vpn.SysVpnType.IKEV2_IPSEC_MSCHAPv2;
|
||||
static readonly TYPE_IKEV2_IPSEC_PSK: number = 2; // vpn.SysVpnType.IKEV2_IPSEC_PSK;
|
||||
static readonly TYPE_IKEV2_IPSEC_RSA: number = 3; // vpn.SysVpnType.IKEV2_IPSEC_RSA;
|
||||
static readonly TYPE_L2TP_IPSEC_PSK: number = 4; // vpn.SysVpnType.L2TP_IPSEC_PSK;
|
||||
static readonly TYPE_L2TP_IPSEC_RSA: number = 5; // vpn.SysVpnType.L2TP_IPSEC_RSA;
|
||||
static readonly TYPE_IPSEC_XAUTH_PSK: number = 6; // vpn.SysVpnType.IPSEC_XAUTH_PSK;
|
||||
static readonly TYPE_IPSEC_XAUTH_RSA: number = 7; // vpn.SysVpnType.IPSEC_XAUTH_RSA;
|
||||
static readonly TYPE_IPSEC_HYBRID_RSA: number = 8; // vpn.SysVpnType.IPSEC_HYBRID_RSA;
|
||||
static readonly TYPE_OPENVPN: number = 9; // vpn.SysVpnType.OPENVPN;
|
||||
|
||||
private supportVpnTypes: number[] = [];
|
||||
private static instance: VpnTypeModel;
|
||||
|
||||
public static getInstance(): VpnTypeModel {
|
||||
if (!this.instance) {
|
||||
this.instance = new VpnTypeModel();
|
||||
}
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
let supportStr: string = parameter.getSync("const.product.supportVpn", "");
|
||||
supportStr.split(',').forEach((vpnTypeStr) => {
|
||||
let vpnType: number = Number(vpnTypeStr);
|
||||
switch (vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2:
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_PSK:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_RSA:
|
||||
case VpnTypeModel.TYPE_IPSEC_HYBRID_RSA:
|
||||
case VpnTypeModel.TYPE_OPENVPN:
|
||||
this.supportVpnTypes.push(vpnType);
|
||||
break;
|
||||
default :
|
||||
LogUtil.info(MODULE_TAG + supportStr + ` has unknown vpnType:` + vpnType);
|
||||
break;
|
||||
}
|
||||
})
|
||||
LogUtil.info(MODULE_TAG + `supportVpn ${this.supportVpnTypes}`);
|
||||
}
|
||||
|
||||
isSupportVpn(): boolean {
|
||||
return this.supportVpnTypes.length > 0;
|
||||
}
|
||||
|
||||
getSupportVpnTypes(): number[] {
|
||||
return this.supportVpnTypes;
|
||||
}
|
||||
|
||||
getSupportVpnTypeStrs(): string[] {
|
||||
let types: string[] = [];
|
||||
this.supportVpnTypes.forEach(type => {
|
||||
types.push(this.getVpnTypeStr(type))
|
||||
});
|
||||
return types;
|
||||
}
|
||||
|
||||
getVpnTypeStr(vpnType: number): string {
|
||||
switch (vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2: return 'IKEv2/IPSec MSCHAPv2';
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_PSK: return 'IKEv2/IPSec PSK';
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_RSA: return 'IKEv2/IPSec RSA';
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_PSK: return 'L2TP/IPSec PSK';
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_RSA: return 'L2TP/IPSec RSA';
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_PSK: return 'IPSec Xauth PSK';
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_RSA: return 'IPSec Xauth RSA';
|
||||
case VpnTypeModel.TYPE_IPSEC_HYBRID_RSA: return 'IPSec Hybrid RSA';
|
||||
case VpnTypeModel.TYPE_OPENVPN: return 'OpenVpn';
|
||||
default :
|
||||
LogUtil.warn(MODULE_TAG + 'getVpnTypeStr unknown vpnType:' + vpnType);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
@ -16,12 +16,15 @@
|
||||
import display from '@ohos.display';
|
||||
import deviceInfo from '@ohos.deviceInfo';
|
||||
import NfcModel from '../model/moreConnectionsImpl/NfcModel';
|
||||
import parameter from '@ohos.systemparameter';
|
||||
import LogUtil from '../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
import ConfigData from '../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
|
||||
import HeadComponent from '../../../../../../common/component/src/main/ets/default/headComponent';
|
||||
import {
|
||||
SubEntryComponent,
|
||||
SubEntryComponentWithEndText
|
||||
} from '../../../../../../common/component/src/main/ets/default/subEntryComponent';
|
||||
import { VpnTypeModel } from '../model/vpnImpl/VpnTypeModel';
|
||||
|
||||
const TAG = ConfigData.TAG + 'MoreConnections: ';
|
||||
const deviceTypeInfo = deviceInfo.deviceType;
|
||||
@ -38,6 +41,7 @@ struct MoreConnections {
|
||||
private maxScreenHeight: number = 0;
|
||||
private nfcImageWidth: number = 0;
|
||||
private nfcImageHeight: number = 0;
|
||||
private nfcSupport: string = 'false';
|
||||
|
||||
nfcStatusChange() {
|
||||
AppStorage.SetOrCreate("nfcStatusInfo", this.nfcStatus ? $r("app.string.enabled") : $r("app.string.disabled"))
|
||||
@ -48,13 +52,43 @@ struct MoreConnections {
|
||||
GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
|
||||
Column() {
|
||||
HeadComponent({ headName: $r('app.string.moreConnectionsTab'), isActive: true });
|
||||
|
||||
Column() {
|
||||
List() {
|
||||
// NFC
|
||||
if (this.nfcSupport === 'true') {
|
||||
ListItem() {
|
||||
SubEntryComponentWithEndText({
|
||||
targetPage: 'pages/nfc',
|
||||
title: $r('app.string.NFC'),
|
||||
endText: $nfcStatusInfo
|
||||
})
|
||||
.margin({ top: $r("app.float.distance_8") })
|
||||
}
|
||||
}
|
||||
// vpn
|
||||
if (VpnTypeModel.getInstance().isSupportVpn()) {
|
||||
ListItem() {
|
||||
SubEntryComponent({
|
||||
targetPage: 'pages/vpn/vpnList',
|
||||
title: $r("app.string.VPN"),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
.width(ConfigData.WH_100_100)
|
||||
.divider({
|
||||
strokeWidth: $r('app.float.divider_wh'),
|
||||
color: $r('sys.color.ohos_id_color_list_separator'),
|
||||
startMargin: $r('app.float.wh_value_15'),
|
||||
endMargin: $r('app.float.wh_value_15') })
|
||||
}
|
||||
.borderRadius($r("app.float.radius_16"))
|
||||
.backgroundColor($r("app.color.white_bg_color"))
|
||||
.width(ConfigData.WH_100_100)
|
||||
.margin({ top: $r("app.float.distance_12") })
|
||||
.padding({
|
||||
top: $r("app.float.distance_4"),
|
||||
bottom: $r("app.float.distance_4")
|
||||
})
|
||||
}
|
||||
.useSizeType({
|
||||
sm: { span: 4, offset: 0 },
|
||||
@ -71,6 +105,15 @@ struct MoreConnections {
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
this.nfcSupport = parameter.getSync('const.SystemCapability.Communication.NFC.Core', 'false');
|
||||
LogUtil.info(TAG + `nfcSupport ${this.nfcSupport}`);
|
||||
|
||||
if (this.nfcSupport === 'true') {
|
||||
this.nfcInit();
|
||||
}
|
||||
}
|
||||
|
||||
nfcInit(){
|
||||
LogUtil.info(TAG + 'aboutToAppear in');
|
||||
|
||||
try {
|
||||
@ -106,8 +149,7 @@ struct MoreConnections {
|
||||
this.nfcImageWidth = (this.maxScreenHeight / 2) * 0.8;
|
||||
this.nfcImageHeight = (this.maxScreenHeight / 2) * 0.8;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this.maxScreenHeight > this.maxScreenWidth / 2) {
|
||||
this.nfcImageWidth = (this.maxScreenWidth / 2) * 0.7;
|
||||
this.nfcImageHeight = (this.maxScreenWidth / 2) * 0.7;
|
||||
|
@ -25,6 +25,7 @@ import ConfigData from '../../../../../../common/utils/src/main/ets/default/base
|
||||
import ResourceUtil from '../../../../../../common/search/src/main/ets/default/common/ResourceUtil';
|
||||
import {SettingItemComponent} from '../../../../../../common/component/src/main/ets/default/settingItemComponent';
|
||||
import GlobalResourceManager from '../../../../../../common/utils/src/main/ets/default/baseUtil/GlobalResourceManager';
|
||||
import { VpnTypeModel } from '../model/vpnImpl/VpnTypeModel';
|
||||
|
||||
const deviceTypeInfo = deviceInfo.deviceType;
|
||||
|
||||
@ -120,22 +121,6 @@ struct SettingList {
|
||||
}
|
||||
LogUtil.info('CCCC settings SettingList aboutToAppear end');
|
||||
}
|
||||
|
||||
onPageShow() {
|
||||
LogUtil.info('CCCC settings SettingList onPageShow enter');
|
||||
FeatureAbility.getWant().then((want) => {
|
||||
if (want.uri === "wifi") {
|
||||
Router.replace({ uri: "pages/wifi" });
|
||||
} else if (want.uri === "bluetooth") {
|
||||
Router.replace({ uri: "pages/bluetooth" });
|
||||
} else if (want.uri === "volumeControl") {
|
||||
Router.replace({ uri: "pages/volumeControl" });
|
||||
} else if (want.uri === "locationServices") {
|
||||
Router.replace({ uri: "pages/locationServices" });
|
||||
}
|
||||
})
|
||||
LogUtil.info('CCCC settings SettingList onPageShow end');
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@ -272,13 +257,13 @@ struct EntryComponent {
|
||||
})
|
||||
}
|
||||
|
||||
if (this.info === 'true') {
|
||||
ListItem(){
|
||||
if (this.info === 'true' || VpnTypeModel.getInstance().isSupportVpn()) {
|
||||
ListItem() {
|
||||
// moreConnections
|
||||
SettingItemComponent({
|
||||
targetPage: "pages/moreConnections",
|
||||
settingTitle: $r("app.string.moreConnectionsTab"),
|
||||
settingEndText:$endTextEmpty,
|
||||
settingEndText: $endTextEmpty,
|
||||
settingIcon: "/res/image/ic_settings_more_connections.svg",
|
||||
})
|
||||
}
|
||||
|
224
product/phone/src/main/ets/pages/vpn/customComponent.ets
Normal file
224
product/phone/src/main/ets/pages/vpn/customComponent.ets
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import deviceInfo from '@ohos.deviceInfo';
|
||||
import fileIo from '@ohos.file.fs';
|
||||
import picker from '@ohos.file.picker';
|
||||
import util from '@ohos.util';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import { SelectDialog } from '@ohos.arkui.advanced.Dialog';
|
||||
import VpnConfig, { OpenVpnConfig } from '../../model/vpnImpl/VpnConfig';
|
||||
import { VpnTypeModel } from '../../model/vpnImpl/VpnTypeModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
export const SELECTER_VPNTYPE: number = 1;
|
||||
export const SELECTER_OVPN_PROTOCOL: number = 2;
|
||||
export const SELECTER_OVPN_AUTH: number = 3;
|
||||
export const deviceTypeInfo = deviceInfo.deviceType;
|
||||
|
||||
export const INPUT_TYPE_IP: number = 1;
|
||||
export const INPUT_TYPE_PORT: number = 2;
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:custom_component:';
|
||||
|
||||
@Component
|
||||
export struct TextWithInput {
|
||||
title: Resource | string = '';
|
||||
inputType: number | undefined = undefined;
|
||||
inputPlaceholder: Resource | string = '';
|
||||
maxLength: number = VpnConstant.INPUT_MAX_LENGTH;
|
||||
@Prop inputText: string = '';
|
||||
@State fontColor: ResourceColor = $r('app.color.font_color_182431');
|
||||
onChange: (value: string) => void = () => {};
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text(this.title)
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.fontColor($r('app.color.font_color_182431'))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.textAlign(TextAlign.Start)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.textAlign(TextAlign.Start)
|
||||
.padding({ left: 8 })
|
||||
.margin({ top: 10 });
|
||||
TextInput({ placeholder: this.inputPlaceholder, text: this.inputText }).onChange((value: string) => {
|
||||
if (this.inputType === INPUT_TYPE_IP) {
|
||||
if (VpnConstant.REGEX_IP.test(value)) {
|
||||
this.fontColor = $r('app.color.font_color_182431');
|
||||
} else {
|
||||
this.fontColor = $r('sys.color.ohos_id_color_warning');
|
||||
}
|
||||
}
|
||||
if (this.inputType === INPUT_TYPE_PORT) {
|
||||
if (VpnConstant.REGEX_PORT.test(value)) {
|
||||
this.fontColor = $r('app.color.font_color_182431');
|
||||
} else {
|
||||
this.fontColor = $r('sys.color.ohos_id_color_warning');
|
||||
}
|
||||
}
|
||||
this.onChange(value);
|
||||
}).padding({ left: 5 })
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.showUnderline(true)
|
||||
.height(45)
|
||||
.margin({ top: 5 })
|
||||
.fontColor(this.fontColor)
|
||||
.maxLength(this.maxLength);
|
||||
}.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
export struct Selector {
|
||||
title: string | Resource = '';
|
||||
@Link vpnConfig: VpnConfig;
|
||||
type: number = 0;
|
||||
sheetTitles: string[] = [];
|
||||
sheetInfos: SheetInfo[] = [];
|
||||
selectDialogController: CustomDialogController | undefined = undefined;
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Text(this.title)
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.fontColor($r('app.color.font_color_182431'))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.textAlign(TextAlign.Start)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.textAlign(TextAlign.Start)
|
||||
Blank()
|
||||
Text(this.sheetTitles[this.getSelectIndex(this.vpnConfig, this.type)])
|
||||
.padding({ right: 4 })
|
||||
Image($r('app.media.ic_settings_arrow'))
|
||||
.width($r('app.float.wh_value_12'))
|
||||
.height($r('app.float.wh_value_24'))
|
||||
.fillColor($r('sys.color.ohos_id_color_primary'))
|
||||
.opacity($r('app.float.opacity_0_2'))
|
||||
}
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.backgroundColor('#ffffff')
|
||||
.width('100%')
|
||||
.height($r('app.float.wh_value_56'))
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.padding({ left: 8, right: 8 })
|
||||
.onClick(() => {
|
||||
this.showSelectDialog();
|
||||
})
|
||||
}
|
||||
|
||||
getSelectIndex(vpnConfig: VpnConfig, selecter: number): number {
|
||||
if (selecter === SELECTER_VPNTYPE) {
|
||||
return VpnTypeModel.getInstance().getSupportVpnTypes().indexOf(vpnConfig.vpnType);
|
||||
} else if (selecter === SELECTER_OVPN_PROTOCOL) {
|
||||
let openvpn : OpenVpnConfig = vpnConfig as OpenVpnConfig;
|
||||
return openvpn.ovpnProtocol;
|
||||
} else if (selecter === SELECTER_OVPN_AUTH) {
|
||||
let openvpn : OpenVpnConfig = vpnConfig as OpenVpnConfig;
|
||||
return openvpn.ovpnAuthType;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
showSelectDialog() {
|
||||
this.selectDialogController = new CustomDialogController({
|
||||
builder: SelectDialog({
|
||||
title: this.title,
|
||||
selectedIndex: this.getSelectIndex(this.vpnConfig, this.type),
|
||||
confirm: {
|
||||
value: $r('app.string.cancel'),
|
||||
action: () => {
|
||||
this.selectDialogController?.close();
|
||||
},
|
||||
},
|
||||
radioContent: this.sheetInfos
|
||||
}),
|
||||
autoCancel: true,
|
||||
alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? DialogAlignment.Bottom : DialogAlignment.Center,
|
||||
offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 })
|
||||
});
|
||||
this.selectDialogController?.open();
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
export struct SelectFile {
|
||||
title: ResourceStr = '';
|
||||
@Prop vpnConfig: VpnConfig;
|
||||
@State fileName: string | undefined = undefined;
|
||||
realFilePath: string | undefined = undefined;
|
||||
callback?: (result: string[]) => void;
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Text(this.title)
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.fontColor($r('app.color.font_color_182431'))
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.textAlign(TextAlign.Start)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.textAlign(TextAlign.Start)
|
||||
Blank()
|
||||
Text(this.fileName ?? $r('app.string.vpn_edit_ovpn_click_select'))
|
||||
.padding({ right: 4 })
|
||||
Image($r('sys.media.ohos_ic_public_arrow_right')).width($r('app.float.wh_value_12'))
|
||||
.height($r('app.float.wh_value_24'))
|
||||
.fillColor($r('sys.color.ohos_id_color_primary'))
|
||||
.opacity($r('app.float.opacity_0_2'))
|
||||
}
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.backgroundColor('#ffffff')
|
||||
.width('100%')
|
||||
.height($r('app.float.wh_value_56'))
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.padding({ left: 8, right: 8 })
|
||||
.onClick(() => {
|
||||
this.pickFile((result: string[]) => {
|
||||
if (result) {
|
||||
this.fileName = result[0];
|
||||
this.callback!(result);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pickFile(callback: (result: string[]) => void): void {
|
||||
try {
|
||||
let selectOption = new picker.DocumentSelectOptions();
|
||||
let documentPicker = new picker.DocumentViewPicker();
|
||||
documentPicker.select(selectOption).then((result: Array<string>) => {
|
||||
if (result.length > 0) {
|
||||
let uri = result[0];
|
||||
let fileName = uri.substring(uri.lastIndexOf('/') + 1);
|
||||
let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY);
|
||||
let fileStat = fileIo.statSync(file.fd);
|
||||
let buf = new ArrayBuffer(fileStat.size);
|
||||
fileIo.readSync(file.fd, buf);
|
||||
fileIo.close(file.fd)
|
||||
let unit8 = new Uint8Array(buf);
|
||||
let content = new util.TextDecoder().decodeWithStream(unit8);
|
||||
callback([fileName, content]);
|
||||
}
|
||||
}).catch((err: BusinessError) => {
|
||||
LogUtil.error(MODULE_TAG + 'DocumentViewPicker select failed with err: ' + JSON.stringify(err));
|
||||
});
|
||||
} catch (error) {
|
||||
let err: BusinessError = error as BusinessError;
|
||||
LogUtil.error(MODULE_TAG + 'DocumentViewPicker failed with err: ' + JSON.stringify(err));
|
||||
}
|
||||
}
|
||||
}
|
301
product/phone/src/main/ets/pages/vpn/ipsecVpnEdit.ets
Normal file
301
product/phone/src/main/ets/pages/vpn/ipsecVpnEdit.ets
Normal file
@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { util } from '@kit.ArkTS';
|
||||
import { TextWithInput, SelectFile, INPUT_TYPE_IP } from './customComponent';
|
||||
import { IpsecVpnConfig } from '../../model/vpnImpl/VpnConfig';
|
||||
import { VpnTypeModel } from '../../model/vpnImpl/VpnTypeModel';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
@Component
|
||||
export default struct IpsecVpnEdit {
|
||||
onSaveBtnEnableChange: Function = (enabled: boolean) => {};
|
||||
@State @Watch('onVpnConfigChange') vpnConfig: IpsecVpnConfig = new IpsecVpnConfig();
|
||||
@State ipsecIdentifierVisibility: Visibility = Visibility.None;
|
||||
@State l2tpSecretVisibility: Visibility = Visibility.None;
|
||||
@State ipsecSecretVisibility: Visibility = Visibility.None;
|
||||
@State userCertVisibility: Visibility = Visibility.None;
|
||||
@State caServerCertVisibility: Visibility = Visibility.None;
|
||||
@State advanceChecked: boolean = false;
|
||||
@State vpnAddress: string = '';
|
||||
@State dnsAddress: string = '';
|
||||
vpnType: number = 0;
|
||||
base64Util = new util.Base64Helper();
|
||||
|
||||
aboutToAppear() {
|
||||
this.vpnAddress = VpnConfigModel.getInstance().getAddress(this.vpnConfig) ?? '';
|
||||
let dnsAddresses = this.vpnConfig.dnsAddresses;
|
||||
if (dnsAddresses) {
|
||||
this.dnsAddress = dnsAddresses[0];
|
||||
}
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
updateUI() {
|
||||
this.updateIpsecIdentifierVisibility();
|
||||
this.updateL2tpSecretVisibility();
|
||||
this.updateIpsecSecretVisibility();
|
||||
this.updateUserCertVisibility();
|
||||
this.updateCaServerCertVisibility();
|
||||
}
|
||||
|
||||
onVpnConfigChange() {
|
||||
if (this.vpnType !== this.vpnConfig.vpnType) {
|
||||
LogUtil.info('onVpnConfigChange ' + this.vpnType + '->' + this.vpnConfig.vpnType);
|
||||
this.vpnType = this.vpnConfig.vpnType;
|
||||
this.updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
onNonNullableParamChange(): void {
|
||||
let isNonNullParamReady = true;
|
||||
if (!VpnConstant.REGEX_IP.test(this.vpnAddress)) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
if (this.dnsAddress.length >0 && !VpnConstant.REGEX_IP.test(this.dnsAddress)) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
if (this.vpnConfig.vpnType !== VpnTypeModel.TYPE_L2TP_IPSEC_PSK) {
|
||||
if (this.ipsecIdentifierVisibility === Visibility.Visible && !this.vpnConfig.ipsecIdentifier) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
if (this.l2tpSecretVisibility === Visibility.Visible && !this.vpnConfig.l2tpSharedKey) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
}
|
||||
if (this.ipsecSecretVisibility === Visibility.Visible && !this.vpnConfig.ipsecPreSharedKey) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
this.onSaveBtnEnableChange(isNonNullParamReady);
|
||||
}
|
||||
|
||||
updateIpsecIdentifierVisibility(): void {
|
||||
switch (this.vpnConfig.vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2:
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_PSK:
|
||||
this.ipsecIdentifierVisibility = Visibility.Visible;
|
||||
break;
|
||||
default:
|
||||
this.ipsecIdentifierVisibility = Visibility.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateL2tpSecretVisibility(): void {
|
||||
switch (this.vpnConfig.vpnType) {
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_RSA:
|
||||
this.l2tpSecretVisibility = Visibility.Visible;
|
||||
break;
|
||||
default:
|
||||
this.l2tpSecretVisibility = Visibility.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateIpsecSecretVisibility(): void {
|
||||
switch (this.vpnConfig.vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_PSK:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_PSK:
|
||||
this.ipsecSecretVisibility = Visibility.Visible;
|
||||
break;
|
||||
default:
|
||||
this.ipsecSecretVisibility = Visibility.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateUserCertVisibility(): void {
|
||||
switch (this.vpnConfig.vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_RSA:
|
||||
this.userCertVisibility = Visibility.Visible;
|
||||
break;
|
||||
default:
|
||||
this.userCertVisibility = Visibility.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateCaServerCertVisibility(): void {
|
||||
switch (this.vpnConfig.vpnType) {
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_MSCHAPv2:
|
||||
case VpnTypeModel.TYPE_IKEV2_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_L2TP_IPSEC_RSA:
|
||||
case VpnTypeModel.TYPE_IPSEC_XAUTH_RSA:
|
||||
case VpnTypeModel.TYPE_IPSEC_HYBRID_RSA:
|
||||
this.caServerCertVisibility = Visibility.Visible;
|
||||
break;
|
||||
default:
|
||||
this.caServerCertVisibility = Visibility.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_serveraddress'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnAddress,
|
||||
inputType: INPUT_TYPE_IP,
|
||||
onChange: (value: string) => {
|
||||
this.vpnAddress = value.trim();
|
||||
VpnConfigModel.getInstance().setAddress(this.vpnConfig, this.vpnAddress);
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
})
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ipsecidentifier'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.ipsecIdentifier,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.ipsecIdentifier = value.trim();
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).visibility(this.ipsecIdentifierVisibility)
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_l2tpsecret'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.l2tpSharedKey,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.l2tpSharedKey = value.trim();
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).visibility(this.l2tpSecretVisibility)
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ipsecsecret'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.ipsecPreSharedKey,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.ipsecPreSharedKey = value.trim();
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).visibility(this.ipsecSecretVisibility)
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_usercert'),
|
||||
fileName: this.vpnConfig.ipsecPublicUserCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ipsecPublicUserCertFilePath = result[0];
|
||||
this.vpnConfig.
|
||||
ipsecPublicUserCertConfig = this.base64Util.encodeToStringSync(
|
||||
VpnConfigModel.getInstance().stringToUint8Array(result[1]));
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 15 })
|
||||
.visibility(this.userCertVisibility)
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_user_private_cert'),
|
||||
fileName: this.vpnConfig.ipsecPrivateUserCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ipsecPrivateUserCertFilePath = result[0];
|
||||
this.vpnConfig.
|
||||
ipsecPrivateUserCertConfig = this.base64Util.encodeToStringSync(
|
||||
VpnConfigModel.getInstance().stringToUint8Array(result[1]));
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 15 })
|
||||
.visibility(this.userCertVisibility)
|
||||
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_cacert'),
|
||||
fileName: this.vpnConfig.ipsecCaCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ipsecCaCertFilePath = result[0];
|
||||
this.vpnConfig.ipsecCaCertConfig = this.base64Util.encodeToStringSync(
|
||||
VpnConfigModel.getInstance().stringToUint8Array(result[1]));
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 10 })
|
||||
.visibility(this.caServerCertVisibility)
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_servercert'),
|
||||
fileName: this.vpnConfig.ipsecPublicServerCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ipsecPublicServerCertFilePath = result[0];
|
||||
this.vpnConfig.ipsecPublicServerCertConfig = this.base64Util.encodeToStringSync(
|
||||
VpnConfigModel.getInstance().stringToUint8Array(result[1]));
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 10 })
|
||||
.visibility(this.caServerCertVisibility)
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_server_private_cert'),
|
||||
fileName: this.vpnConfig.ipsecPrivateServerCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ipsecPrivateServerCertFilePath = result[0];
|
||||
this.vpnConfig.ipsecPrivateServerCertConfig = this.base64Util.encodeToStringSync(
|
||||
VpnConfigModel.getInstance().stringToUint8Array(result[1]));
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 10, bottom: 10 })
|
||||
.visibility(this.caServerCertVisibility)
|
||||
Row({ space: 10 }) {
|
||||
Checkbox().shape(CheckBoxShape.ROUNDED_SQUARE).onChange((value) => {
|
||||
this.advanceChecked = value;
|
||||
})
|
||||
Text($r('app.string.vpn_edit_advanced'))
|
||||
}.width('100%').margin({ left: 4 })
|
||||
Column({ space: 10 }) {
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_searchdomains'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.searchDomains?.[0],
|
||||
onChange: (value: string) => {
|
||||
let searchDomain = value.trim();
|
||||
if (searchDomain) {
|
||||
this.vpnConfig.searchDomains = [searchDomain];
|
||||
}
|
||||
}
|
||||
})
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_dnsaddresses'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.dnsAddress,
|
||||
inputType: INPUT_TYPE_IP,
|
||||
onChange: (value: string) => {
|
||||
this.dnsAddress = value.trim();
|
||||
if (this.dnsAddress && this.dnsAddress.length > 0) {
|
||||
this.vpnConfig.dnsAddresses = [this.dnsAddress];
|
||||
}
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
})
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_router'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.forwardingRoutes,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.forwardingRoutes = value.trim();
|
||||
}
|
||||
})
|
||||
}.width('100%')
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.visibility(this.advanceChecked ? Visibility.Visible : Visibility.None)
|
||||
}
|
||||
}
|
||||
}
|
274
product/phone/src/main/ets/pages/vpn/openVpnEdit.ets
Normal file
274
product/phone/src/main/ets/pages/vpn/openVpnEdit.ets
Normal file
@ -0,0 +1,274 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import ResourceManager from '@ohos.resourceManager';
|
||||
import {
|
||||
TextWithInput,
|
||||
Selector,
|
||||
SelectFile,
|
||||
SELECTER_OVPN_PROTOCOL,
|
||||
SELECTER_OVPN_AUTH,
|
||||
INPUT_TYPE_IP,
|
||||
INPUT_TYPE_PORT
|
||||
} from './customComponent';
|
||||
import { OpenVpnConfig } from '../../model/vpnImpl/VpnConfig';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
import { GlobalContext } from '../../../../../../../common/utils/src/main/ets/default/baseUtil/GlobalContext';
|
||||
|
||||
@Component
|
||||
export default struct OpenVpnEdit {
|
||||
onSaveBtnEnableChange: Function = (enabled: boolean) => {};
|
||||
@State vpnConfig: OpenVpnConfig = new OpenVpnConfig();
|
||||
@State vpnAddress: string = '';
|
||||
@State vpnPort: string = '';
|
||||
@State ovpnAdvanceChecked: boolean = false;
|
||||
@State ovpnProxyChecked: boolean = false;
|
||||
@State ovpnProxyHost: string = '';
|
||||
@State ovpnProxyPort: string = '';
|
||||
|
||||
ovpnProtocolSheetTitles: string[] = [];
|
||||
ovpnProtocolSheets: SheetInfo[] = [];
|
||||
ovpnAuthSheetTitles: string[] = [];
|
||||
ovpnAuthSheets: SheetInfo[] = [];
|
||||
|
||||
aboutToAppear() {
|
||||
try {
|
||||
let context = GlobalContext.getContext().getObject(GlobalContext.globalKeySettingsAbilityContext) as Context;
|
||||
let resMgr: ResourceManager.ResourceManager = context.resourceManager;
|
||||
this.vpnConfig.ovpnProtocol = this.vpnConfig.ovpnProtocol ?? 0;
|
||||
this.ovpnProtocolSheetTitles = resMgr.getStringArrayValueSync($r('app.strarray.ovpn_protocol').id);
|
||||
this.ovpnProtocolSheets = this.ovpnProtocolSheetTitles.map((title, index) => {
|
||||
let sheetInfo: SheetInfo = {
|
||||
title: title,
|
||||
action: () => {
|
||||
this.vpnConfig.ovpnProtocol = index;
|
||||
}
|
||||
}
|
||||
return sheetInfo;
|
||||
})
|
||||
this.vpnConfig.ovpnAuthType = this.vpnConfig.ovpnAuthType ?? 0;
|
||||
this.ovpnAuthSheetTitles = resMgr.getStringArrayValueSync($r('app.strarray.ovpn_auth_type').id);
|
||||
this.ovpnAuthSheets = this.ovpnAuthSheetTitles.map((title, index) => {
|
||||
let sheetInfo: SheetInfo = {
|
||||
title: title,
|
||||
action: () => {
|
||||
this.vpnConfig.ovpnAuthType = index;
|
||||
}
|
||||
}
|
||||
return sheetInfo;
|
||||
})
|
||||
} catch (error) {
|
||||
LogUtil.error(`getStringArrayValueSync failed, error: ${JSON.stringify(error)}.`);
|
||||
}
|
||||
|
||||
this.updateUI();
|
||||
}
|
||||
|
||||
updateUI() {
|
||||
this.vpnAddress = VpnConfigModel.getInstance().getAddress(this.vpnConfig) ?? '';
|
||||
this.vpnPort = this.vpnConfig.ovpnPort ?? '';
|
||||
}
|
||||
|
||||
onNonNullableParamChange(): void {
|
||||
let isNonNullParamReady = true;
|
||||
if (!VpnConstant.REGEX_IP.test(this.vpnAddress) || !VpnConstant.REGEX_PORT.test(this.vpnPort)) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
if (this.ovpnProxyHost.length > 0 && !VpnConstant.REGEX_IP.test(this.ovpnProxyHost)) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
if (this.ovpnProxyPort.length > 0 && !VpnConstant.REGEX_PORT.test(this.ovpnProxyPort)) {
|
||||
isNonNullParamReady = false;
|
||||
}
|
||||
this.onSaveBtnEnableChange(isNonNullParamReady);
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_ovpn_configfile'),
|
||||
fileName: this.vpnConfig.ovpnConfigFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
VpnConfigModel.getInstance().inflateConfigFromFileData(this.vpnConfig, result);
|
||||
this.updateUI();
|
||||
}
|
||||
});
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_serveraddress'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnAddress,
|
||||
inputType: INPUT_TYPE_IP,
|
||||
onChange: (value: string) => {
|
||||
this.vpnAddress = value.trim();
|
||||
VpnConfigModel.getInstance().setAddress(this.vpnConfig, this.vpnAddress);
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
}).margin({ top: 5 })
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_port'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnPort,
|
||||
inputType: INPUT_TYPE_PORT,
|
||||
onChange: (value: string) => {
|
||||
this.vpnPort = value.trim()
|
||||
this.vpnConfig.ovpnPort = this.vpnPort;
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
})
|
||||
|
||||
Selector({
|
||||
title: $r('app.string.vpn_edit_ovpn_protocol'),
|
||||
vpnConfig: this.vpnConfig,
|
||||
type: SELECTER_OVPN_PROTOCOL,
|
||||
sheetTitles: this.ovpnProtocolSheetTitles,
|
||||
sheetInfos: this.ovpnProtocolSheets
|
||||
}).margin({ top: 10, bottom: 10 });
|
||||
|
||||
Row({ space: 10 }) {
|
||||
Checkbox().shape(CheckBoxShape.ROUNDED_SQUARE).onChange((value) => {
|
||||
this.ovpnAdvanceChecked = value;
|
||||
})
|
||||
Text($r('app.string.vpn_edit_advanced'))
|
||||
}.width('100%').margin({ left: 4, bottom: 10 })
|
||||
|
||||
Column({ space: 10 }) {
|
||||
Selector({
|
||||
title: $r('app.string.vpn_edit_auth_type'),
|
||||
vpnConfig: this.vpnConfig,
|
||||
type: SELECTER_OVPN_AUTH,
|
||||
sheetTitles: this.ovpnAuthSheetTitles,
|
||||
sheetInfos: this.ovpnAuthSheets
|
||||
})
|
||||
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_ovpn_ca_cert_file'),
|
||||
fileName: this.vpnConfig.ovpnCaCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ovpnCaCertFilePath = result[0];
|
||||
this.vpnConfig.ovpnCaCert = '<ca>\n' + result[1] + '\n</ca>';
|
||||
}
|
||||
});
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_ovpn_user_cert_file'),
|
||||
fileName: this.vpnConfig.ovpnUserCertFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ovpnUserCertFilePath = result[0];
|
||||
this.vpnConfig.ovpnUserCert = '<cert>\n' + result[1] + '\n</cert>';
|
||||
}
|
||||
}).visibility(this.vpnConfig.ovpnAuthType !== VpnConstant.OVPN_AUTH_TYPE_PWD ?
|
||||
Visibility.Visible : Visibility.None);
|
||||
|
||||
SelectFile({
|
||||
title: $r('app.string.vpn_edit_ovpn_private_key'),
|
||||
fileName: this.vpnConfig.ovpnPrivateKeyFilePath,
|
||||
vpnConfig: this.vpnConfig,
|
||||
callback: (result: string[]) => {
|
||||
this.vpnConfig.ovpnPrivateKeyFilePath = result[0];
|
||||
this.vpnConfig.ovpnPrivateKey = '<key>\n' + result[1] + '\n</key>';
|
||||
}
|
||||
}).visibility(this.vpnConfig.ovpnAuthType !== VpnConstant.OVPN_AUTH_TYPE_PWD ?
|
||||
Visibility.Visible : Visibility.None);
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_private_key_psd'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnConfig.askpass,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.askpass = value.trim();
|
||||
}
|
||||
}).visibility(this.vpnConfig.ovpnAuthType !== VpnConstant.OVPN_AUTH_TYPE_PWD ?
|
||||
Visibility.Visible : Visibility.None);
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_username'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnConfig.userName,
|
||||
maxLength: VpnConstant.VPN_USER_NAME_MAX_LENGTH,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.userName = value.trim();
|
||||
}
|
||||
}).visibility(this.vpnConfig.ovpnAuthType !== VpnConstant.OVPN_AUTH_TYPE_TLS ?
|
||||
Visibility.Visible : Visibility.None);
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_password'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnConfig.password,
|
||||
maxLength: VpnConstant.VPN_PASSWORD_MAX_LENGTH,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.password = value.trim();
|
||||
}
|
||||
}).visibility(this.vpnConfig.ovpnAuthType !== VpnConstant.OVPN_AUTH_TYPE_TLS ?
|
||||
Visibility.Visible : Visibility.None);
|
||||
|
||||
Row({ space: 10 }) {
|
||||
Checkbox().shape(CheckBoxShape.ROUNDED_SQUARE).onChange((value) => {
|
||||
this.ovpnProxyChecked = value;
|
||||
})
|
||||
Text($r('app.string.vpn_edit_proxy_advanced'))
|
||||
}.width('100%').margin({ left: 4 })
|
||||
|
||||
Column({ space: 10 }) {
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_proxy_host'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.ovpnProxyHost,
|
||||
inputType: INPUT_TYPE_IP,
|
||||
onChange: (value: string) => {
|
||||
this.ovpnProxyHost = value.trim();
|
||||
this.vpnConfig.ovpnProxyHost = this.ovpnProxyHost;
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
})
|
||||
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_proxy_port'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.ovpnProxyPort,
|
||||
inputType: INPUT_TYPE_PORT,
|
||||
onChange: (value: string) => {
|
||||
this.ovpnProxyPort = value.trim();
|
||||
this.vpnConfig.ovpnProxyPort = this.ovpnProxyPort;
|
||||
this.onNonNullableParamChange();
|
||||
}
|
||||
})
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_proxy_username'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.ovpnProxyUser,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.ovpnProxyUser = value.trim();
|
||||
}
|
||||
})
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_ovpn_proxy_password'),
|
||||
inputPlaceholder: $r('app.string.vpn_edit_unuse'),
|
||||
inputText: this.vpnConfig.ovpnProxyPass,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.ovpnProxyPass = value.trim();
|
||||
}
|
||||
})
|
||||
}.visibility(this.ovpnProxyChecked ? Visibility.Visible : Visibility.None)
|
||||
}.visibility(this.ovpnAdvanceChecked ? Visibility.Visible : Visibility.None)
|
||||
}
|
||||
}
|
||||
}
|
230
product/phone/src/main/ets/pages/vpn/vpnConnect.ets
Normal file
230
product/phone/src/main/ets/pages/vpn/vpnConnect.ets
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import deviceInfo from '@ohos.deviceInfo';
|
||||
import router from '@ohos.router';
|
||||
import util from '@ohos.util';
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import { VpnConnectModel } from '../../model/vpnImpl/VpnConnectModel';
|
||||
import VpnConfig, { VpnListItem } from '../../model/vpnImpl/VpnConfig';
|
||||
import { SwanCtlModel } from '../../model/vpnImpl/SwanCtlModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import { ResourceUtils } from '../../model/accessibilityImpl/resourceUtils';
|
||||
import HeadComponent from '../../../../../../../common/component/src/main/ets/default/headComponent';
|
||||
import ConfigData from '../../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const deviceTypeInfo = deviceInfo.deviceType;
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnConnect:';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
export struct VpnConnect {
|
||||
@StorageLink('connectState') connectState: number = VpnConstant.VPN_STATE_NONE;
|
||||
@State vpnConfig: VpnConfig = new VpnConfig();
|
||||
@State vpnUserName: string = '';
|
||||
@State vpnPassword: string = '';
|
||||
@State isSetupBtnEnabled: boolean = false;
|
||||
|
||||
async aboutToAppear() {
|
||||
let state: number | undefined = AppStorage.get(VpnConstant.STORAGE_KEY_CONNECT_STATE);
|
||||
if (state) {
|
||||
this.connectState = state;
|
||||
}
|
||||
let vpnItem: VpnListItem = router.getParams() as VpnListItem;
|
||||
if (vpnItem && vpnItem.vpnId) {
|
||||
LogUtil.info(MODULE_TAG + `vpnid = ${JSON.stringify(vpnItem.vpnId)}`)
|
||||
try {
|
||||
let data: vpn.SysVpnConfig = await vpn.getSysVpnConfig(vpnItem.vpnId);
|
||||
if (data) {
|
||||
this.vpnConfig = data as VpnConfig;
|
||||
if (this.vpnConfig.saveLogin) {
|
||||
this.vpnUserName = this.vpnConfig.userName ?? '';
|
||||
this.vpnPassword = this.vpnConfig.password ?? '';
|
||||
}
|
||||
this.setConnectBtnEnabled();
|
||||
} else {
|
||||
VpnConfigModel.getInstance().showToast($r('app.string.vpn_error_operation_failed'));
|
||||
}
|
||||
} catch (err) {
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(
|
||||
ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
} else {
|
||||
LogUtil.error(MODULE_TAG + `getParams is error`)
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
HeadComponent({
|
||||
headName: $r('app.string.vpn_connect_title', this.vpnConfig.vpnName),
|
||||
isActive: true
|
||||
}).padding({ right: 35 })
|
||||
|
||||
Column() {
|
||||
Column() {
|
||||
Text($r('app.string.vpn_connect_username'))
|
||||
.width('100%')
|
||||
TextInput({ text: this.vpnUserName })
|
||||
.padding({ left: 1 })
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.maxLength(VpnConstant.VPN_USER_NAME_MAX_LENGTH)
|
||||
.backgroundColor('#00000000')
|
||||
.height(40)
|
||||
.onChange((value) => {
|
||||
value = value.replace(/\s+/g, '');
|
||||
this.vpnUserName = value.trim();
|
||||
this.setConnectBtnEnabled();
|
||||
})
|
||||
Divider()
|
||||
.color($r('sys.color.ohos_id_color_list_separator'))
|
||||
Text($r('app.string.vpn_connect_password'))
|
||||
.width('100%')
|
||||
.margin({ top: 15 })
|
||||
TextInput({ text: this.vpnPassword })
|
||||
.padding({ left: 1 })
|
||||
.type(InputType.Password)
|
||||
.maxLength(VpnConstant.VPN_PASSWORD_MAX_LENGTH)
|
||||
.fontSize($r('app.float.font_16'))
|
||||
.backgroundColor('#00000000')
|
||||
.height(40)
|
||||
.onChange((value) => {
|
||||
value = value.replace(/\s+/g, '');
|
||||
this.vpnPassword = value.trim();
|
||||
this.setConnectBtnEnabled();
|
||||
})
|
||||
Divider()
|
||||
.color($r('sys.color.ohos_id_color_list_separator'))
|
||||
|
||||
Row({ space: 8 }) {
|
||||
Checkbox().select(this.vpnConfig.saveLogin ?? false).onChange((value) => {
|
||||
this.vpnConfig.saveLogin = value;
|
||||
}).shape(CheckBoxShape.ROUNDED_SQUARE)
|
||||
Text($r('app.string.vpn_connect_save'))
|
||||
}.width('100%').margin({ top: 15 })
|
||||
}
|
||||
|
||||
Blank().layoutWeight(1)
|
||||
Row() {
|
||||
Button($r('app.string.cancel'))
|
||||
.fontColor('#0A59F7')
|
||||
.fontSize(16)
|
||||
.height(45)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.padding({ top: 10, left: 60, right: 60, bottom: 10 })
|
||||
.borderRadius($r('app.float.radius_20'))
|
||||
.backgroundColor('#E6E8E9')
|
||||
.layoutWeight(1)
|
||||
.onClick(() => {
|
||||
router.back();
|
||||
})
|
||||
Blank().width(30)
|
||||
Button($r('app.string.vpn_connect_confirm'))
|
||||
.fontColor(this.isSetupBtnEnabled ? '#0A59F7' : '#92B3F3')
|
||||
.fontSize(16)
|
||||
.height(45)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.padding({ top: 10, left: 60, right: 60, bottom: 10 })
|
||||
.borderRadius($r('app.float.radius_20'))
|
||||
.backgroundColor('#E6E8E9')
|
||||
.layoutWeight(1)
|
||||
.enabled(this.isSetupBtnEnabled)
|
||||
.onClick(() => {
|
||||
this.onSetupBtnClick();
|
||||
})
|
||||
}.margin({ bottom: 65 })
|
||||
}
|
||||
.padding($r('app.float.distance_4'))
|
||||
}
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
.padding({ left: ConfigData.GRID_CONTAINER_MARGIN_24, right: ConfigData.GRID_CONTAINER_MARGIN_24, bottom: 20 })
|
||||
.backgroundColor($r('sys.color.ohos_id_color_sub_background'))
|
||||
}
|
||||
|
||||
async onSetupBtnClick() {
|
||||
LogUtil.info(MODULE_TAG + `onSetupBtnClick current connect = ${JSON.stringify(this.connectState)}`);
|
||||
if (this.connectState === VpnConstant.VPN_STATE_CONNECTED ||
|
||||
this.connectState === VpnConstant.VPN_STATE_CONNECTING) {
|
||||
this.showVpnChangeDialog();
|
||||
return;
|
||||
}
|
||||
if ((!this.vpnConfig.userName || !this.vpnConfig.password) ||
|
||||
this.vpnUserName !== this.vpnConfig.userName || this.vpnPassword !== this.vpnConfig.password) {
|
||||
this.vpnConfig.userName = this.vpnUserName;
|
||||
this.vpnConfig.password = this.vpnPassword;
|
||||
// name and pwd changed, need to rebuild config
|
||||
this.vpnConfig = SwanCtlModel.getInstance().buildConfig(this.vpnConfig);
|
||||
if (!this.vpnConfig.vpnId || this.vpnConfig.vpnId === '') {
|
||||
this.vpnConfig.vpnId = util.generateRandomUUID();
|
||||
}
|
||||
try {
|
||||
await vpn.addSysVpnConfig(this.vpnConfig);
|
||||
VpnConnectModel.getInstance().setUp(this.vpnConfig);
|
||||
} catch (err) {
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
router.back();
|
||||
return;
|
||||
}
|
||||
VpnConnectModel.getInstance().setUp(this.vpnConfig);
|
||||
router.back();
|
||||
}
|
||||
|
||||
setConnectBtnEnabled() {
|
||||
if (this.vpnUserName === '' || this.vpnPassword === '') {
|
||||
this.isSetupBtnEnabled = false;
|
||||
} else {
|
||||
this.isSetupBtnEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
showVpnChangeDialog(): void {
|
||||
AlertDialog.show({
|
||||
title: $r('app.string.vpn_change_alert_title'),
|
||||
message: $r('app.string.vpn_change_alert_content'),
|
||||
primaryButton: {
|
||||
value: $r('app.string.cancel'),
|
||||
action: () => {
|
||||
LogUtil.info('dialog cancel callbacks');
|
||||
}
|
||||
},
|
||||
secondaryButton: {
|
||||
value: $r('app.string.vpn_change_alert_confirm'),
|
||||
action: () => {
|
||||
VpnConnectModel.getInstance().setConnectState(VpnConstant.VPN_STATE_DISCONNECTING);
|
||||
VpnConnectModel.getInstance().setReplaceConnectVpn(this.vpnConfig);
|
||||
VpnConnectModel.getInstance().destroy((error: string) => {
|
||||
if (error) {
|
||||
LogUtil.info(MODULE_TAG + `vpn destroy failed, error:` + error);
|
||||
}
|
||||
});
|
||||
router.back();
|
||||
}
|
||||
},
|
||||
alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ?
|
||||
DialogAlignment.Bottom : DialogAlignment.Center,
|
||||
offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
263
product/phone/src/main/ets/pages/vpn/vpnEdit.ets
Normal file
263
product/phone/src/main/ets/pages/vpn/vpnEdit.ets
Normal file
@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import router from '@ohos.router';
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import util from '@ohos.util';
|
||||
import window from '@ohos.window';
|
||||
import OpenVpnEdit from './openVpnEdit';
|
||||
import IpsecVpnEdit from './ipsecVpnEdit';
|
||||
import { TextWithInput, Selector, SELECTER_VPNTYPE, deviceTypeInfo } from './customComponent';
|
||||
import { VpnTypeModel } from '../../model/vpnImpl/VpnTypeModel';
|
||||
import { VpnConnectModel } from '../../model/vpnImpl/VpnConnectModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import { ResourceUtils } from '../../model/accessibilityImpl/resourceUtils';
|
||||
import VpnConfig, { OpenVpnConfig, IpsecVpnConfig } from '../../model/vpnImpl/VpnConfig';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
import ConfigData from '../../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
|
||||
import HeadComponent from '../../../../../../../common/component/src/main/ets/default/headComponent';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnEdit:';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
export struct VpnEdit {
|
||||
@State vpnConfig: VpnConfig = new VpnConfig();
|
||||
@State isSaveBtnEnabled: boolean = false;
|
||||
@State isDelBtnVisibility: Visibility = Visibility.None;
|
||||
protocolSheets: SheetInfo[] = [];
|
||||
|
||||
aboutToAppear() {
|
||||
window.getLastWindow(getContext(this), (err, w) => {
|
||||
w.setWindowSystemBarProperties({
|
||||
statusBarColor: '#ffffff'
|
||||
})
|
||||
})
|
||||
let param = router.getParams();
|
||||
if (param) {
|
||||
this.vpnConfig = param as VpnConfig;
|
||||
}
|
||||
this.isDelBtnVisibility = this.vpnConfig.vpnName ? Visibility.Visible : Visibility.None;
|
||||
|
||||
this.protocolSheets = VpnTypeModel.getInstance().getSupportVpnTypeStrs().map((str, index) => {
|
||||
let s: SheetInfo = {
|
||||
title: str,
|
||||
action: () => {
|
||||
this.vpnConfig.vpnType = (index < VpnTypeModel.getInstance().getSupportVpnTypes().length) ?
|
||||
VpnTypeModel.getInstance().getSupportVpnTypes()[index] : 0;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
})
|
||||
}
|
||||
|
||||
onSaveBtnEnableChange: Function = (enabled: boolean) => {
|
||||
this.isSaveBtnEnabled = enabled && this.vpnConfig.vpnName.length > 0;
|
||||
}
|
||||
|
||||
async onSaveClick() {
|
||||
if (!this.vpnConfig.vpnName || this.vpnConfig.vpnName.length < 1) {
|
||||
VpnConfigModel.getInstance().showToast($r('app.string.vpn_error_invalid_param'));
|
||||
return;
|
||||
}
|
||||
// destroy connect when vpn connected
|
||||
if (VpnConnectModel.getInstance().isConnectedOrConnecting(this.vpnConfig.vpnId)) {
|
||||
VpnConfigModel.getInstance().showToast($r('app.string.vpn_error_disconnect_first'))
|
||||
return;
|
||||
}
|
||||
|
||||
VpnConfigModel.getInstance().prepareAddSysVpnConfig(this.vpnConfig);
|
||||
if (!this.vpnConfig.vpnId || this.vpnConfig.vpnId === '') {
|
||||
this.vpnConfig.vpnId = util.generateRandomUUID();
|
||||
}
|
||||
try {
|
||||
await vpn.addSysVpnConfig(this.vpnConfig);
|
||||
VpnConfigModel.getInstance().setNeedUpdateVpnList(true);
|
||||
this.backToListPage();
|
||||
} catch (err) {
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(
|
||||
ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
backToListPage() {
|
||||
router.back();
|
||||
}
|
||||
|
||||
async onDeleteClick() {
|
||||
if (!this.vpnConfig) {
|
||||
LogUtil.error(MODULE_TAG + 'onDeleteClick failed, vpn config is error');
|
||||
return;
|
||||
}
|
||||
if (!this.vpnConfig.vpnId || this.vpnConfig.vpnId === '') {
|
||||
LogUtil.error(MODULE_TAG + 'onDeleteClick failed, vpnId is error');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await vpn.deleteSysVpnConfig(this.vpnConfig.vpnId);
|
||||
VpnConfigModel.getInstance().setNeedUpdateVpnList(true);
|
||||
this.backToListPage();
|
||||
}catch (err){
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(
|
||||
ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
showDeleteDialog(): void {
|
||||
AlertDialog.show({
|
||||
message: $r('app.string.vpn_line_remove_alert_title', this.vpnConfig.vpnName),
|
||||
primaryButton: {
|
||||
value: $r('app.string.cancel'),
|
||||
action: () => {
|
||||
LogUtil.info('dialog cancel callbacks');
|
||||
}
|
||||
},
|
||||
secondaryButton: {
|
||||
fontColor: $r('sys.color.ohos_id_color_warning'),
|
||||
value: $r('app.string.vpn_line_remove_alert_confirm'),
|
||||
action: () => {
|
||||
this.onDeleteClick();
|
||||
}
|
||||
},
|
||||
alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ?
|
||||
DialogAlignment.Bottom : DialogAlignment.Center,
|
||||
offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 })
|
||||
})
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
|
||||
RelativeContainer() {
|
||||
HeadComponent({ headName: $r('app.string.vpn_edit_title'), isActive: true }).alignRules({
|
||||
top: { anchor: '__container__', align: VerticalAlign.Top },
|
||||
left: { anchor: '__container__', align: HorizontalAlign.Start }
|
||||
}).id('head')
|
||||
|
||||
Scroll() {
|
||||
Column({ space: 10 }) {
|
||||
TextWithInput({
|
||||
title: $r('app.string.vpn_edit_alias'),
|
||||
inputPlaceholder: '',
|
||||
inputText: this.vpnConfig.vpnName,
|
||||
maxLength: VpnConstant.VPN_NAME_MAX_LENGTH,
|
||||
onChange: (value: string) => {
|
||||
this.vpnConfig.vpnName = value.trim();
|
||||
this.onSaveBtnEnableChange(this.vpnConfig.vpnName.length > 0 ? true : false);
|
||||
}
|
||||
})
|
||||
Text($r('app.string.vpn_line_disconnect_operation_remove'))
|
||||
.fontColor($r('sys.color.ohos_id_color_badge_red'))
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.width(ConfigData.WH_100_100)
|
||||
.textAlign(TextAlign.Center)
|
||||
.onClick(() => {
|
||||
if (VpnConnectModel.getInstance().isConnectedOrConnecting(this.vpnConfig.vpnId)) {
|
||||
VpnConfigModel.getInstance().showToast($r('app.string.vpn_error_disconnect_first'))
|
||||
} else {
|
||||
this.showDeleteDialog();
|
||||
}
|
||||
})
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.backgroundColor('#ffffff')
|
||||
.width('100%')
|
||||
.height($r('app.float.wh_value_52'))
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.padding({ left: 8, right: 8 })
|
||||
.visibility(this.isDelBtnVisibility)
|
||||
|
||||
Selector({
|
||||
title: $r('app.string.vpn_edit_type'),
|
||||
vpnConfig: this.vpnConfig,
|
||||
type: SELECTER_VPNTYPE,
|
||||
sheetTitles: VpnTypeModel.getInstance().getSupportVpnTypeStrs(),
|
||||
sheetInfos: this.protocolSheets,
|
||||
}).enabled(this.isDelBtnVisibility !== Visibility.Visible)
|
||||
|
||||
if (this.vpnConfig.vpnType === VpnTypeModel.TYPE_OPENVPN) {
|
||||
OpenVpnEdit({
|
||||
vpnConfig: this.vpnConfig as OpenVpnConfig,
|
||||
onSaveBtnEnableChange: this.onSaveBtnEnableChange,
|
||||
})
|
||||
} else {
|
||||
IpsecVpnEdit({
|
||||
vpnConfig: this.vpnConfig as IpsecVpnConfig,
|
||||
onSaveBtnEnableChange: this.onSaveBtnEnableChange,
|
||||
})
|
||||
}
|
||||
Blank().layoutWeight(1)
|
||||
}.alignItems(HorizontalAlign.Start).width(ConfigData.WH_100_100)
|
||||
}.alignRules({
|
||||
top: { anchor: 'head', align: VerticalAlign.Bottom },
|
||||
left: { anchor: '__container__', align: HorizontalAlign.Start },
|
||||
right: { anchor: '__container__', align: HorizontalAlign.End },
|
||||
bottom: { anchor: 'bottom', align: VerticalAlign.Top }
|
||||
}).id('content')
|
||||
|
||||
Row() {
|
||||
Button($r('app.string.cancel'))
|
||||
.fontColor('#0A59F7')
|
||||
.fontSize(16)
|
||||
.height(45)
|
||||
.layoutWeight(1)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.padding({ top: 10, left: 60, right: 60, bottom: 10 })
|
||||
.borderRadius($r('app.float.radius_20'))
|
||||
.backgroundColor('#E6E8E9')
|
||||
.onClick(() => {
|
||||
this.backToListPage();
|
||||
})
|
||||
Blank().width(30)
|
||||
Button($r('app.string.vpn_edit_save'))
|
||||
.fontColor(this.isSaveBtnEnabled ? '#0A59F7' : '#92B3F3')
|
||||
.fontSize(16)
|
||||
.height(45)
|
||||
.layoutWeight(1)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.padding({ top: 10, left: 60, right: 60, bottom: 10 })
|
||||
.borderRadius($r('app.float.radius_20'))
|
||||
.backgroundColor('#E6E8E9')
|
||||
.enabled(this.isSaveBtnEnabled)
|
||||
.background()
|
||||
.onClick(() => {
|
||||
this.onSaveClick();
|
||||
})
|
||||
}.margin(15).alignRules({
|
||||
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
|
||||
left: { anchor: '__container__', align: HorizontalAlign.Start }
|
||||
}).id('bottom')
|
||||
|
||||
}.width(ConfigData.WH_100_100).height(ConfigData.WH_100_100)
|
||||
.useSizeType({
|
||||
sm: { span: 4, offset: 0 },
|
||||
md: { span: 6, offset: 1 },
|
||||
lg: { span: 8, offset: 2 }
|
||||
})
|
||||
}
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
}
|
||||
.backgroundColor($r('sys.color.ohos_id_color_sub_background'))
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
235
product/phone/src/main/ets/pages/vpn/vpnLine.ets
Normal file
235
product/phone/src/main/ets/pages/vpn/vpnLine.ets
Normal file
@ -0,0 +1,235 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import deviceInfo from '@ohos.deviceInfo';
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import router from '@ohos.router';
|
||||
import { VpnConnectModel } from '../../model/vpnImpl/VpnConnectModel';
|
||||
import VpnConfig, { VpnListItem } from '../../model/vpnImpl/VpnConfig';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import VpnConstant from '../../model/vpnImpl/VpnConstant';
|
||||
import { ResourceUtils } from '../../model/accessibilityImpl/resourceUtils';
|
||||
import ComponentConfig from '../../../../../../../common/component/src/main/ets/default/ComponentConfig';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VpnLine:';
|
||||
const deviceTypeInfo = deviceInfo.deviceType;
|
||||
|
||||
/**
|
||||
* item custom component
|
||||
*/
|
||||
@Entry
|
||||
@Component
|
||||
export default struct VpnLine {
|
||||
@StorageLink(VpnConstant.STORAGE_KEY_CONNECT_STATE) @Watch('onConnectStateChange') connectState: number =
|
||||
VpnConstant.VPN_STATE_NONE;
|
||||
@State connectStateLabel: string | Resource = '';
|
||||
@State vpnListItem: VpnListItem | undefined = undefined;
|
||||
@State titleFontColor: Resource = $r('sys.color.ohos_id_color_text_primary');
|
||||
@State isTouched: boolean = false;
|
||||
@State heights: Resource = $r('app.float.wh_value_72');
|
||||
@State fontSize: Resource = $r('sys.float.ohos_id_text_size_body1');
|
||||
@State valueFontSize: Resource = $r('sys.float.ohos_id_text_size_body2');
|
||||
private isEnabled: boolean = true;
|
||||
@State editPopupVisibility: boolean = false
|
||||
|
||||
showDisconnectDialog(): void {
|
||||
AlertDialog.show({
|
||||
message: $r('app.string.vpn_line_disconnect_alert_title', this.vpnListItem!.vpnName),
|
||||
primaryButton: {
|
||||
value: $r('app.string.cancel'),
|
||||
action: () => {
|
||||
LogUtil.info('dialog cancel callbacks');
|
||||
}
|
||||
},
|
||||
secondaryButton: {
|
||||
fontColor: $r('sys.color.ohos_id_color_warning'),
|
||||
value: $r('app.string.vpn_line_disconnect_alert_confirm'),
|
||||
action: () => {
|
||||
VpnConnectModel.getInstance().setConnectState(VpnConstant.VPN_STATE_DISCONNECTING);
|
||||
VpnConnectModel.getInstance().destroy((error: string) => {
|
||||
if (error) {
|
||||
LogUtil.info(MODULE_TAG + `vpn destroy failed, error:` + error);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
alignment: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ?
|
||||
DialogAlignment.Bottom : DialogAlignment.Center,
|
||||
offset: ({ dx: 0, dy: deviceTypeInfo === 'phone' || deviceTypeInfo === 'default' ? '-24dp' : 0 })
|
||||
})
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
let state: number | undefined = AppStorage.get(VpnConstant.STORAGE_KEY_CONNECT_STATE);
|
||||
if (state) {
|
||||
this.connectState = state;
|
||||
if (this.connectState === VpnConstant.VPN_STATE_CONNECTED &&
|
||||
this.vpnListItem!.vpnId === VpnConnectModel.getInstance().getConnectedVpnId()) {
|
||||
this.connectStateLabel = $r('app.string.vpn_state_connec_success');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onEditBtnClick() {
|
||||
if (VpnConnectModel.getInstance().isConnecting(this.vpnListItem!.vpnId)) {
|
||||
this.showDisconnectDialog();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let data: vpn.SysVpnConfig = await vpn.getSysVpnConfig(this.vpnListItem?.vpnId);
|
||||
if (data) {
|
||||
router.pushUrl({
|
||||
url: 'pages/vpn/vpnEdit',
|
||||
params: data as VpnConfig
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
}
|
||||
|
||||
onListItemClick() {
|
||||
if (VpnConnectModel.getInstance().isConnectedOrConnecting(this.vpnListItem!.vpnId)) {
|
||||
this.showDisconnectDialog();
|
||||
} else {
|
||||
router.pushUrl({
|
||||
url: 'pages/vpn/vpnConnect',
|
||||
params: this.vpnListItem
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onConnectStateChange(): void {
|
||||
if (this.vpnListItem!.vpnId === VpnConnectModel.getInstance().getConnectedVpnId()) {
|
||||
LogUtil.info(MODULE_TAG + 'onConnectStateChange state=' + this.connectState);
|
||||
switch (this.connectState) {
|
||||
case VpnConstant.VPN_STATE_CONNECTING:
|
||||
this.connectStateLabel = $r('app.string.vpn_state_connect_ing');
|
||||
return;
|
||||
case VpnConstant.VPN_STATE_CONNECTED:
|
||||
this.connectStateLabel = $r('app.string.vpn_state_connec_success');
|
||||
return;
|
||||
case VpnConstant.VPN_STATE_DISCONNECTING:
|
||||
this.connectStateLabel = $r('app.string.vpn_state_disconnecting');
|
||||
return;
|
||||
case VpnConstant.VPN_STATE_DISCONNECTED:
|
||||
this.connectStateLabel = $r('app.string.vpn_state_disconnected');
|
||||
return;
|
||||
case VpnConstant.VPN_STATE_CONNECT_FAILED:
|
||||
this.connectStateLabel = $r('app.string.vpn_state_connec_failed');
|
||||
return;
|
||||
default:
|
||||
this.connectStateLabel = '';
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.connectStateLabel = '';
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Row() {
|
||||
Image($r('app.media.ic_vpn'))
|
||||
.width(30)
|
||||
.height(16)
|
||||
.margin({
|
||||
right: $r('app.float.wh_value_16')
|
||||
})
|
||||
Column() {
|
||||
Text(this.vpnListItem?.vpnName ?? '')
|
||||
.fontColor(this.isEnabled ? this.titleFontColor : $r('sys.color.ohos_id_color_primary'))
|
||||
.fontSize(this.fontSize)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.align(Alignment.Start)
|
||||
.maxLines(ComponentConfig.MAX_LINES_1)
|
||||
.width(ComponentConfig.WH_100_100)
|
||||
.ellipsisMode(EllipsisMode.END)
|
||||
.padding({ right: 50 })
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
|
||||
Text(this.connectStateLabel)
|
||||
.fontColor($r('sys.color.ohos_id_color_mask_light'))
|
||||
.fontSize(this.valueFontSize)
|
||||
.textAlign(TextAlign.Start)
|
||||
.fontWeight(FontWeight.Regular)
|
||||
.maxLines(ComponentConfig.MAX_LINES_1)
|
||||
.width(ComponentConfig.WH_100_100)
|
||||
.ellipsisMode(EllipsisMode.END)
|
||||
.padding({ right: 50 })
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.margin({ top: 8 })
|
||||
.visibility(this.connectStateLabel.toString().length > 0 ? Visibility.Visible : Visibility.None)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('80%')
|
||||
|
||||
Row() {
|
||||
Image($r('app.media.ic_public_detail'))
|
||||
.width(24)
|
||||
.height(24)
|
||||
}
|
||||
.width($r('app.float.wh_value_50'))
|
||||
.height(ComponentConfig.WH_100_100)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.margin({
|
||||
right: $r('app.float.wh_value_16')
|
||||
})
|
||||
.onClick(() => {
|
||||
this.onEditBtnClick();
|
||||
})
|
||||
}
|
||||
.flexShrink(0)
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.align(Alignment.Start)
|
||||
|
||||
Blank()
|
||||
}
|
||||
.width(ComponentConfig.WH_100_100)
|
||||
.padding({
|
||||
left: $r('sys.float.ohos_id_card_margin_end'),
|
||||
right: $r('sys.float.ohos_id_card_margin_end'),
|
||||
top: $r('sys.float.ohos_id_elements_margin_vertical_m'),
|
||||
bottom: $r('sys.float.ohos_id_elements_margin_vertical_m')
|
||||
})
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.height('62vp')
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.linearGradient(this.isTouched ? {
|
||||
angle: 90,
|
||||
direction: GradientDirection.Right,
|
||||
colors: [[$r('app.color.DCEAF9'), 0.0], [$r('app.color.FAFAFA'), 1.0]]
|
||||
} : {
|
||||
angle: 90,
|
||||
direction: GradientDirection.Right,
|
||||
colors: [[$r('sys.color.ohos_id_color_foreground_contrary'), 1],
|
||||
[$r('sys.color.ohos_id_color_foreground_contrary'), 1]]
|
||||
})
|
||||
.onTouch((event?: TouchEvent | undefined) => {
|
||||
if (event?.type === TouchType.Down) {
|
||||
this.isTouched = true;
|
||||
}
|
||||
if (event?.type === TouchType.Up) {
|
||||
this.isTouched = false;
|
||||
}
|
||||
})
|
||||
.onClick(() => {
|
||||
this.onListItemClick();
|
||||
})
|
||||
}
|
||||
}
|
190
product/phone/src/main/ets/pages/vpn/vpnList.ets
Normal file
190
product/phone/src/main/ets/pages/vpn/vpnList.ets
Normal file
@ -0,0 +1,190 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import common from '@ohos.app.ability.common';
|
||||
import router from '@ohos.router';
|
||||
import vpn from '@ohos.net.vpn';
|
||||
import VpnLine from './vpnLine';
|
||||
import VpnConfig, { VpnListItem } from '../../model/vpnImpl/VpnConfig';
|
||||
import { VpnConnectModel } from '../../model/vpnImpl/VpnConnectModel';
|
||||
import { SwanCtlModel } from '../../model/vpnImpl/SwanCtlModel';
|
||||
import { VpnConfigModel } from '../../model/vpnImpl/VpnConfigModel';
|
||||
import { ResourceUtils } from '../../model/accessibilityImpl/resourceUtils';
|
||||
import ConfigData from '../../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
|
||||
import { BaseData } from '../../../../../../../common/utils/src/main/ets/default/bean/BaseData';
|
||||
import HeadComponent from '../../../../../../../common/component/src/main/ets/default/headComponent';
|
||||
import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
|
||||
|
||||
const MODULE_TAG: string = 'setting_vpn:VPNList:';
|
||||
|
||||
/**
|
||||
* VPN list
|
||||
*/
|
||||
@Entry
|
||||
@Component
|
||||
struct VPNList {
|
||||
@State vpnList: VpnListItem[] = [];
|
||||
@State isLoading: boolean = false;
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
GridContainer({ gutter: ConfigData.GRID_CONTAINER_GUTTER_24, margin: ConfigData.GRID_CONTAINER_MARGIN_24 }) {
|
||||
Column() {
|
||||
HeadComponent({ headName: $r('app.string.VPN'), isActive: true })
|
||||
if (this.isLoading) {
|
||||
Column() {
|
||||
LoadingProgress()
|
||||
.color(Color.White)
|
||||
.width(80)
|
||||
}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)
|
||||
} else {
|
||||
if (this.vpnList!.length > 0 ) {
|
||||
Column() {
|
||||
List() {
|
||||
ForEach(this.vpnList, (item: VpnListItem, index: number) => {
|
||||
ListItem() {
|
||||
VpnLine({
|
||||
vpnListItem: item,
|
||||
fontSize: $r('sys.float.ohos_id_text_size_body1'),
|
||||
valueFontSize: $r('sys.float.ohos_id_text_size_body2'),
|
||||
})
|
||||
}.padding(3)
|
||||
}, (item: BaseData) => JSON.stringify(item));
|
||||
}
|
||||
.margin({ top: $r('app.float.distance_8') })
|
||||
.align(Alignment.Top)
|
||||
.borderRadius($r('app.float.radius_16'))
|
||||
.backgroundColor($r('sys.color.ohos_id_color_foreground_contrary'))
|
||||
.divider({
|
||||
strokeWidth: $r('app.float.divider_wh'),
|
||||
color: $r('sys.color.ohos_id_color_list_separator'),
|
||||
startMargin: $r('app.float.wh_value_48'),
|
||||
endMargin: $r('app.float.wh_value_8')
|
||||
})
|
||||
}
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
.layoutWeight(1)
|
||||
|
||||
Column({ space: 5 }) {
|
||||
Image($r('app.media.ic_public_add'))
|
||||
.width(20)
|
||||
.height(20)
|
||||
Text($r('app.string.vpn_list_add'))
|
||||
.fontColor('#333333')
|
||||
.fontSize(14)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
}
|
||||
.margin({ bottom: 25, top: 25 })
|
||||
.onClick(() => {
|
||||
this.onAddBtnClick();
|
||||
})
|
||||
} else {
|
||||
Column() {
|
||||
Image($r('app.media.empty'))
|
||||
.width(200)
|
||||
.height(200)
|
||||
Text($r('app.string.vpn_list_empty'))
|
||||
.fontSize(15)
|
||||
.fontColor('#999999')
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
.layoutWeight(1)
|
||||
|
||||
Column({ space: 5 }) {
|
||||
Button($r('app.string.vpn_list_add'))
|
||||
.fontColor('#0A59F7')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.height(45)
|
||||
.padding({ top: 10, left: 60, right: 60, bottom: 10 })
|
||||
.borderRadius($r('app.float.radius_24'))
|
||||
.backgroundColor('#E6E8E9')
|
||||
.onClick(() => {
|
||||
this.onAddBtnClick();
|
||||
})
|
||||
}.margin({ bottom: 25, top: 25 })
|
||||
}
|
||||
}
|
||||
}
|
||||
.useSizeType({
|
||||
sm: { span: 4, offset: 0 },
|
||||
md: { span: 6, offset: 1 },
|
||||
lg: { span: 8, offset: 2 }
|
||||
})
|
||||
}
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
}
|
||||
.backgroundColor($r('sys.color.ohos_id_color_sub_background'))
|
||||
.width(ConfigData.WH_100_100)
|
||||
.height(ConfigData.WH_100_100)
|
||||
}
|
||||
|
||||
onAddBtnClick() {
|
||||
router.pushUrl({
|
||||
url: 'pages/vpn/vpnEdit',
|
||||
});
|
||||
}
|
||||
|
||||
async updateVpnList() {
|
||||
this.isLoading = true;
|
||||
try {
|
||||
let data: vpn.SysVpnConfig[] = await vpn.getSysVpnConfigList();
|
||||
if (data) {
|
||||
let list = data as VpnListItem[];
|
||||
let currentVpnId = VpnConnectModel.getInstance().getConnectedVpnId();
|
||||
list.sort((item1, item2) => {
|
||||
if (currentVpnId! && item1.vpnId === currentVpnId) {
|
||||
return -1;
|
||||
} else if (currentVpnId! && item2.vpnId === currentVpnId) {
|
||||
return 1;
|
||||
} else {
|
||||
return item1.vpnName.localeCompare(item2.vpnName, 'zh');
|
||||
}
|
||||
});
|
||||
this.vpnList = list;
|
||||
} else {
|
||||
this.vpnList = [];
|
||||
}
|
||||
} catch (err) {
|
||||
let message = (err as BusinessError).message;
|
||||
VpnConfigModel.getInstance().showToast(ResourceUtils.getStringSync($r('app.string.vpn_error_operation_failed')) + ': ' + message);
|
||||
}
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
LogUtil.info(MODULE_TAG + 'aboutToAppear');
|
||||
VpnConfigModel.getInstance().setNeedUpdateVpnList(true);
|
||||
VpnConnectModel.getInstance().init(getContext() as common.UIAbilityContext);
|
||||
SwanCtlModel.getInstance().init(getContext() as common.UIAbilityContext);
|
||||
}
|
||||
|
||||
onPageShow(): void {
|
||||
if (VpnConfigModel.getInstance().isUpdateVpnList()) {
|
||||
this.updateVpnList();
|
||||
VpnConfigModel.getInstance().setNeedUpdateVpnList(false);
|
||||
}
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
LogUtil.info(MODULE_TAG + 'aboutToDisappear');
|
||||
VpnConnectModel.getInstance().release();
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
"module": {
|
||||
"name": "phone",
|
||||
"type": "entry",
|
||||
"srcEntrance": "./ets/Application/AbilityStage.ts",
|
||||
"srcEntry": "./ets/Application/AbilityStage.ts",
|
||||
"description": "$string:mainability_description",
|
||||
"mainElement": "com.ohos.settings.MainAbility",
|
||||
"deviceTypes": [
|
||||
@ -22,7 +22,7 @@
|
||||
"abilities": [
|
||||
{
|
||||
"name": "com.ohos.settings.MainAbility",
|
||||
"srcEntrance": "./ets/MainAbility/MainAbility.ts",
|
||||
"srcEntry": "./ets/MainAbility/MainAbility.ts",
|
||||
"description": "$string:mainability_description",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:entry_MainAbility",
|
||||
@ -43,7 +43,7 @@
|
||||
},
|
||||
{
|
||||
"name": "com.ohos.settings.AppInfoAbility",
|
||||
"srcEntrance": "./ets/MainAbility/AppInfoAbility.ts",
|
||||
"srcEntry": "./ets/MainAbility/AppInfoAbility.ts",
|
||||
"description": "$string:applicationInfo",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:applicationInfo",
|
||||
@ -227,6 +227,9 @@
|
||||
{
|
||||
"name": "ohos.permission.sec.ACCESS_UDID",
|
||||
"reason": "$string:GET_ACCESS_UDID"
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.MANAGE_VPN"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -83,6 +83,10 @@
|
||||
{
|
||||
"name": "white",
|
||||
"value": "#FFFFFF"
|
||||
},
|
||||
{
|
||||
"name": "FA2A2D",
|
||||
"value": "#FA2A2D"
|
||||
}
|
||||
]
|
||||
}
|
29
product/phone/src/main/resources/base/element/strarray.json
Normal file
29
product/phone/src/main/resources/base/element/strarray.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"strarray": [
|
||||
{
|
||||
"name": "ovpn_auth_type",
|
||||
"value": [
|
||||
{
|
||||
"value": "证书(TLS)"
|
||||
},
|
||||
{
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"value": "证书和密码(TLS)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ovpn_protocol",
|
||||
"value": [
|
||||
{
|
||||
"value": "TCP"
|
||||
},
|
||||
{
|
||||
"value": "UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1491,6 +1491,282 @@
|
||||
{
|
||||
"name": "GET_ACCESS_UDID",
|
||||
"value": "获取UDID的权限"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_title",
|
||||
"value": "要替换现有VPN吗?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_content",
|
||||
"value": "您已连接到VPN,如果您要连接到其他VPN,则系统替换现有VPN."
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_change_alert_confirm",
|
||||
"value": "替换"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_connect_title",
|
||||
"value": "连接到%s"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_username",
|
||||
"value": "用户名"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_password",
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_save",
|
||||
"value": "保存账户信息"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_confirm",
|
||||
"value": "连接"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_title",
|
||||
"value": "编辑VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_alias",
|
||||
"value": "名称"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_type",
|
||||
"value": "类型"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_configfile",
|
||||
"value": "OpenVPN 配置文件"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_ca_cert_file",
|
||||
"value": "CA 证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_user_cert_file",
|
||||
"value": "用户证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key",
|
||||
"value": "私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key_psd",
|
||||
"value": "私钥密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_username",
|
||||
"value": "用户名"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_password",
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_click_select",
|
||||
"value": "点击选择"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_protocol",
|
||||
"value": "OpenVPN 协议"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_auth_type",
|
||||
"value": "OpenVPN 认证类型"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_serveraddress",
|
||||
"value": "服务器地址"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_serveraddress",
|
||||
"value": "OpenVPN 服务器地址"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_port",
|
||||
"value": "OpenVPN 服务器端口"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecidentifier",
|
||||
"value": "IPSec 标识符"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_edit_l2tpsecret",
|
||||
"value": "L2TP 密钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecsecret",
|
||||
"value": "IPSec 预共享密钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_usercert",
|
||||
"value": "IPSec 用户证书公钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_user_private_cert",
|
||||
"value": "IPSec 用户证书私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cacert",
|
||||
"value": "IPSec CA 证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_servercert",
|
||||
"value": "IPSec 服务器证书公钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_server_private_cert",
|
||||
"value": "IPSec 服务器秘钥证书私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_unuse",
|
||||
"value": "未使用"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_advanced",
|
||||
"value": "显示高级选项"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_proxy_advanced",
|
||||
"value": "显示代理"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_searchdomains",
|
||||
"value": "DNS 搜索域"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_dnsaddresses",
|
||||
"value": "DNS 服务器(例如 8.8.8.8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_router",
|
||||
"value": "转发路线(例如 10.0.0.0/8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_host",
|
||||
"value": "OpenVPN 代理主机"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_port",
|
||||
"value": "OpenVPN 代理端口"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_username",
|
||||
"value": "OpenVPN 代理用户名"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_password",
|
||||
"value": "OpenVPN 代理密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_useauth",
|
||||
"value": "使用基本身份验证"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_save",
|
||||
"value": "保存"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_specified",
|
||||
"value": "(未指定)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_verify_server",
|
||||
"value": "(不验证服务器)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_from_server",
|
||||
"value": "(来自服务器)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_title",
|
||||
"value": "是否删除%s网络?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_confirm",
|
||||
"value": "删除"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_title",
|
||||
"value": "是否断开%s网络?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_confirm",
|
||||
"value": "断开"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_edit",
|
||||
"value": "编辑VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_remove",
|
||||
"value": "删除VPN网络"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_state_connect_ing",
|
||||
"value": "连接中..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_success",
|
||||
"value": "连接成功"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_failed",
|
||||
"value": "连接失败"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnecting",
|
||||
"value": "断开中..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnected",
|
||||
"value": "已断开"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_empty",
|
||||
"value": "没有VPN"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_add",
|
||||
"value": "添加VPN网络"
|
||||
}, {
|
||||
"name": "ovpn_auth_type_cert",
|
||||
"value": "证书( TLS )"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_pass",
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_certpass",
|
||||
"value": "证书和密码( TLS )"
|
||||
},
|
||||
{
|
||||
"name": "VPN",
|
||||
"value": "VPN"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_invalid_param",
|
||||
"value": "参数错误"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_operation_failed",
|
||||
"value": "API调用失败"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_system_internal",
|
||||
"value": "系统内部错误"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_disconnect_first",
|
||||
"value": "请先断开VPN,再操作"
|
||||
}
|
||||
]
|
||||
}
|
1
product/phone/src/main/resources/base/media/empty.svg
Normal file
1
product/phone/src/main/resources/base/media/empty.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1710986847033" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4597" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M79.205516 455.117464a455.106029 452.591568 90 1 0 905.183136 0 455.106029 452.591568 90 1 0-905.183136 0Z" fill="#EEEEEE" p-id="4598"></path><path d="M791.719262 692.116443l24.002896-24.13162a16.907189 16.907189 0 0 1 24.002896-0.004022L903.732776 732.342512l-48.005791 48.271284-64.007723-64.361712a17.134742 17.134742 0 0 1 0-24.135641z" fill="#D8D8D8" p-id="4599"></path><path d="M722.156558 273.075052l0.318574-0.489239a5.711581 5.711581 0 0 0-1.154831 3.453117V341.340956c0 3.140232 2.531527 5.688825 5.654692 5.688826h85.09345c0.739547 0 1.45065-0.142221 2.099177-0.403907l0.494927 0.403907v261.685966c0 15.706847-12.663325 28.444127-28.284839 28.444127h-492.197171c-15.615826 0-28.28484-12.73728-28.28484-28.444127V301.519179c0-15.706847 12.669014-28.444127 28.290529-28.444127h427.970332z" fill="#FDFDFD" p-id="4600"></path><path d="M322.471066 364.096258m8.533238 0l265.804676 0q8.533238 0 8.533238 8.533238l0 0q0 8.533238-8.533238 8.533238l-265.804676 0q-8.533238 0-8.533238-8.533238l0 0q0-8.533238 8.533238-8.533238Z" fill="#D8D8D8" p-id="4601"></path><path d="M322.471066 438.050988m8.533238 0l186.599161 0q8.533238 0 8.533238 8.533238l0 0q0 8.533238-8.533238 8.533238l-186.599161 0q-8.533238 0-8.533238-8.533238l0 0q0-8.533238 8.533238-8.533238Z" fill="#D8D8D8" p-id="4602"></path><path d="M322.471066 512.005717m8.533238 0l186.599161 0q8.533238 0 8.533238 8.533238l0 0q0 8.533238-8.533238 8.533238l-186.599161 0q-8.533238 0-8.533238-8.533238l0 0q0-8.533238 8.533238-8.533238Z" fill="#D8D8D8" p-id="4603"></path><path d="M226.295784 25.611149a19.910889 19.802801 90 1 0 39.605602 0 19.910889 19.802801 90 1 0-39.605602 0Z" fill="#EEEEEE" p-id="4604"></path><path d="M995.703726 347.029782a11.377651 11.315074 90 1 0 22.630147 0 11.377651 11.315074 90 1 0-22.630147 0Z" fill="#EEEEEE" p-id="4605"></path><path d="M715.65992 278.763877v68.265905c0 3.140232 2.531527 5.688825 5.660381 5.688825h90.5149a5.700203 5.700203 0 1 0 3.396229-10.239886l-90.520589-68.265904a5.631937 5.631937 0 0 0-7.918845 1.137765c-0.739547 0.984167-1.132076 2.184509-1.132076 3.413295z" fill="#D8D8D8" p-id="4606"></path><path d="M585.539417 566.049558a113.776507 113.150736 90 1 0 226.301473 0 113.776507 113.150736 90 1 0-226.301473 0Z" fill="#EEEEEE" p-id="4607"></path><path d="M759.714183 659.937932l24.006843-24.137686 31.999643 32.181685-24.006843 24.137686zM42.432948 267.386227c4.113021 0 7.549071 14.739747 8.322752 34.303617 19.444405 0.77368 34.104508 4.221108 34.104508 8.362573s-14.660103 7.588893-34.110197 8.368262C49.98202 337.984549 46.545969 352.718607 42.438637 352.718607c-4.11871 0-7.55476-14.739747-8.322751-34.303617C14.660103 317.646999 0 314.199571 0 310.052417s14.660103-7.588893 34.110197-8.368262C34.872499 282.120284 38.314239 267.386227 42.432948 267.386227zM995.703726 153.609719c2.742014 0 5.028922 9.824601 5.546604 22.869078 12.970522 0.511994 22.738235 2.815969 22.738235 5.575049s-9.773402 5.063055-22.738235 5.575049c-0.511994 13.044477-2.804591 22.869078-5.546604 22.869078-2.747703 0-5.03461-9.824601-5.552294-22.869078-12.964833-0.511994-22.738235-2.815969-22.738235-5.575049s9.773402-5.063055 22.738235-5.575049c0.511994-13.044477 2.804591-22.869078 5.552294-22.869078z" fill="#D8D8D8" p-id="4608"></path><path d="M851.440803 0.011435c4.181287 0 7.657159 17.248519 8.356885 39.946931 22.573259 0.705414 39.730756 4.204042 39.730756 8.408084 0 4.209731-17.157497 7.70267-39.730756 8.402395-0.699726 22.698413-4.175598 39.952621-8.362573 39.952621-4.181287 0-7.657159-17.248519-8.356885-39.946932-22.573259-0.705414-39.730756-4.204042-39.730756-8.408084 0-4.209731 17.157497-7.70267 39.730756-8.402395 0.699726-22.698413 4.175598-39.952621 8.362573-39.95262z" fill="#EEEEEE" p-id="4609"></path></svg>
|
After Width: | Height: | Size: 4.0 KiB |
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Public/ic_public_add</title>
|
||||
<defs>
|
||||
<path d="M12.75,21.25 C12.75,21.6642136 12.4142136,22 12,22 C11.5857864,22 11.25,21.6642136 11.25,21.25 L11.25,12.75 L2.75,12.75 C2.33578644,12.75 2,12.4142136 2,12 C2,11.5857864 2.33578644,11.25 2.75,11.25 L11.25,11.25 L11.25,2.75 C11.25,2.33578644 11.5857864,2 12,2 C12.4142136,2 12.75,2.33578644 12.75,2.75 L12.75,21.25 Z M21.25,11.25 C21.6642136,11.25 22,11.5857864 22,12 C22,12.4142136 21.6642136,12.75 21.25,12.75 L13.75,12.75 L13.75,11.25 L21.25,11.25 Z" id="path-1"></path>
|
||||
</defs>
|
||||
<g id="Public/ic_public_add" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<use id="形状结合" fill="#000000" xlink:href="#path-1"></use>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>ic_public_detail</title>
|
||||
<g id="ic_public_detail" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="编组" transform="translate(1.000000, 1.000000)" fill="#000000" fill-rule="nonzero">
|
||||
<path d="M11,0 C17.0751322,0 22,4.92486775 22,11 C22,17.0751322 17.0751322,22 11,22 C4.92486775,22 0,17.0751322 0,11 C0,4.92486775 4.92486775,0 11,0 Z M11,1.5 C5.75329488,1.5 1.5,5.75329488 1.5,11 C1.5,16.2467051 5.75329488,20.5 11,20.5 C16.2467051,20.5 20.5,16.2467051 20.5,11 C20.5,5.75329488 16.2467051,1.5 11,1.5 Z M11,8.75 C11.4142136,8.75 11.75,9.0857864 11.75,9.5 L11.75,16.25 C11.75,16.6642136 11.4142136,17 11,17 C10.5857864,17 10.25,16.6642136 10.25,16.25 L10.25,9.5 C10.25,9.0857864 10.5857864,8.75 11,8.75 Z M11,5 C11.6903559,5 12.25,5.55964406 12.25,6.25 C12.25,6.94035594 11.6903559,7.5 11,7.5 C10.3096441,7.5 9.75,6.94035594 9.75,6.25 C9.75,5.55964406 10.3096441,5 11,5 Z" id="path-1"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
35
product/phone/src/main/resources/base/media/ic_vpn.svg
Normal file
35
product/phone/src/main/resources/base/media/ic_vpn.svg
Normal file
@ -0,0 +1,35 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="29.502" height="15.56" viewBox="0 0 29.502 15.56">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke: #b2b2b2;
|
||||
stroke-linecap: round;
|
||||
stroke-width: 5px;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #b2b2b2;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5 {
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #b2b2b2;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="组_1" data-name="组 1" transform="translate(-35 -10.64)">
|
||||
<g id="路径_14" data-name="路径 14" class="cls-1" transform="translate(35 10.64)">
|
||||
<path class="cls-4" d="M7.78,0A7.78,7.78,0,1,1,0,7.78,7.78,7.78,0,0,1,7.78,0Z"/>
|
||||
<path class="cls-5" d="M 7.780176162719727 4.999996185302734 C 6.247176170349121 4.999996185302734 4.999996185302734 6.247176170349121 4.999996185302734 7.780176162719727 C 4.999996185302734 9.313176155090332 6.247176170349121 10.56035614013672 7.780176162719727 10.56035614013672 C 9.313176155090332 10.56035614013672 10.56035614013672 9.313176155090332 10.56035614013672 7.780176162719727 C 10.56035614013672 6.247176170349121 9.313176155090332 4.999996185302734 7.780176162719727 4.999996185302734 M 7.780176162719727 -3.814697265625e-06 C 12.07704639434814 -3.814697265625e-06 15.56035614013672 3.483305931091309 15.56035614013672 7.780176162719727 C 15.56035614013672 12.07704639434814 12.07704639434814 15.56035614013672 7.780176162719727 15.56035614013672 C 3.483305931091309 15.56035614013672 -3.814697265625e-06 12.07704639434814 -3.814697265625e-06 7.780176162719727 C -3.814697265625e-06 3.483305931091309 3.483305931091309 -3.814697265625e-06 7.780176162719727 -3.814697265625e-06 Z"/>
|
||||
</g>
|
||||
<line id="直线_7" data-name="直线 7" class="cls-2" x2="11.875" transform="translate(50.127 18.625)"/>
|
||||
<path id="路径_15" data-name="路径 15" class="cls-3" d="M0,0H5V2A2,2,0,0,1,3,4H2A2,2,0,0,1,0,2Z" transform="translate(57 22)"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -43,6 +43,9 @@
|
||||
"pages/accessibilityShortKey",
|
||||
"pages/accessibilityColorCorrection",
|
||||
"pages/accessibilityScreenTouch",
|
||||
"pages/abilityDialog/accessibilityWindowShortKeyDialog"
|
||||
"pages/abilityDialog/accessibilityWindowShortKeyDialog",
|
||||
"pages/vpn/vpnList",
|
||||
"pages/vpn/vpnEdit",
|
||||
"pages/vpn/vpnConnect"
|
||||
]
|
||||
}
|
||||
|
29
product/phone/src/main/resources/en_US/element/strarray.json
Normal file
29
product/phone/src/main/resources/en_US/element/strarray.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"strarray": [
|
||||
{
|
||||
"name": "ovpn_auth_type",
|
||||
"value": [
|
||||
{
|
||||
"value": "Certificate(TLS)"
|
||||
},
|
||||
{
|
||||
"value": "Password"
|
||||
},
|
||||
{
|
||||
"value": "Certificate and Password(TLS)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ovpn_protocol",
|
||||
"value": [
|
||||
{
|
||||
"value": "TCP"
|
||||
},
|
||||
{
|
||||
"value": "UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1487,6 +1487,272 @@
|
||||
{
|
||||
"name": "GET_ACCESS_UDID",
|
||||
"value": "Permission to obtain a UDID"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_title",
|
||||
"value": "Replace the existing VPN?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_content",
|
||||
"value": "You have connected to the VPN. If you want to connect to another VPN, the system will replace the existing VPN."
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_confirm",
|
||||
"value": "Replace"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_title",
|
||||
"value": "Connection to %s"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_username",
|
||||
"value": "Username"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_password",
|
||||
"value": "Password"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_save",
|
||||
"value": "Save Account Information"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_confirm",
|
||||
"value": "Connect"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_title",
|
||||
"value": "Edit VPN Network"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_alias",
|
||||
"value": "Alias"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_type",
|
||||
"value": "Protocol Type"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_configfile",
|
||||
"value": "OpenVPN Config File"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_click_select",
|
||||
"value": "Click Select"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_ca_cert_file",
|
||||
"value": "CA Certificate"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_user_cert_file",
|
||||
"value": "User Certificate"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key",
|
||||
"value": "Private key"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key_psd",
|
||||
"value": "Private key password"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_protocol",
|
||||
"value": "OpenVPN Protocol"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_auth_type",
|
||||
"value": "OpenVPN Auth Type"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_serveraddress",
|
||||
"value": "Server Address"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_serveraddress",
|
||||
"value": "OpenVpn Server Address"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_port",
|
||||
"value": "OpenVpn Server Port"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecidentifier",
|
||||
"value": "IPSec Identifier"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_edit_l2tpsecret",
|
||||
"value": "L2TP Secret"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecsecret",
|
||||
"value": "IPSec Secret"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_usercert",
|
||||
"value": "IPSec User Certificate Public Key"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_user_private_cert",
|
||||
"value": "IPSec User Certificate Private Key"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cacert",
|
||||
"value": "IPSec CA Certificate"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_servercert",
|
||||
"value": "IPSec Server Certificate Public Key"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_server_private_cert",
|
||||
"value": "IPSec Server Certificate Private Key"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_unuse",
|
||||
"value": "not used"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_advanced",
|
||||
"value": "Show Advanced Options"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_proxy_advanced",
|
||||
"value": "Show Proxy Advanced Options"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_searchdomains",
|
||||
"value": "DNS Search Domain"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_dnsaddresses",
|
||||
"value": "DNS Server (e.g. 8.8.8.8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_router",
|
||||
"value": "Forwarding Route (e.g. 10.0.0.0/8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_host",
|
||||
"value": "OpenVpn Proxy Host"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_port",
|
||||
"value": "OpenVpn Proxy Port"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_username",
|
||||
"value": "OpenVpn Proxy Username"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_password",
|
||||
"value": "OpenVpn Proxy Password"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_useauth",
|
||||
"value": "Using Basic Authentication"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_save",
|
||||
"value": "Save"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_specified",
|
||||
"value": "(unspecified)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_verify_server",
|
||||
"value": "(Do not verify server)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_from_server",
|
||||
"value": "(From server)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_title",
|
||||
"value": "Delete the %s vpn?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_confirm",
|
||||
"value": "Delete"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_title",
|
||||
"value": "Disconnect the %s VPN?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_confirm",
|
||||
"value": "Disconnect"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_edit",
|
||||
"value": "Edit VPN Network"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_remove",
|
||||
"value": "Delete VPN Network"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "vpn_state_connect_ing",
|
||||
"value": "Connecting..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_success",
|
||||
"value": "Connection successful"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_failed",
|
||||
"value": "Connection failed"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnecting",
|
||||
"value": "Disconnecting..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnected",
|
||||
"value": "DisConnected"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_empty",
|
||||
"value": "No VPN Network"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_add",
|
||||
"value": "Add VPN Network"
|
||||
}, {
|
||||
"name": "ovpn_auth_type_cert",
|
||||
"value": "Certificate(TLS)"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_pass",
|
||||
"value": "Password"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_certpass",
|
||||
"value": "Certificate and Password(TLS)"
|
||||
},
|
||||
{
|
||||
"name": "VPN",
|
||||
"value": "VPN"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_invalid_param",
|
||||
"value": "Invalid parameter value"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_operation_failed",
|
||||
"value": "Operation failed"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_system_internal",
|
||||
"value": "System internal error"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_disconnect_first",
|
||||
"value": "Disconnect the VPN before operating"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes des md4 sha1 sha2 fips-prf pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default eap-identity eap-mschapv2 updown
|
||||
}
|
||||
|
||||
charon {
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
connections {
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = eap-mschapv2
|
||||
eap_id = vpn_username_value
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes128gcm128-x25519
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-x25519
|
||||
}
|
||||
}
|
||||
secrets {
|
||||
eap-carol {
|
||||
id = ipsec_identifier_value
|
||||
secret = password_value
|
||||
}
|
||||
eap-dave {
|
||||
id = vpn_username_value
|
||||
secret = vpn_password_value
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = random openssl
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes sha1 sha2 hmac kdf curve25519 kernel-netlink socket-default updown vici kernel-libipsec
|
||||
}
|
||||
charon {
|
||||
plugins {
|
||||
kernel-libipsec {
|
||||
allow_peer_ts = yes
|
||||
}
|
||||
}
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
connections {
|
||||
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = psk
|
||||
}
|
||||
remote {
|
||||
auth = psk
|
||||
id = vpn_ipsec_identifier_value
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes128gcm128-x25519
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-x25519
|
||||
}
|
||||
}
|
||||
|
||||
secrets {
|
||||
|
||||
ike-moon {
|
||||
id = vpn_ipsec_identifier_value
|
||||
secret = vpn_ipsec_sharedKey_value
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes des md4 sha1 sha2 fips-prf pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default eap-identity eap-mschapv2 updown
|
||||
}
|
||||
|
||||
charon {
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
connections {
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = /data/service/el1/public/netmanager/client.cert.pem
|
||||
id = vpn_ipsec_identifier_value
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes128gcm128-x25519
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-x25519
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes des md4 sha1 sha2 fips-prf pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default eap-identity eap-mschapv2 updown
|
||||
}
|
||||
|
||||
charon {
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
connections {
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = xauth
|
||||
xauth_id = vpn_username_value
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes256-sha2_384
|
||||
}
|
||||
}
|
||||
version = 1
|
||||
proposals = aes256-sha2_384-modp1024
|
||||
}
|
||||
}
|
||||
|
||||
secrets {
|
||||
xauth {
|
||||
id = vpn_username_value
|
||||
secret = vpn_password_value
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes des md4 sha1 sha2 fips-prf pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default eap-identity eap-mschapv2 updown
|
||||
}
|
||||
|
||||
charon {
|
||||
|
||||
i_dont_care_about_security_and_use_aggressive_mode_psk = yes
|
||||
|
||||
plugins {
|
||||
kernel-netlink {
|
||||
install_routes_xfrmi = yes
|
||||
}
|
||||
}
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 2
|
||||
knl = 3
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
connections {
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = psk
|
||||
}
|
||||
local-xauth {
|
||||
auth = xauth
|
||||
xauth_id = vpn_username_value
|
||||
}
|
||||
remote {
|
||||
auth = psk
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes256-sha2_384
|
||||
}
|
||||
}
|
||||
version = 1
|
||||
proposals = aes256-sha2_384-modp1024
|
||||
aggressive=yes
|
||||
}
|
||||
}
|
||||
secrets {
|
||||
ike-moon {
|
||||
secret = vpn_ipsec_sharedKey_value
|
||||
}
|
||||
xauth{
|
||||
id = vpn_username_value
|
||||
secret = vpn_password_value
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce aes des md4 sha1 sha2 fips-prf pem pkcs1 curve25519 gmp x509 curl revocation hmac kdf vici kernel-netlink socket-default eap-identity eap-mschapv2 updown
|
||||
}
|
||||
|
||||
charon {
|
||||
|
||||
i_dont_care_about_security_and_use_aggressive_mode_psk = yes
|
||||
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
connections {
|
||||
home {
|
||||
remote_addrs = vpn_address_value
|
||||
vips = 0.0.0.0
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = /data/service/el1/public/netmanager/client.cert.pem
|
||||
id = vpn_username_value
|
||||
}
|
||||
local-xauth {
|
||||
auth = xauth
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts=0.0.0.0/0
|
||||
esp_proposals = aes256-sha2_384
|
||||
}
|
||||
}
|
||||
version = 1
|
||||
proposals = aes256-sha2_384-modp1024
|
||||
}
|
||||
}
|
||||
secrets {
|
||||
xauth-carol {
|
||||
id = vpn_username_value
|
||||
secret = vpn_password_value
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
# ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev1
|
||||
authby=secret
|
||||
ike=aes128-sha1-modp1024,3des-sha1-modp1024!
|
||||
esp=aes128-sha1-modp1024,3des-sha1-modp1024!
|
||||
|
||||
conn home
|
||||
keyexchange=ikev1
|
||||
left=%defaultroute
|
||||
auto=add
|
||||
authby=secret
|
||||
type=transport
|
||||
leftprotoport=17/1701
|
||||
rightprotoport=17/1701
|
||||
right=vpn_address_value
|
@ -0,0 +1,2 @@
|
||||
# ipsec.secrets.conf - strongSwan IPsec secrets file
|
||||
: PSK vpn_ipsec_sharedKey_value
|
@ -0,0 +1,16 @@
|
||||
ipcp-accept-local
|
||||
ipcp-accept-remote
|
||||
refuse-eap
|
||||
require-mschap-v2
|
||||
noccp
|
||||
noauth
|
||||
logfile /data/service/el1/public/netmanager/xl2tpd.log
|
||||
idle 1800
|
||||
mtu 1410
|
||||
mru 1410
|
||||
defaultroute
|
||||
usepeerdns
|
||||
debug
|
||||
connect-delay 5000
|
||||
name vpn_username_value
|
||||
password vpn_password_value
|
@ -0,0 +1,39 @@
|
||||
# strongswan.conf - strongSwan configuration file
|
||||
#
|
||||
# Refer to the strongswan.conf(5) manpage for details
|
||||
#
|
||||
# Configuration changes should be made in the included files
|
||||
|
||||
charon {
|
||||
load_modular = yes
|
||||
plugins {
|
||||
include /system/etc/strongswan/strongswan.d/charon/*.conf
|
||||
kernel-libipsec {
|
||||
load = no
|
||||
}
|
||||
}
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include /system/etc/strongswan/strongswan.d/*.conf
|
@ -0,0 +1,6 @@
|
||||
[lac myVPN]
|
||||
; set this to the ip address of your vpn server
|
||||
lns = vpn_address_value
|
||||
ppp debug = yes
|
||||
pppoptfile = /data/service/el1/public/netmanager/options.l2tpd.client.conf
|
||||
length bit = yes
|
@ -0,0 +1,23 @@
|
||||
# ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
keyexchange=ikev1
|
||||
authby=secret
|
||||
ike=aes128-sha1-modp1024,3des-sha1-modp1024!
|
||||
esp=aes128-sha1-modp1024,3des-sha1-modp1024!
|
||||
|
||||
conn home
|
||||
keyexchange=ikev1
|
||||
left=%defaultroute
|
||||
auto=add
|
||||
authby=secret
|
||||
type=transport
|
||||
leftprotoport=17/1701
|
||||
rightprotoport=17/1701
|
||||
right= vpn_address_value
|
@ -0,0 +1,2 @@
|
||||
# ipsec.secrets.conf - strongSwan IPsec secrets file
|
||||
: PSK vpn_ipsec_sharedKey_value
|
@ -0,0 +1,16 @@
|
||||
ipcp-accept-local
|
||||
ipcp-accept-remote
|
||||
refuse-eap
|
||||
require-mschap-v2
|
||||
noccp
|
||||
noauth
|
||||
logfile /data/service/el1/public/netmanager/xl2tpd.log
|
||||
idle 1800
|
||||
mtu 1410
|
||||
mru 1410
|
||||
defaultroute
|
||||
usepeerdns
|
||||
debug
|
||||
connect-delay 5000
|
||||
name USERNAME_VALUE
|
||||
password PASSWORD_VALUE
|
@ -0,0 +1,40 @@
|
||||
# strongswan.conf - strongSwan configuration file
|
||||
#
|
||||
# Refer to the strongswan.conf(5) manpage for details
|
||||
#
|
||||
# Configuration changes should be made in the included files
|
||||
|
||||
|
||||
charon {
|
||||
load_modular = yes
|
||||
plugins {
|
||||
include /system/etc/strongswan/strongswan.d/charon/*.conf
|
||||
kernel-libipsec {
|
||||
load = no
|
||||
}
|
||||
}
|
||||
filelog {
|
||||
charon {
|
||||
# path to the log file, specify this as section name in versions prior to 5.7.0
|
||||
path = /data/service/el1/public/netmanager/charon.log
|
||||
# add a timestamp prefix
|
||||
time_format = %b %e %T
|
||||
# prepend connection name, simplifies grepping
|
||||
ike_name = yes
|
||||
# overwrite existing files
|
||||
append = no
|
||||
# increase default loglevel for all daemon subsystems
|
||||
default = 4
|
||||
# flush each line to disk
|
||||
flush_line = yes
|
||||
}
|
||||
stderr {
|
||||
# more detailed loglevel for a specific subsystem, overriding the
|
||||
# default loglevel.
|
||||
ike = 4
|
||||
knl = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include /system/etc/strongswan/strongswan.d/*.conf
|
@ -0,0 +1,6 @@
|
||||
[lac myVPN]
|
||||
; set this to the ip address of your vpn server
|
||||
lns = vpn_address_value
|
||||
ppp debug = yes
|
||||
pppoptfile = /data/service/el1/public/netmanager/options.l2tpd.client.conf
|
||||
length bit = yes
|
29
product/phone/src/main/resources/zh_CN/element/strarray.json
Normal file
29
product/phone/src/main/resources/zh_CN/element/strarray.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"strarray": [
|
||||
{
|
||||
"name": "ovpn_auth_type",
|
||||
"value": [
|
||||
{
|
||||
"value": "证书(TLS)"
|
||||
},
|
||||
{
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"value": "证书和密码(TLS)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ovpn_protocol",
|
||||
"value": [
|
||||
{
|
||||
"value": "TCP"
|
||||
},
|
||||
{
|
||||
"value": "UDP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1491,6 +1491,270 @@
|
||||
{
|
||||
"name": "GET_ACCESS_UDID",
|
||||
"value": "获取UDID的权限"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_title",
|
||||
"value": "要替换现有VPN吗?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_content",
|
||||
"value": "您已连接到VPN,如果您要连接到其他VPN,则系统替换现有VPN."
|
||||
},
|
||||
{
|
||||
"name": "vpn_change_alert_confirm",
|
||||
"value": "替换"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_title",
|
||||
"value": "连接到%s"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_username",
|
||||
"value": "用户名"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_password",
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_save",
|
||||
"value": "保存账户信息"
|
||||
},
|
||||
{
|
||||
"name": "vpn_connect_confirm",
|
||||
"value": "连接"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_title",
|
||||
"value": "编辑VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_alias",
|
||||
"value": "名称"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_type",
|
||||
"value": "类型"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_configfile",
|
||||
"value": "OpenVPN 配置文件"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_ca_cert_file",
|
||||
"value": "CA 证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_user_cert_file",
|
||||
"value": "用户证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key",
|
||||
"value": "私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_private_key_psd",
|
||||
"value": "私钥密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_click_select",
|
||||
"value": "点击选择"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_protocol",
|
||||
"value": "OpenVPN 协议"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_auth_type",
|
||||
"value": "OpenVPN 认证类型"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_serveraddress",
|
||||
"value": "服务器地址"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_serveraddress",
|
||||
"value": "OpenVPN 服务器地址"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_port",
|
||||
"value": "OpenVPN 服务器端口"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecidentifier",
|
||||
"value": "IPSec 标识符"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_l2tpsecret",
|
||||
"value": "L2TP 密钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ipsecsecret",
|
||||
"value": "IPSec 预共享密钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_usercert",
|
||||
"value": "IPSec 用户证书公钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_user_private_cert",
|
||||
"value": "IPSec 用户证书私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cacert",
|
||||
"value": "IPSec CA 证书"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_servercert",
|
||||
"value": "IPSec 服务器证书公钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_server_private_cert",
|
||||
"value": "IPSec 服务器证书私钥"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_unuse",
|
||||
"value": "未使用"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_advanced",
|
||||
"value": "显示高级选项"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_proxy_advanced",
|
||||
"value": "显示代理"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_searchdomains",
|
||||
"value": "DNS 搜索域"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_dnsaddresses",
|
||||
"value": "DNS 服务器(例如 8.8.8.8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_router",
|
||||
"value": "转发路线(例如 10.0.0.0/8)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_host",
|
||||
"value": "OpenVPN 代理主机"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_port",
|
||||
"value": "OpenVPN 代理端口"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_username",
|
||||
"value": "OpenVPN 代理用户名"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_proxy_password",
|
||||
"value": "OpenVPN 代理密码"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_ovpn_useauth",
|
||||
"value": "使用基本身份验证"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_save",
|
||||
"value": "保存"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_specified",
|
||||
"value": "(未指定)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_not_verify_server",
|
||||
"value": "(不验证服务器)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_edit_cert_from_server",
|
||||
"value": "(来自服务器)"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_title",
|
||||
"value": "是否删除%s网络?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_remove_alert_confirm",
|
||||
"value": "删除"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_title",
|
||||
"value": "是否断开%s网络?"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_alert_confirm",
|
||||
"value": "断开"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_edit",
|
||||
"value": "编辑VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "vpn_line_disconnect_operation_remove",
|
||||
"value": "删除VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connect_ing",
|
||||
"value": "连接中..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_success",
|
||||
"value": "连接成功"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_connec_failed",
|
||||
"value": "连接失败"
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnecting",
|
||||
"value": "断开中..."
|
||||
},
|
||||
{
|
||||
"name": "vpn_state_disconnected",
|
||||
"value": "已断开"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_empty",
|
||||
"value": "没有VPN"
|
||||
},
|
||||
{
|
||||
"name": "vpn_list_add",
|
||||
"value": "添加VPN网络"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_cert",
|
||||
"value": "证书( TLS )"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_pass",
|
||||
"value": "密码"
|
||||
},
|
||||
{
|
||||
"name": "ovpn_auth_type_certpass",
|
||||
"value": "证书和密码( TLS )"
|
||||
},
|
||||
{
|
||||
"name": "VPN",
|
||||
"value": "VPN"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_invalid_param",
|
||||
"value": "参数错误"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_operation_failed",
|
||||
"value": "API调用失败"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_system_internal",
|
||||
"value": "系统内部错误"
|
||||
},
|
||||
{
|
||||
"name": "vpn_error_disconnect_first",
|
||||
"value": "请先断开VPN,再操作"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user