Compare commits

...

10 commits

Author SHA1 Message Date
Shishkevich D.
c35179d924 chore: remove unused variable 2025-03-09 06:38:45 +00:00
Shishkevich D.
cedc7f0fb8 chore: refactoring RandomUtil class
now we use window.crypto.getRandomValues to generate random values.
2025-03-09 06:37:05 +00:00
Shishkevich D.
64fa0e97a3 chore: use crypto.randomUUID() for generating UUIDv4 2025-03-09 06:09:42 +00:00
Shishkevich D.
a45e9de472 chore: use Base64 library for generating SS password 2025-03-09 06:06:27 +00:00
Shishkevich D.
101e9ebf35 fix: modals style 2025-03-09 06:01:27 +00:00
Shishkevich D.
17a76d2843 Revert "chore: add missing params for grpc stream settings (outbound)"
This reverts commit 1c59afe031.
2025-03-09 05:38:34 +00:00
Shishkevich D.
a23a5de540 Revert "chore: add new grpc params for outbound (#2744)"
This reverts commit c49ec9a74c.
2025-03-09 05:37:50 +00:00
Shishkevich D.
a16e83468b
chore: add dns type for kcp protocol
see https://xtls.github.io/config/transports/mkcp.html#headerobject
2025-03-09 12:23:35 +07:00
Shishkevich D.
1c59afe031 chore: add missing params for grpc stream settings (outbound) 2025-03-09 04:49:17 +00:00
Shishkevich D.
c49ec9a74c
chore: add new grpc params for outbound (#2744) 2025-03-09 11:28:12 +07:00
5 changed files with 48 additions and 67 deletions

View file

@ -1050,7 +1050,7 @@ class Allocate extends XrayCommonClass {
class Inbound extends XrayCommonClass { class Inbound extends XrayCommonClass {
constructor( constructor(
port = RandomUtil.randomIntRange(10000, 60000), port = RandomUtil.randomInteger(10000, 60000),
listen = '', listen = '',
protocol = Protocols.VLESS, protocol = Protocols.VLESS,
settings = null, settings = null,
@ -1226,7 +1226,7 @@ class Inbound extends XrayCommonClass {
} }
reset() { reset() {
this.port = RandomUtil.randomIntRange(10000, 60000); this.port = RandomUtil.randomInteger(10000, 60000);
this.listen = ''; this.listen = '';
this.protocol = Protocols.VMESS; this.protocol = Protocols.VMESS;
this.settings = Inbound.Settings.getSettings(Protocols.VMESS); this.settings = Inbound.Settings.getSettings(Protocols.VMESS);

View file

@ -80,66 +80,48 @@ class PromiseUtil {
} }
} }
const seq = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
class RandomUtil { class RandomUtil {
static randomIntRange(min, max) { static getSeq({ hasNumbers = true, hasLowercase = true, hasUppercase = true } = {}) {
return Math.floor(Math.random() * (max - min) + min); let seq = '';
if (hasNumbers) seq += "0123456789";
if (hasLowercase) seq += "abcdefghijklmnopqrstuvwxyz";
if (hasUppercase) seq += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return seq;
} }
static randomInt(n) { static randomInteger(min, max) {
return this.randomIntRange(0, n); const range = max - min + 1;
const randomBuffer = new Uint32Array(1);
window.crypto.getRandomValues(randomBuffer);
return Math.floor((randomBuffer[0] / (0xFFFFFFFF + 1)) * range) + min;
} }
static randomSeq(count) { static randomSeq(count, options = {}) {
let str = ''; const seq = this.getSeq(options);
for (let i = 0; i < count; ++i) { const seqLength = seq.length;
str += seq[this.randomInt(62)]; const randomValues = new Uint32Array(count);
} window.crypto.getRandomValues(randomValues);
return str; return Array.from(randomValues, v => seq[v % seqLength]).join('');
} }
static randomShortIds() { static randomShortIds() {
const lengths = [2, 4, 6, 8, 10, 12, 14, 16]; const lengths = [2, 4, 6, 8, 10, 12, 14, 16].sort(() => Math.random() - 0.5);
for (let i = lengths.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[lengths[i], lengths[j]] = [lengths[j], lengths[i]];
}
let shortIds = []; return lengths.map(len => this.randomSeq(len)).join(',');
for (let length of lengths) {
let shortId = '';
for (let i = 0; i < length; i++) {
shortId += seq[this.randomInt(16)];
}
shortIds.push(shortId);
}
return shortIds.join(',');
} }
static randomLowerAndNum(len) { static randomLowerAndNum(len) {
let str = ''; return this.randomSeq(len, { hasUppercase: false });
for (let i = 0; i < len; ++i) {
str += seq[this.randomInt(36)];
}
return str;
} }
static randomUUID() { static randomUUID() {
const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; return window.crypto.randomUUID();
return template.replace(/[xy]/g, function (c) {
const randomValues = new Uint8Array(1);
crypto.getRandomValues(randomValues);
let randomValue = randomValues[0] % 16;
let calculatedValue = (c === 'x') ? randomValue : (randomValue & 0x3 | 0x8);
return calculatedValue.toString(16);
});
} }
static randomShadowsocksPassword() { static randomShadowsocksPassword() {
let array = new Uint8Array(32); const array = new Uint8Array(32);
window.crypto.getRandomValues(array); window.crypto.getRandomValues(array);
return btoa(String.fromCharCode.apply(null, array)); return Base64.encode(String.fromCharCode(...array));
} }
} }

View file

@ -8,6 +8,7 @@
<a-select-option value="wechat-video">WeChat</a-select-option> <a-select-option value="wechat-video">WeChat</a-select-option>
<a-select-option value="dtls">DTLS 1.2</a-select-option> <a-select-option value="dtls">DTLS 1.2</a-select-option>
<a-select-option value="wireguard">WireGuard</a-select-option> <a-select-option value="wireguard">WireGuard</a-select-option>
<a-select-option value="dns">DNS</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>

View file

@ -927,7 +927,7 @@
expiryTime: dbInbound.expiryTime, expiryTime: dbInbound.expiryTime,
listen: '', listen: '',
port: RandomUtil.randomIntRange(10000, 60000), port: RandomUtil.randomInteger(10000, 60000),
protocol: baseInbound.protocol, protocol: baseInbound.protocol,
settings: Inbound.Settings.getSettings(baseInbound.protocol).toString(), settings: Inbound.Settings.getSettings(baseInbound.protocol).toString(),
streamSettings: baseInbound.stream.toString(), streamSettings: baseInbound.stream.toString(),

View file

@ -20,7 +20,7 @@
color: var(--dark-color-text-primary); color: var(--dark-color-text-primary);
} }
.ant-backup-list-item { .ant-backup-list-item {
text-align: left; gap: 10px;
user-select: none; user-select: none;
cursor: pointer; cursor: pointer;
} }
@ -272,7 +272,7 @@
</a-layout> </a-layout>
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true" <a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer=""> @ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
<a-alert type="warning" style="margin-bottom: 12px; width: fit-content" <a-alert type="warning" style="margin-bottom: 12px; width: 100%;"
message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert> message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
<a-list class="ant-xray-version-list" bordered style="width: 100%;"> <a-list class="ant-xray-version-list" bordered style="width: 100%;">
<a-list-item class="ant-xray-version-list-item" v-for="version in versionModal.versions"> <a-list-item class="ant-xray-version-list-item" v-for="version in versionModal.versions">
@ -334,27 +334,25 @@
:closable="true" :closable="true"
footer="" footer=""
:class="themeSwitcher.currentTheme"> :class="themeSwitcher.currentTheme">
<a-space direction="horizontal" style="text-align: center; margin-bottom: 10px;"> <a-list class="ant-backup-list" bordered style="width: 100%;">
<a-list class="ant-backup-list" bordered style="width: 100%;"> <a-list-item class="ant-backup-list-item" @click="exportDatabase()">
<a-list-item class="ant-backup-list-item" @click="exportDatabase()"> <a-list-item-meta>
<a-list-item-meta> <template #title>{{ i18n "pages.index.exportDatabase" }}</template>
<template #title>{{ i18n "pages.index.exportDatabase" }}</template> <template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template> </a-list-item-meta>
</a-list-item-meta> <a-icon type="right" />
<a-icon type="right" /> </a-list-item>
</a-list-item> <a-list-item class="ant-backup-list-item" @click="importDatabase()">
<a-list-item class="ant-backup-list-item" @click="importDatabase()"> <a-list-item-meta>
<a-list-item-meta> <template #title>{{ i18n "pages.index.importDatabase" }}</template>
<template #title>{{ i18n "pages.index.importDatabase" }}</template> <template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template> <templaet #avatar>
<templaet #avatar> <a-icon type="import" />
<a-icon type="import" /> </templaet>
</templaet> </a-list-item-meta>
</a-list-item-meta> <a-icon type="right" />
<a-icon type="right" /> </a-list-item>
</a-list-item> </a-list>
</a-list>
</a-space>
</a-modal> </a-modal>
</a-layout> </a-layout>
{{template "js" .}} {{template "js" .}}