add share to guest by web client
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import Clipboard from 'clipboard'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { T } from '@/utils/i18n'
|
||||
|
||||
export function handleClipboard (text, event) {
|
||||
const clipboard = new Clipboard(event.target.toString(), {
|
||||
text: () => text,
|
||||
})
|
||||
clipboard.on('success', () => {
|
||||
ElMessage.success(T('CopySuccess'))
|
||||
clipboard.destroy()
|
||||
})
|
||||
clipboard.on('error', () => {
|
||||
ElMessage.error(T('CopyFailed'))
|
||||
clipboard.destroy()
|
||||
})
|
||||
clipboard.onClick(event)
|
||||
}
|
||||
|
||||
export function copyImage (targetNode) {
|
||||
if (window.getSelection) {
|
||||
// chrome等主流浏览器
|
||||
var selection = window.getSelection()
|
||||
selection.removeAllRanges()
|
||||
var range = document.createRange()
|
||||
range.selectNode(targetNode)
|
||||
selection.addRange(range)
|
||||
} else if (document.body.createTextRange) {
|
||||
console.log('IE')
|
||||
// ie
|
||||
const range = document.body.createTextRange()
|
||||
range.moveToElementText(targetNode)
|
||||
range.select()
|
||||
}
|
||||
document.execCommand('copy')
|
||||
}
|
||||
@@ -282,5 +282,70 @@
|
||||
},
|
||||
"PleaseSelectData": {
|
||||
"One": "Please select data"
|
||||
},
|
||||
"PasswordType": {
|
||||
"One": "Password Type"
|
||||
},
|
||||
"OncePassword": {
|
||||
"One": "One-time Password"
|
||||
},
|
||||
"FixedPassword": {
|
||||
"One": "Fixed Password"
|
||||
},
|
||||
"FixedPasswordWarning": {
|
||||
"One": "Fixed passwords may be leaked, so please use them with caution and use one-time passwords is recommended"
|
||||
},
|
||||
"ExpireTime": {
|
||||
"One": "Expire Time"
|
||||
},
|
||||
"ShareByWebClient": {
|
||||
"One": "Share By Web Client"
|
||||
},
|
||||
"Minutes": {
|
||||
"One": "{param} Minute",
|
||||
"Other": "{param} Minutes"
|
||||
},
|
||||
"Hours": {
|
||||
"One": "{param} Hour",
|
||||
"Other": "{param} Hours"
|
||||
},
|
||||
"Days": {
|
||||
"One": "{param} Day",
|
||||
"Other": "{param} Days"
|
||||
},
|
||||
"Weeks": {
|
||||
"One": "{param} Week",
|
||||
"Other": "{param} Weeks"
|
||||
},
|
||||
"Months": {
|
||||
"One": "{param} Month",
|
||||
"Other": "{param} Months"
|
||||
},
|
||||
"Forever": {
|
||||
"One": "Forever"
|
||||
},
|
||||
"Error": {
|
||||
"One": "Error"
|
||||
},
|
||||
"IDNotExist": {
|
||||
"One": "ID does not exist"
|
||||
},
|
||||
"RemoteDesktopOffline": {
|
||||
"One": "Remote desktop is offline"
|
||||
},
|
||||
"KeyMismatch": {
|
||||
"One": "Key mismatch"
|
||||
},
|
||||
"KeyOveruse": {
|
||||
"One": "Key overuse"
|
||||
},
|
||||
"Link": {
|
||||
"One": "Link"
|
||||
},
|
||||
"CopySuccess": {
|
||||
"One": "Copy Success"
|
||||
},
|
||||
"CopyFailed": {
|
||||
"One": "Copy Failed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,5 +274,65 @@
|
||||
},
|
||||
"PleaseSelectData": {
|
||||
"One": "请选择数据"
|
||||
},
|
||||
"PasswordType": {
|
||||
"One": "密码类型"
|
||||
},
|
||||
"OncePassword": {
|
||||
"One": "一次性密码"
|
||||
},
|
||||
"FixedPassword": {
|
||||
"One": "固定密码"
|
||||
},
|
||||
"FixedPasswordWarning": {
|
||||
"One": "固定密码可能存在泄露风险,请谨慎使用,建议使用一次性密码"
|
||||
},
|
||||
"ExpireTime": {
|
||||
"One": "过期时间"
|
||||
},
|
||||
"ShareByWebClient": {
|
||||
"One": "通过 Web Client 分享"
|
||||
},
|
||||
"Minutes": {
|
||||
"One": "{param} 分钟"
|
||||
},
|
||||
"Hours": {
|
||||
"One": "{param} 小时"
|
||||
},
|
||||
"Days": {
|
||||
"One": "{param} 天"
|
||||
},
|
||||
"Weeks": {
|
||||
"One": "{param} 周"
|
||||
},
|
||||
"Months": {
|
||||
"One": "{param} 月"
|
||||
},
|
||||
"Forever": {
|
||||
"One": "永久"
|
||||
},
|
||||
"Error": {
|
||||
"One": "错误"
|
||||
},
|
||||
"IDNotExist": {
|
||||
"One": "ID 不存在"
|
||||
},
|
||||
"RemoteDesktopOffline": {
|
||||
"One": "远程电脑不在线"
|
||||
},
|
||||
"KeyMismatch": {
|
||||
"One": "KEY不匹配"
|
||||
},
|
||||
"KeyOveruse": {
|
||||
"One": "KEY使用过度"
|
||||
},
|
||||
"Link": {
|
||||
"One": "链接"
|
||||
},
|
||||
"CopySuccess": {
|
||||
"One": "复制成功"
|
||||
},
|
||||
"CopyFailed": {
|
||||
"One": "复制失败"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ service.interceptors.request.use(
|
||||
const app = useAppStore()
|
||||
const lang = app.setting.lang
|
||||
if (lang) {
|
||||
console.log('lang', lang)
|
||||
// console.log('lang', lang)
|
||||
config.headers['Accept-Language'] = lang
|
||||
}
|
||||
|
||||
|
||||
+84
-1
@@ -1,5 +1,10 @@
|
||||
import { ref } from 'vue'
|
||||
import { config } from '@/api/rustdesk'
|
||||
import Websock from '@/utils/webclient/websock'
|
||||
import * as rendezvous from '@/utils/webclient/rendezvous'
|
||||
import * as message from '@/utils/webclient/message'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { T } from '@/utils/i18n'
|
||||
|
||||
export const toWebClientLink = (row) => {
|
||||
window.open(`${rustdeskConfig.value.api_server}/webclient/#/?id=${row.id}`)
|
||||
@@ -23,4 +28,82 @@ export function loadRustdeskConfig () {
|
||||
rustdeskConfig,
|
||||
}
|
||||
}
|
||||
const { rustdeskConfig } = loadRustdeskConfig()
|
||||
|
||||
export const { rustdeskConfig } = loadRustdeskConfig()
|
||||
export async function getPeerSlat (id) {
|
||||
const [addr, port] = rustdeskConfig.value.id_server.split(':')
|
||||
if (!addr) {
|
||||
return
|
||||
}
|
||||
const scheme = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
const ws = new Websock(`${scheme}://${addr}:21118`, true)
|
||||
await ws.open()
|
||||
const conn_type = rendezvous.ConnType.DEFAULT_CONN
|
||||
const nat_type = rendezvous.NatType.SYMMETRIC
|
||||
const punch_hole_request = rendezvous.PunchHoleRequest.fromPartial({
|
||||
id,
|
||||
licence_key: rustdeskConfig.value.key || undefined,
|
||||
conn_type,
|
||||
nat_type,
|
||||
token: undefined,
|
||||
})
|
||||
ws.sendRendezvous({ punch_hole_request })
|
||||
//rendezvous.RendezvousMessage
|
||||
const msg = (await ws.next())
|
||||
ws.close()
|
||||
console.log(new Date() + ': Got relay response', msg)
|
||||
const phr = msg.punch_hole_response
|
||||
const rr = msg.relay_response
|
||||
if (phr) {
|
||||
if (phr?.other_failure) {
|
||||
this.msgbox('error', 'Error', phr?.other_failure)
|
||||
return
|
||||
}
|
||||
if (phr.failure != rendezvous.PunchHoleResponse_Failure.UNRECOGNIZED) {
|
||||
switch (phr?.failure) {
|
||||
case rendezvous.PunchHoleResponse_Failure.ID_NOT_EXIST:
|
||||
ElMessageBox.alert(T('IDNotExist'), T('Error'))
|
||||
break
|
||||
case rendezvous.PunchHoleResponse_Failure.OFFLINE:
|
||||
ElMessageBox.alert(T('RemoteDesktopOffline'), T('Error'))
|
||||
break
|
||||
case rendezvous.PunchHoleResponse_Failure.LICENSE_MISMATCH:
|
||||
ElMessageBox.alert(T('KeyMismatch'), T('Error'))
|
||||
break
|
||||
case rendezvous.PunchHoleResponse_Failure.LICENSE_OVERUSE:
|
||||
ElMessageBox.alert(T('KeyOveruse'), T('Error'))
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
} else if (rr) {
|
||||
const uuid = rr.uuid
|
||||
console.log(new Date() + ': Connecting to relay server')
|
||||
|
||||
const _ws = new Websock(`${scheme}://${addr}:21119`, false)
|
||||
await _ws.open()
|
||||
console.log(new Date() + ': Connected to relay server')
|
||||
const request_relay = rendezvous.RequestRelay.fromPartial({
|
||||
licence_key: rustdeskConfig.value.key || undefined,
|
||||
uuid,
|
||||
})
|
||||
_ws.sendRendezvous({ request_relay })
|
||||
|
||||
//暂不支持pk
|
||||
const public_key = message.PublicKey.fromPartial({})
|
||||
_ws?.sendMessage({ public_key })
|
||||
// const secure = (await this.secure(pk)) || false;
|
||||
// globals.pushEvent("connection_ready", { secure, direct: false });
|
||||
while (true) {
|
||||
const msg = (await _ws?.next())
|
||||
console.log('msg', msg)
|
||||
if (msg?.hash) {
|
||||
console.log('hash msg.....', msg.hash)
|
||||
_ws.close()
|
||||
return msg.hash
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,183 @@
|
||||
import * as message from "./message.js";
|
||||
import * as rendezvous from "./rendezvous.js";
|
||||
|
||||
type Keys = "message" | "open" | "close" | "error";
|
||||
|
||||
export default class Websock {
|
||||
_websocket: WebSocket;
|
||||
_eventHandlers: { [key in Keys]: Function };
|
||||
_buf: (rendezvous.RendezvousMessage | message.Message)[];
|
||||
_status: any;
|
||||
_latency: number;
|
||||
_secretKey: [Uint8Array, number, number] | undefined;
|
||||
_uri: string;
|
||||
_isRendezvous: boolean;
|
||||
|
||||
constructor(uri: string, isRendezvous: boolean = true) {
|
||||
this._eventHandlers = {
|
||||
message: (_: any) => {},
|
||||
open: () => {},
|
||||
close: () => {},
|
||||
error: () => {},
|
||||
};
|
||||
this._uri = uri;
|
||||
this._status = "";
|
||||
this._buf = [];
|
||||
this._websocket = new WebSocket(uri);
|
||||
this._websocket.onmessage = this._recv_message.bind(this);
|
||||
this._websocket.binaryType = "arraybuffer";
|
||||
this._latency = new Date().getTime();
|
||||
this._isRendezvous = isRendezvous;
|
||||
}
|
||||
|
||||
latency(): number {
|
||||
return this._latency;
|
||||
}
|
||||
|
||||
setSecretKey(key: Uint8Array) {
|
||||
this._secretKey = [key, 0, 0];
|
||||
}
|
||||
|
||||
sendMessage(json: message.DeepPartial<message.Message>) {
|
||||
let data = message.Message.encode(
|
||||
message.Message.fromPartial(json)
|
||||
).finish();
|
||||
// let k = this._secretKey;
|
||||
// if (k) {
|
||||
// k[1] += 1;
|
||||
// data = globals.encrypt(data, k[1], k[0]);
|
||||
// }
|
||||
this._websocket.send(data);
|
||||
}
|
||||
|
||||
sendRendezvous(data: rendezvous.DeepPartial<rendezvous.RendezvousMessage>) {
|
||||
this._websocket.send(
|
||||
rendezvous.RendezvousMessage.encode(
|
||||
rendezvous.RendezvousMessage.fromPartial(data)
|
||||
).finish()
|
||||
);
|
||||
}
|
||||
|
||||
parseMessage(data: Uint8Array) {
|
||||
return message.Message.decode(data);
|
||||
}
|
||||
|
||||
parseRendezvous(data: Uint8Array) {
|
||||
return rendezvous.RendezvousMessage.decode(data);
|
||||
}
|
||||
|
||||
// Event Handlers
|
||||
off(evt: Keys) {
|
||||
this._eventHandlers[evt] = () => {};
|
||||
}
|
||||
|
||||
on(evt: Keys, handler: Function) {
|
||||
this._eventHandlers[evt] = handler;
|
||||
}
|
||||
|
||||
async open(timeout: number = 12000): Promise<Websock> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
if (this._status != "open") {
|
||||
reject(this._status || "Timeout");
|
||||
}
|
||||
}, timeout);
|
||||
this._websocket.onopen = () => {
|
||||
this._latency = new Date().getTime() - this._latency;
|
||||
this._status = "open";
|
||||
console.debug(">> WebSock.onopen");
|
||||
if (this._websocket?.protocol) {
|
||||
console.info(
|
||||
"Server choose sub-protocol: " + this._websocket.protocol
|
||||
);
|
||||
}
|
||||
|
||||
this._eventHandlers.open();
|
||||
console.info("WebSock.onopen");
|
||||
resolve(this);
|
||||
};
|
||||
this._websocket.onclose = (e) => {
|
||||
if (this._status == "open") {
|
||||
// e.code 1000 means that the connection was closed normally.
|
||||
//
|
||||
}
|
||||
this._status = e;
|
||||
console.error("WebSock.onclose: ");
|
||||
console.error(e);
|
||||
this._eventHandlers.close(e);
|
||||
reject("Reset by the peer");
|
||||
};
|
||||
this._websocket.onerror = (e: any) => {
|
||||
if (!this._status) {
|
||||
reject("Failed to connect to " + (this._isRendezvous ? "rendezvous" : "relay") + " server");
|
||||
return;
|
||||
}
|
||||
this._status = e;
|
||||
console.error("WebSock.onerror: ")
|
||||
console.error(e);
|
||||
this._eventHandlers.error(e);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async next(
|
||||
timeout = 12000
|
||||
): Promise<rendezvous.RendezvousMessage | message.Message> {
|
||||
const func = (
|
||||
resolve: (value: rendezvous.RendezvousMessage | message.Message) => void,
|
||||
reject: (reason: any) => void,
|
||||
tm0: number
|
||||
) => {
|
||||
// console.log('next')
|
||||
if (this._buf.length) {
|
||||
resolve(this._buf[0]);
|
||||
this._buf.splice(0, 1);
|
||||
} else {
|
||||
if (this._status != "open") {
|
||||
reject(this._status);
|
||||
return;
|
||||
}
|
||||
if (new Date().getTime() > tm0 + timeout) {
|
||||
reject("Timeout");
|
||||
} else {
|
||||
setTimeout(() => func(resolve, reject, tm0), 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
func(resolve, reject, new Date().getTime());
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
this._status = "";
|
||||
if (this._websocket) {
|
||||
if (
|
||||
this._websocket.readyState === WebSocket.OPEN ||
|
||||
this._websocket.readyState === WebSocket.CONNECTING
|
||||
) {
|
||||
console.info("Closing WebSocket connection");
|
||||
this._websocket.close();
|
||||
}
|
||||
|
||||
this._websocket.onmessage = () => {};
|
||||
}
|
||||
}
|
||||
|
||||
_recv_message(e: any) {
|
||||
if (e.data instanceof window.ArrayBuffer) {
|
||||
let bytes = new Uint8Array(e.data);
|
||||
// const k = this._secretKey;
|
||||
// if (k) {
|
||||
// k[2] += 1;
|
||||
// bytes = globals.decrypt(bytes, k[2], k[0]);
|
||||
// }
|
||||
this._buf.push(
|
||||
this._isRendezvous
|
||||
? this.parseRendezvous(bytes)
|
||||
: this.parseMessage(bytes)
|
||||
);
|
||||
}
|
||||
this._eventHandlers.message(e.data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user