///
namespace profiles.identities {
export namespace TSIdentityHelper {
export let funcationParseIdentity: any;
export let funcationParseIdentityByFile: any;
export let funcationCalculateSecurityLevel: any;
export let functionUid: any;
export let funcationExportIdentity: any;
export let funcationPublicKey: any;
export let funcationSignMessage: any;
let functionLastError: any;
let functionClearLastError: any;
let functionDestroyString: any;
let functionDestroyIdentity: any;
export function setup() : boolean {
functionDestroyString = Module.cwrap("destroy_string", "pointer", []);
functionLastError = Module.cwrap("last_error_message", null, ["string"]);
funcationParseIdentity = Module.cwrap("parse_identity", "pointer", ["string"]);
funcationParseIdentityByFile = Module.cwrap("parse_identity_file", "pointer", ["string"]);
functionDestroyIdentity = Module.cwrap("delete_identity", null, ["pointer"]);
funcationCalculateSecurityLevel = Module.cwrap("identity_security_level", "pointer", ["pointer"]);
funcationExportIdentity = Module.cwrap("identity_export", "pointer", ["pointer"]);
funcationPublicKey = Module.cwrap("identity_key_public", "pointer", ["pointer"]);
funcationSignMessage = Module.cwrap("identity_sign", "pointer", ["pointer", "string", "number"]);
functionUid = Module.cwrap("identity_uid", "pointer", ["pointer"]);
return Module.cwrap("tomcrypt_initialize", "number", [])() == 0;
}
export function last_error() : string {
return unwarpString(functionLastError());
}
export function unwarpString(str) : string {
if(str == "") return "";
try {
if(!$.isFunction(window.Pointer_stringify)) {
displayCriticalError(tr("Missing required wasm function!
Please reload the page!"));
}
let message: string = window.Pointer_stringify(str);
functionDestroyString(str);
return message;
} catch (error) {
console.error(error);
return "";
}
}
export function loadIdentity(key: string) : TeamSpeakIdentity {
try {
let handle = funcationParseIdentity(key);
if(!handle) return undefined;
return new TeamSpeakIdentity(handle, "TeaWeb user");
} catch(error) {
console.error(error);
}
return undefined;
}
export function loadIdentityFromFileContains(contains: string) : TeamSpeakIdentity {
let handle = funcationParseIdentityByFile(contains);
if(!handle) return undefined;
return new TeamSpeakIdentity(handle, "TeaWeb user");
}
export function load_identity(handle: TeamSpeakIdentity, key) : boolean {
let native_handle = funcationParseIdentity(key);
if(!native_handle) return false;
handle["handle"] = native_handle;
return true;
}
}
class TeamSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
identity: TeamSpeakIdentity;
constructor(connection: ServerConnection, identity: TeamSpeakIdentity) {
super(connection);
this.identity = identity;
}
start_handshake() {
this.connection.commandHandler["handshakeidentityproof"] = this.handle_proof.bind(this);
this.connection.sendCommand("handshakebegin", {
intention: 0,
authentication_method: this.identity.type(),
publicKey: this.identity.publicKey()
}).catch(error => {
console.error(tr("Failed to initialize TeamSpeak based handshake. Error: %o"), error);
if(error instanceof CommandResult)
error = error.extra_message || error.message;
this.trigger_fail("failed to execute begin (" + error + ")");
});
}
private handle_proof(json) {
const proof = this.identity.signMessage(json[0]["message"]);
this.connection.sendCommand("handshakeindentityproof", {proof: proof}).catch(error => {
console.error(tr("Failed to proof the identity. Error: %o"), error);
if(error instanceof CommandResult)
error = error.extra_message || error.message;
this.trigger_fail("failed to execute proof (" + error + ")");
}).then(() => this.trigger_success());
}
}
export class TeamSpeakIdentity implements Identity {
private handle: any;
private _name: string;
constructor(handle: any, name: string) {
this.handle = handle;
this._name = name;
}
securityLevel() : number | undefined {
return parseInt(TSIdentityHelper.unwarpString(TSIdentityHelper.funcationCalculateSecurityLevel(this.handle)));
}
name() : string { return this._name; }
uid() : string {
return TSIdentityHelper.unwarpString(TSIdentityHelper.functionUid(this.handle));
}
type() : IdentitifyType { return IdentitifyType.TEAMSPEAK; }
signMessage(message: string): string {
return TSIdentityHelper.unwarpString(TSIdentityHelper.funcationSignMessage(this.handle, message, message.length));
}
exported() : string {
return TSIdentityHelper.unwarpString(TSIdentityHelper.funcationExportIdentity(this.handle));
}
publicKey() : string {
return TSIdentityHelper.unwarpString(TSIdentityHelper.funcationPublicKey(this.handle));
}
valid() : boolean { return this.handle !== undefined; }
decode(data) : boolean {
data = JSON.parse(data);
if(data.version != 1) return false;
if(!TSIdentityHelper.load_identity(this, data["key"]))
return false;
this._name = data["name"];
return true;
}
encode?() : string {
if(!this.handle) return undefined;
const key = this.exported();
if(!key) return undefined;
return JSON.stringify({
key: key,
name: this._name,
version: 1
})
}
spawn_identity_handshake_handler(connection: ServerConnection) : HandshakeIdentityHandler {
return new TeamSpeakHandshakeHandler(connection, this);
}
}
export function setup_teamspeak() : boolean {
return TSIdentityHelper.setup();
}
}