Skip to content

Commit

Permalink
support XEP-0106: JID Escaping (fix #501)
Browse files Browse the repository at this point in the history
  • Loading branch information
sualko committed Jun 30, 2017
1 parent 757770b commit 457e175
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 8 deletions.
50 changes: 42 additions & 8 deletions src/JID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,54 @@ export default class JID implements JIDInterface {
public readonly resource:string;

constructor(full:string) {
this.full = (full || '').toLowerCase();
let matches = /(([^@]+)@([^/]+))(?:\/(.+))?/.exec(this.full);
let matches = /([^@]+)@([^/]+)(?:\/(.+))?/.exec(full);

this.bare = matches[1];
this.node = matches[2];
this.domain = matches[3];
this.resource = matches[4];
this.node = this.unescapeNode(matches[1].toLowerCase());
this.domain = matches[2].toLowerCase();
this.resource = matches[3];

this.bare = this.node + '@' + this.domain;
this.full = this.bare + ((this.resource) ? '/' + this.resource : '');
}

public toString() {
public toString():string {
return this.full;
}

public isBare() {
public toEscapedString():string {
let bare = this.escapeNode(this.node) + '@' + this.domain;

return bare + ((this.resource) ? '/' + this.resource : '');
}

public isBare():boolean {
return this.full === this.bare;
}

private escapeNode(node:string) {
return node.replace(/^\s+|\s+$/g, '')
.replace(/\\/g, "\\5c")
.replace(/ /g, "\\20")
.replace(/\"/g, "\\22")
.replace(/\&/g, "\\26")
.replace(/\'/g, "\\27")
.replace(/\//g, "\\2f")
.replace(/:/g, "\\3a")
.replace(/</g, "\\3c")
.replace(/>/g, "\\3e")
.replace(/@/g, "\\40");
}

private unescapeNode(node:string) {
return node.replace(/\\20/g, " ")
.replace(/\\22/g, '"')
.replace(/\\26/g, "&")
.replace(/\\27/g, "'")
.replace(/\\2f/g, "/")
.replace(/\\3a/g, ":")
.replace(/\\3c/g, "<")
.replace(/\\3e/g, ">")
.replace(/\\40/g, "@")
.replace(/\\5c/g, "\\");
}
}
91 changes: 91 additions & 0 deletions test/JID.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {expect} from 'chai';
import * as sinon from 'sinon';
import 'mocha';

import JID from '../src/JID'

class JIDDummy {
constructor(public node:string, public domain:string, public resource:string) {

}

public toEscapedString() {
let node = this.node.replace(/^\s+|\s+$/g, '')
.replace(/\\/g, "\\5c")
.replace(/ /g, "\\20")
.replace(/\"/g, "\\22")
.replace(/\&/g, "\\26")
.replace(/\'/g, "\\27")
.replace(/\//g, "\\2f")
.replace(/:/g, "\\3a")
.replace(/</g, "\\3c")
.replace(/>/g, "\\3e")
.replace(/@/g, "\\40");

return node + '@' + this.domain + ((this.resource) ? '/' + this.resource : '');
}

public toUnescapedString() {
return this.node + '@' + this.domain + ((this.resource) ? '/' + this.resource : '');
}
}

describe('JID', function() {

let jids = [
new JIDDummy('foo', 'localhost'),
new JIDDummy('foo.bar', 'localhost'),
new JIDDummy('foo', 'bar.local'),
new JIDDummy('foo.bar', 'local.host'),
new JIDDummy('foo.bar', 'localhost', 'res'),
new JIDDummy('foo.bar', 'local.host', 'random'),
new JIDDummy('foo.bar', 'local.host', 'rand/om'),
new JIDDummy('äöüßᚹᛦᛚᚳᚢᛗணோம்', 'local.host', '私はガラス'),
new JIDDummy('foo bar', 'local.host', 'rand om'),
new JIDDummy('foo "&\'":<>@bar', 'your.local.host')
];

it('should split a JID in its components', function() {
jids.forEach((dummy) => {
let jid = new JID(dummy.toEscapedString());

expect(jid.node).equals(dummy.node);
expect(jid.domain).equals(dummy.domain);
expect(jid.resource).equals(dummy.resource);
});
});

it('should escape a JID', function() {
jids.forEach((dummy) => {
let jid = new JID(dummy.toEscapedString());

expect(jid.toEscapedString()).equals(dummy.toEscapedString());
});
});

it('should unescape a JID', function() {
jids.forEach((dummy) => {
let jid = new JID(dummy.toEscapedString());

expect(jid.toString()).equals(dummy.toUnescapedString());
});
});

it('should lower-case node and domain part', function() {
let jid1 = new JID('Foo.Bar@Local.Host/Random');
let jid2 = new JID('fOo.baR@loCAL.HOST/Random');

expect(jid1.node).equals(jid2.node);
expect(jid1.domain).equals(jid2.domain);

expect(jid1.toString()).equals(jid2.toString());
});

it('should not lower-case resource part', function() {
let jid1 = new JID('Foo.Bar@Local.Host/RanDom');
let jid2 = new JID('fOo.baR@loCAL.HOST/RANDOM');

expect(jid1.resource).not.equals(jid2.resource);
expect(jid1.toString()).not.equal(jid2.toString());
});
});

0 comments on commit 457e175

Please sign in to comment.