diff --git a/config.js.example b/config.js.example
index 08ecf73..7a36cb3 100644
--- a/config.js.example
+++ b/config.js.example
@@ -65,3 +65,11 @@ exports.production = {
// }*/
//]
};
+
+// Test suite settings
+exports.testing = {
+ port: 19123,
+ xmppDomain: 'localhost',
+ xmppHost: '127.0.0.1',
+ xmppPort: 15222,
+};
diff --git a/package.json b/package.json
index b2724f8..7fad7ba 100644
--- a/package.json
+++ b/package.json
@@ -15,11 +15,11 @@
"dependencies": {
"connect": "2.4.x",
"express": "3.x",
- "libxmljs": "0.5.x",
- "ltx": "0.2.x",
- "node-expat": "1.6.x",
- "node-stringprep": "0.1.x",
- "node-xmpp": "0.3.2",
+ "libxmljs": "~0.8.1",
+ "ltx": "~0.3.0",
+ "node-expat": "~2.0.0",
+ "node-stringprep": "~0.1.8",
+ "node-xmpp": "~0.7.0",
"jwt-simple": "0.1.x",
"iso8601": "1.1.1",
"pubcontrol": "0.3.1",
diff --git a/src/metadata.js b/src/metadata.js
index ba55085..0c1453f 100644
--- a/src/metadata.js
+++ b/src/metadata.js
@@ -41,7 +41,6 @@ exports.setup = function(app) {
function getNodeMetadata(req, res) {
var channel = req.params.channel;
var node = req.params.node;
-
requestNodeMetadata(req, res, channel, node, function(reply) {
var body = replyToJSON(reply);
res.contentType('json');
@@ -86,7 +85,7 @@ function getOption(reply, name) {
function setNodeMetadata(req, res) {
var channel = req.params.channel;
var node = req.params.node;
- var fields = JSON.parse(req.body);
+ var fields = JSON.parse(req.body.toString() || '{}');
configureNode(req, res, channel, node, fields, function() {
res.send(200);
diff --git a/src/subscriptions.js b/src/subscriptions.js
index 6abf664..28fec64 100644
--- a/src/subscriptions.js
+++ b/src/subscriptions.js
@@ -158,15 +158,15 @@ function extractSubscriptionCommand(body) {
function subscribe(req, res, channel, node, callback) {
var nodeId = pubsub.channelNodeId(channel, node);
- var bareJid = req.user.split('/', 2)[0];
- var iq = pubsub.subscribeIq(nodeId, bareJid);
+ var jid = req.user;
+ var iq = pubsub.subscribeIq(nodeId, jid);
api.sendQuery(req, res, iq, callback);
}
function unsubscribe(req, res, channel, node, callback) {
var nodeId = pubsub.channelNodeId(channel, node);
- var bareJid = req.user.split('/', 2)[0];
- var iq = pubsub.unsubscribeIq(nodeId, bareJid);
+ var jid = req.user;
+ var iq = pubsub.unsubscribeIq(nodeId, jid);
api.sendQuery(req, res, iq, callback);
}
@@ -177,27 +177,8 @@ function getNodeSubscriptions(req, res) {
var node = req.params.node;
requestNodeAffiliations(req, res, channel, node, function(reply) {
var body = replyToJSON(reply, 'node');
- if (!body[req.session.jid]) {
- var nodeId = pubsub.channelNodeId(channel, node);
- console.log(req.session.jid + " is not subscribed to " + nodeId + ", creating temporary subscription");
- req.session.subscribe(nodeId, function(sub) {
- res.contentType('json');
- res.send(body);
- }, function(errstr) {
- if (errstr == 'registration-required') {
- if (req.user) {
- res.send(403);
- } else {
- api.sendUnauthorized(res);
- }
- } else {
- res.send(500);
- }
- });
- } else {
- res.contentType('json');
- res.send(body);
- }
+ res.contentType('json');
+ res.send(body);
});
}
diff --git a/src/util/atom.js b/src/util/atom.js
index b78b3fe..e748cf3 100644
--- a/src/util/atom.js
+++ b/src/util/atom.js
@@ -174,7 +174,7 @@ exports.fromJSON = function(entry) {
var content = '';
if (entry.content) {
- content = escapeText(entry.content);
+ content = entry.content;
}
entrydoc.root().
node('content', content).
diff --git a/src/util/pubsub.js b/src/util/pubsub.js
index b36d43f..bf3881f 100644
--- a/src/util/pubsub.js
+++ b/src/util/pubsub.js
@@ -186,7 +186,10 @@ exports.userSubscriptionsIq = function() {
*/
exports.subscribeIq = function(nodeId, jid, isTemp) {
var query = iq({type: 'set'});
- query.c('subscribe', {node: nodeId, jid: jid});
+ query.c('subscribe', {
+ node: nodeId,
+ jid: bareJid(jid)
+ });
if (isTemp) {
var form = query.c('options').
c('x', {xmlns: 'jabber:x:data', type: 'submit'});
@@ -202,10 +205,14 @@ exports.subscribeIq = function(nodeId, jid, isTemp) {
*/
exports.unsubscribeIq = function(nodeId, jid) {
return iq({type: 'set'}).
- c('unsubscribe', {node: nodeId, jid: jid}).
+ c('unsubscribe', {node: nodeId, jid: bareJid(jid)}).
root();
};
+function bareJid(jid) {
+ return (jid.indexOf('/') != -1) ? jid.split('/', 2)[0] : jid;
+}
+
/**
* Creates a Pub-Sub IQ which sets a node's configuration.
*/
diff --git a/src/util/session.js b/src/util/session.js
index a0bfc1d..081044b 100644
--- a/src/util/session.js
+++ b/src/util/session.js
@@ -95,7 +95,7 @@ function createSession(req, res, next) {
// FIXME: Checking the error type bassed on the error message
// is fragile, but this is the only information that node-xmpp
// gives us.
- console.log(err);
+ console.error(err);
sessionCache.remove(req.credentials);
for (var n = 0; n < session.waitingReqs.length; ++n) {
var wr = session.waitingReqs[n];
@@ -126,7 +126,7 @@ function xmppConnectionOptions(req) {
jid: '@' + domain,
host: host,
port: port,
- preferredSaslMechanism: 'ANONYMOUS'
+ //preferredSaslMechanism: 'ANONYMOUS'
};
}
}
@@ -430,4 +430,4 @@ Session.prototype.subscribe = function(nodeId, onsub, onerror) {
}
}
});
-}
\ No newline at end of file
+}
diff --git a/test/metadata.js b/test/metadata.js
index 02ea520..60c3ee7 100644
--- a/test/metadata.js
+++ b/test/metadata.js
@@ -213,6 +213,7 @@ describe('Node Metadata', function() {
res.statusCode.should.equal(200);
delete options.body;
+ delete options.method;
tutil.get(options, function(res, body) {
res.statusCode.should.equal(200);
var metadata = JSON.parse(body);
diff --git a/test/session.js b/test/session.js
deleted file mode 100644
index 610f6af..0000000
--- a/test/session.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2012 Denis Washington
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// test/session.js:
-// Tests session management.
-
-var should = require('should');
-var xml = require('libxmljs');
-var atom = require('../src/util/atom');
-var config = require('../src/util/config');
-var tutil = require('./support/testutil');
-
-// See xmpp_mockserver.js
-var mockConfig = {
- users: {
- 'alice': 'alice',
- 'bob': 'bob'
- },
- stanzas: {
- '\
- \
- \
- \
- ':
- '\
- \
- \
- - \
- \
- foo\
- bar\
- \
-
\
- \
- \
- ',
-
- '\
- \
- \
- \
- ':
- '\
- \
- \
- - \
- \
- bar\
- baz\
- \
-
\
- \
- \
- '
- }
-};
-
-describe('Session ID', function() {
-
- before(function(done) {
- tutil.startHttpServer(function() {
- tutil.mockXmppServer(mockConfig, done);
- });
- });
-
- it('should be returned on authenicated requests', function(done) {
- var options = {
- path: '/public@localhost/content/posts',
- auth: 'alice@localhost:alice'
- };
- tutil.get(options, function(res, body) {
- res.statusCode.should.equal(200);
- should.exist(res.headers['x-session-id']);
- done();
- }).on('error', done);
- });
-
- it('should also be returned when username is unqualified', function(done) {
- var options = {
- path: '/public@localhost/content/posts',
- auth: 'alice:alice'
- };
- tutil.get(options, function(res, body) {
- res.statusCode.should.equal(200);
- should.exist(res.headers['x-session-id']);
- done();
- }).on('error', done);
- });
-
- it('should not be returned on anonymous requests', function(done) {
- var options = {
- path: '/public@localhost/content/posts',
- };
- tutil.get(options, function(res) {
- res.statusCode.should.equal(200);
- should.not.exist(res.headers['x-session-id']);
- done();
- }).on('error', done);
- });
-
- it('should allow second request without re-authenication', function(done) {
- var options = {
- path: '/private@localhost/content/posts',
- auth: 'alice@localhost/http:alice'
- };
- tutil.get(options, function(res) {
- delete options.auth;
- options.headers = {'x-session-id': res.headers['x-session-id']};
- tutil.get(options, function(res2) {
- res2.statusCode.should.equal(200);
- done();
- }).on('error', done);
- }).on('error', done);
- });
-
- it('should remain the same after the first request', function(done) {
- var options = {
- path: '/private@localhost/content/posts',
- auth: 'alice@localhost/http:alice'
- };
- tutil.get(options, function(res) {
- var sessionId = res.headers['x-session-id'];
- options.headers = {'x-session-id': sessionId};
- tutil.get(options, function(res2) {
- res2.headers['x-session-id'].should.equal(sessionId);
- done();
- }).on('error', done);;
- }).on('error', done);
- });
-
- it('should differ between users', function(done) {
- var aliceOptions = {
- path: '/public@localhost/content/posts',
- auth: 'alice@localhost:alice'
- };
- tutil.get(aliceOptions, function(res) {
- var bobOptions = {
- path: '/public@localhost/content/posts',
- auth: 'bob@localhost:bob'
- };
- tutil.get(bobOptions, function(res2) {
- var aliceSessionId = res.headers['x-session-id']
- var bobSessionId = res2.headers['x-session-id'];
- aliceSessionId.should.not.equal(bobSessionId);
- done();
- }).on('error', done);;
- }).on('error', done);
- });
-
- it('should expire', function(done) {
- this.timeout(0);
- var options = {
- path: '/private@localhost/content/posts',
- auth: 'alice@localhost/http:alice'
- };
- tutil.get(options, function(res) {
- setTimeout(function() {
- delete options.auth;
- options.headers = {
- 'x-session-id': res.headers['x-session-id']
- };
- tutil.get(options, function(res2) {
- res2.statusCode.should.equal(401);
- done();
- }).on('error', done);
- }, config.sessionExpirationTime * 1000 + 100);
- }).on('error', done);
- });
-
- it('should be renewed on each request', function(done) {
- this.timeout(0);
- var options = {
- path: '/private@localhost/content/posts',
- auth: 'alice@localhost/http:alice'
- };
- tutil.get(options, function(res) {
- var sessionId = res.headers['x-session-id'];
- delete options.auth;
- options.headers = {'x-session-id': sessionId};
- setTimeout(function() {
- tutil.get(options, function(res2) {
- res2.statusCode.should.equal(200);
- res2.headers['x-session-id'].should.equal(sessionId);
- setTimeout(function() {
- tutil.get(options, function(res3) {
- res3.statusCode.should.equal(200);
- res3.headers['x-session-id'].should.equal(sessionId);
- done();
- }).on('error', done);
- }, config.sessionExpirationTime * 1000 * 0.75);
- }).on('error', done);
- }, config.sessionExpirationTime * 1000 * 0.75);
- }).on('error', done);
- });
-
- after(function() {
- tutil.end();
- });
-
-});
diff --git a/test/subscriptions.js b/test/subscriptions.js
index f06216a..e5f042a 100644
--- a/test/subscriptions.js
+++ b/test/subscriptions.js
@@ -29,6 +29,21 @@ var mockConfig = {
},
stanzas: {
// Get own subscriptions + affiliations
+ '\
+ \
+ \
+ \
+ ':
+ '\
+ \
+ \
+ \
+ \
+ \
+ \
+ ',
'\
\
\
diff --git a/test/support/xmpp_mockserver.js b/test/support/xmpp_mockserver.js
index 53b223f..f952bc1 100644
--- a/test/support/xmpp_mockserver.js
+++ b/test/support/xmpp_mockserver.js
@@ -121,6 +121,10 @@ function checkAuth(user, password, callback) {
}
function handleStanza(client, stanza) {
+ if (stanza.name == 'presence') {
+ return;
+ }
+
var action = findMatchingRule(stanza);
if (!action) {
console.error('No rule for handling stanza ' + stanza.toString());