Compare commits

..

No commits in common. "c35179d9240647884f592622d036bfad228f7bda" and "a0dd101d9778f11dfe4866e7bc71c5119bcbf6fa" have entirely different histories.

5 changed files with 67 additions and 48 deletions

View file

@ -1050,7 +1050,7 @@ class Allocate extends XrayCommonClass {
class Inbound extends XrayCommonClass { class Inbound extends XrayCommonClass {
constructor( constructor(
port = RandomUtil.randomInteger(10000, 60000), port = RandomUtil.randomIntRange(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.randomInteger(10000, 60000); this.port = RandomUtil.randomIntRange(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,48 +80,66 @@ class PromiseUtil {
} }
} }
const seq = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
class RandomUtil { class RandomUtil {
static getSeq({ hasNumbers = true, hasLowercase = true, hasUppercase = true } = {}) { static randomIntRange(min, max) {
let seq = ''; return Math.floor(Math.random() * (max - min) + min);
if (hasNumbers) seq += "0123456789";
if (hasLowercase) seq += "abcdefghijklmnopqrstuvwxyz";
if (hasUppercase) seq += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return seq;
} }
static randomInteger(min, max) { static randomInt(n) {
const range = max - min + 1; return this.randomIntRange(0, n);
const randomBuffer = new Uint32Array(1);
window.crypto.getRandomValues(randomBuffer);
return Math.floor((randomBuffer[0] / (0xFFFFFFFF + 1)) * range) + min;
} }
static randomSeq(count, options = {}) { static randomSeq(count) {
const seq = this.getSeq(options); let str = '';
const seqLength = seq.length; for (let i = 0; i < count; ++i) {
const randomValues = new Uint32Array(count); str += seq[this.randomInt(62)];
window.crypto.getRandomValues(randomValues); }
return Array.from(randomValues, v => seq[v % seqLength]).join(''); return str;
} }
static randomShortIds() { static randomShortIds() {
const lengths = [2, 4, 6, 8, 10, 12, 14, 16].sort(() => Math.random() - 0.5); const lengths = [2, 4, 6, 8, 10, 12, 14, 16];
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]];
}
return lengths.map(len => this.randomSeq(len)).join(','); let shortIds = [];
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) {
return this.randomSeq(len, { hasUppercase: false }); let str = '';
for (let i = 0; i < len; ++i) {
str += seq[this.randomInt(36)];
}
return str;
} }
static randomUUID() { static randomUUID() {
return window.crypto.randomUUID(); const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
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() {
const array = new Uint8Array(32); let array = new Uint8Array(32);
window.crypto.getRandomValues(array); window.crypto.getRandomValues(array);
return Base64.encode(String.fromCharCode(...array)); return btoa(String.fromCharCode.apply(null, array));
} }
} }

View file

@ -8,7 +8,6 @@
<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.randomInteger(10000, 60000), port: RandomUtil.randomIntRange(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 {
gap: 10px; text-align: left;
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: 100%;" <a-alert type="warning" style="margin-bottom: 12px; width: fit-content"
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,25 +334,27 @@
:closable="true" :closable="true"
footer="" footer=""
:class="themeSwitcher.currentTheme"> :class="themeSwitcher.currentTheme">
<a-list class="ant-backup-list" bordered style="width: 100%;"> <a-space direction="horizontal" style="text-align: center; margin-bottom: 10px;">
<a-list-item class="ant-backup-list-item" @click="exportDatabase()"> <a-list class="ant-backup-list" bordered style="width: 100%;">
<a-list-item-meta> <a-list-item class="ant-backup-list-item" @click="exportDatabase()">
<template #title>{{ i18n "pages.index.exportDatabase" }}</template> <a-list-item-meta>
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template> <template #title>{{ i18n "pages.index.exportDatabase" }}</template>
</a-list-item-meta> <template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
<a-icon type="right" /> </a-list-item-meta>
</a-list-item> <a-icon type="right" />
<a-list-item class="ant-backup-list-item" @click="importDatabase()"> </a-list-item>
<a-list-item-meta> <a-list-item class="ant-backup-list-item" @click="importDatabase()">
<template #title>{{ i18n "pages.index.importDatabase" }}</template> <a-list-item-meta>
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template> <template #title>{{ i18n "pages.index.importDatabase" }}</template>
<templaet #avatar> <template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
<a-icon type="import" /> <templaet #avatar>
</templaet> <a-icon type="import" />
</a-list-item-meta> </templaet>
<a-icon type="right" /> </a-list-item-meta>
</a-list-item> <a-icon type="right" />
</a-list> </a-list-item>
</a-list>
</a-space>
</a-modal> </a-modal>
</a-layout> </a-layout>
{{template "js" .}} {{template "js" .}}