candy-chat / candy

JavaScript-based multi-user chat client for XMPP.
http://candy-chat.github.io/candy
MIT License
1.32k stars 370 forks source link

When XHTML-IM is enabled, don’t try to parse Candy-generated messages as XHTML #446

Closed linkmauve closed 7 years ago

linkmauve commented 8 years ago

In src/view/pane/chat.js:291, onInfoMessage(), when Candy.View.getOptions().enableXHTML === true the message argument will be parsed as XHTML-IM despite having been generated by Candy itself and not being XHTML at all, e.g. in src/view/pane/roster.js:229.

Here is a full stacktrace if you are interested (language is 'fr'):

15:06:25.050 function Candy.Core.Event</a.Jabber.Presence()  - error -  Error: Syntax error, unrecognized expression: linkmauve vient d’entrer dans le salon.
Stack trace:
at.error@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:15710
mt@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:21596
kt@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:24325
at@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:10694
.find@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:21209
x.prototype.init@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:1142
x@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:225
Candy.Util</a.parseAndCropXhtml@http://my.domain.tld/candy.min.js:1:6636
Candy.View.Pane</a.Chat.onInfoMessage@http://my.domain.tld/candy.min.js:3:10377
Candy.View.Pane</a.Chat.infoMessage@http://my.domain.tld/candy.min.js:3:10202
Candy.View.Pane</a.Roster.showJoinAnimation@http://my.domain.tld/candy.min.js:5:3196
Candy.View.Pane</a.Roster.update@http://my.domain.tld/candy.min.js:5:249
Candy.View.Observer</a.Presence.update@http://my.domain.tld/candy.min.js:3:5182
x.event.dispatch@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:14077
x.event.add/v.handle@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:10849
x.event.trigger@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:13253
.triggerHandler@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:20849
Candy.Core.Event</a.Jabber.Room.Presence@http://my.domain.tld/candy.min.js:1:30968
Candy.Core.Event</a.Jabber.Presence@http://my.domain.tld/candy.min.js:1:26238
f.Handler.prototype.run@http://my.domain.tld/libs.min.js:1:15817
f.Connection.prototype._dataRecv/<@http://my.domain.tld/libs.min.js:1:22395
f.forEachChild@http://my.domain.tld/libs.min.js:1:8462
f.Connection.prototype._dataRecv@http://my.domain.tld/libs.min.js:1:22228
Strophe.Bosh.prototype._onRequestStateChange@http://my.domain.tld/libs.min.js:2:6633
EventHandlerNonNull*Strophe.Request.prototype._newXHR@http://my.domain.tld/libs.min.js:2:2105
Strophe.Request@http://my.domain.tld/libs.min.js:2:1283
Strophe.Bosh.prototype._onIdle@http://my.domain.tld/libs.min.js:2:5379
f.Connection.prototype._onIdle@http://my.domain.tld/libs.min.js:1:29423
setTimeout handler*Strophe.Bosh.prototype._send@http://my.domain.tld/libs.min.js:2:9611
f.Connection.prototype.send@http://my.domain.tld/libs.min.js:1:18903
.message@http://my.domain.tld/libs.min.js:2:18425
Candy.Core.Action</a.Jabber.Room.Message@http://my.domain.tld/candy.min.js:1:18452
Candy.View.Pane</a.Message.submit@http://my.domain.tld/candy.min.js:3:22854
x.event.dispatch@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:14077
x.event.add/v.handle@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:10849
EventListener.handleEvent*x.event.add@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:11338
.on/<@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:20275
.each@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:5345
x.prototype.each@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:4:1997
.on@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:20254
x.fn[t]@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:6:8728
Candy.View.Pane</a.Room.init@http://my.domain.tld/candy.min.js:3:27640
Candy.View.Observer</a.Presence.update@http://my.domain.tld/candy.min.js:3:5083
x.event.dispatch@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:14077
x.event.add/v.handle@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:10849
x.event.trigger@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:13253
.triggerHandler@http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js:5:20849
Candy.Core.Event</a.Jabber.Room.Presence@http://my.domain.tld/candy.min.js:1:30968
Candy.Core.Event</a.Jabber.Presence@http://my.domain.tld/candy.min.js:1:26238
f.Handler.prototype.run@http://my.domain.tld/libs.min.js:1:15817
f.Connection.prototype._dataRecv/<@http://my.domain.tld/libs.min.js:1:22395
f.forEachChild@http://my.domain.tld/libs.min.js:1:8462
f.Connection.prototype._dataRecv@http://my.domain.tld/libs.min.js:1:22228
Strophe.Bosh.prototype._onRequestStateChange@http://my.domain.tld/libs.min.js:2:6633
EventHandlerNonNull*Strophe.Request.prototype._newXHR@http://my.domain.tld/libs.min.js:2:2105
Strophe.Request@http://my.domain.tld/libs.min.js:2:1283
Strophe.Bosh.prototype._onIdle@http://my.domain.tld/libs.min.js:2:5379
f.Connection.prototype._onIdle@http://my.domain.tld/libs.min.js:1:29423
setTimeout handler*Strophe.Bosh.prototype._send@http://my.domain.tld/libs.min.js:2:9611
f.Connection.prototype.send@http://my.domain.tld/libs.min.js:1:18903
f.Connection.prototype.sendIQ@http://my.domain.tld/libs.min.js:1:19466
Candy.Core.Action</a.Jabber.GetIgnoreList@http://my.domain.tld/candy.min.js:1:17234
Candy.Core.Event</a.Strophe.Connect@http://my.domain.tld/candy.min.js:1:25280
.init/f@http://my.domain.tld/libs.min.js:2:29512
f.Connection.prototype._changeConnectStatus@http://my.domain.tld/libs.min.js:1:20706
Syntax error, unrecognized expression: linkmauve vient d’entrer dans le salon.1 libs.min.js:1:16005
f.Handler.prototype.run() libs.min.js:1
f.Connection.prototype._dataRecv/<() libs.min.js:1
f.forEachChild() libs.min.js:1
f.Connection.prototype._dataRecv() libs.min.js:1
Strophe.Bosh.prototype._onRequestStateChange() libs.min.js:2
(Async: EventHandlerNonNull) Strophe.Request.prototype._newXHR() libs.min.js:2
Strophe.Request() libs.min.js:2
Strophe.Bosh.prototype._onIdle() libs.min.js:2
f.Connection.prototype._onIdle() libs.min.js:1
(Async: setTimeout handler) Strophe.Bosh.prototype._send() libs.min.js:2
f.Connection.prototype.send() libs.min.js:1
.message() libs.min.js:2
Candy.Core.Action</a.Jabber.Room.Message() candy.min.js:1
Candy.View.Pane</a.Message.submit() candy.min.js:3
x.event.dispatch() jquery.min.js:5
x.event.add/v.handle() jquery.min.js:5
(Async: EventListener.handleEvent) x.event.add() jquery.min.js:5
.on/<() jquery.min.js:5
.each() jquery.min.js:4
x.prototype.each() jquery.min.js:4
.on() jquery.min.js:5
x.fn[t]() jquery.min.js:6
Candy.View.Pane</a.Room.init() candy.min.js:3
Candy.View.Observer</a.Presence.update() candy.min.js:3
x.event.dispatch() jquery.min.js:5
x.event.add/v.handle() jquery.min.js:5
x.event.trigger() jquery.min.js:5
.triggerHandler() jquery.min.js:5
Candy.Core.Event</a.Jabber.Room.Presence() candy.min.js:1
Candy.Core.Event</a.Jabber.Presence() candy.min.js:1
f.Handler.prototype.run() libs.min.js:1
f.Connection.prototype._dataRecv/<() libs.min.js:1
f.forEachChild() libs.min.js:1
f.Connection.prototype._dataRecv() libs.min.js:1
Strophe.Bosh.prototype._onRequestStateChange() libs.min.js:2
(Async: EventHandlerNonNull) Strophe.Request.prototype._newXHR() libs.min.js:2
Strophe.Request() libs.min.js:2
Strophe.Bosh.prototype._onIdle() libs.min.js:2
f.Connection.prototype._onIdle() libs.min.js:1
(Async: setTimeout handler) Strophe.Bosh.prototype._send() libs.min.js:2
f.Connection.prototype.send() libs.min.js:1
f.Connection.prototype.sendIQ() libs.min.js:1
Candy.Core.Action</a.Jabber.GetIgnoreList() candy.min.js:1
Candy.Core.Event</a.Strophe.Connect() candy.min.js:1
.init/f() libs.min.js:2
f.Connection.prototype._changeConnectStatus() libs.min.js:1
benlangfeld commented 8 years ago

Thank you for the report @linkmauve. Do you think you might be able to propose a fix?

sonata82 commented 8 years ago

Possible duplicate of #441?

DynamoGeek commented 8 years ago

I just traced through the code and found this same issue.

For a quick fix for my particular install, I just check to see if its a string before allowing it to be treated as an object.

var msg = str; if ( typeof str !== 'string' ) { msg = self.createHtml($(str).get(0), len) } return $("<div/>").append(msg).html();

I agree that this is likely the root cause of #441.

A hint of search candy, the following is an example of the error it'll throw in the console: Syntax error, unrecognized expression: username left the room.

AlainArachnid commented 8 years ago

Same issue for me. The @unshackleddynamo fix/workaround did the job. Thank you.

For dummies or to save time to people not Candy-aware, this is the detailed how-to: in candy.bundle.js, around line 784, modify the parseAndCropXhtml function. Replace self.parseAndCropXhtml = function(str, len) { return $("<div/>").append(self.createHtml($(str).get(0), len)).html(); }; with self.parseAndCropXhtml = function(str, len) { var msg = str; if ( typeof str !== 'string' ) { msg = self.createHtml($(str).get(0), len) } return $("<div/>").append(msg).html(); };

Then

lkraav commented 8 years ago

I'm also experiencing #441 and started testing this patch. If works, I'll file a PR.

benlangfeld commented 7 years ago

This was fixed in #492