1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
5
<meta http-equiv="content-type" content="text/html; charset=utf-8">
7
<script type="text/javascript" src="config.js"></script>
8
<script type="text/javascript" src="shared.js"></script>
9
<script type="text/javascript" src="browsercheck.js"></script>
10
<script type="text/javascript" src="sounds.js"></script>
11
<script type="text/javascript" src="statusLed.js"></script>
13
<!-- JabberConnection -->
14
<script type="text/javascript" src="jsjac.js"></script>
17
<script type="text/javascript" src="Debugger.js"></script>
19
<script type="text/javascript">
23
* JWChat, a web based jabber client
24
* Copyright (C) 2003-2008 Stefan Strigler <steve@zeank.in-berlin.de>
26
* This program is free software; you can redistribute it and/or
27
* modify it under the terms of the GNU General Public License
28
* as published by the Free Software Foundation; either version 2
29
* of the License, or (at your option) any later version.
31
* This program is distributed in the hope that it will be useful,
32
* but WITHOUT ANY WARRANTY; without even the implied warranty of
33
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
* GNU General Public License for more details.
36
* You should have received a copy of the GNU General Public License
37
* along with this program; if not, write to the Free Software
38
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40
* Please visit http://jwchat.sourceforge.net for more information!
43
/************************************************************************
44
* ****** GLOBAL WARS(tm) *******
45
************************************************************************
49
var register = false; // whether to register new account
57
var autoPopupAway = false;
58
var playSounds = true;
59
var focusWindows = true;
60
var timestamps = false;
61
var usersHidden = false;
62
var enableLog = false;
67
var fmd; // frames.main.document
68
var disco; // holds information from service discovery
73
var onlstatus = new Object();
74
onlstatus["available"] = "conectado";
75
onlstatus["chat"] = "disponible para charlar";
76
onlstatus["away"] = "ausente";
77
onlstatus["xa"] = "no disponible";
78
onlstatus["dnd"] = "no molestar";
79
onlstatus["invisible"] = "invisible";
80
onlstatus["unavailable"] = "desconectado";
83
/************************************************************************
84
* ****** Pop-Up's *******
85
************************************************************************
88
function openGroupchat(aJid,nick,pass) {
92
var user = roster.getUserByJID(aJid);
95
user = roster.addUser(new RosterUser(aJid,'',["Salas de charla"],aJid.substring(0,aJid.indexOf('@'))));
96
user.type = 'groupchat';
99
} catch(e) { Debug.log(e.message, 1); }
100
if (!user.chatW || user.chatW.closed)
101
user.chatW = open("groupchat.html?jid="+escape(aJid)+"&nick="+escape(nick)+"&pass="+escape(pass),"gchatW"+makeWindowName(aJid+"/"+nick),"width=520,height=390,resizable=yes");
106
function openSubscription(aJid) {
107
var param = (aJid) ? "?jid="+escape(aJid) : "";
108
subw = open("subscription.html"+param,"sub","width=320,height=240,resizable=yes");
113
function openCustomPresence(aJid) {
114
var user = roster.getUserByJID(aJid);
117
if (!user.onlStatW || user.onlStatW.closed)
118
user.onlStatW = open("changestatus.html?jid="+escape(aJid),"onlStatW","width=330,height=240,resizable=yes");
119
user.onlStatW.focus();
123
function sendCustomPresence(aJid,presence,msg) {
124
var oPresence = new JSJaCPresence();
125
oPresence.setTo(aJid);
126
if (roster.getUserByJID(aJid).roster)
127
oPresence.setXMLNS();
131
oPresence.setType('unavailable');
133
oPresence.setType('unavailable');
134
presence = "invisible";
136
if (presence != 'available')
137
oPresence.setShow(presence);
140
if (typeof(msg) != 'undefined' && msg != '')
141
oPresence.setStatus(msg);
143
Debug.log(oPresence.xml(),2);
147
function openUserProps(aJid) {
148
open("userprops.html?jid="+escape(aJid),"uProps"+makeWindowName(aJid),"width=480,height=360,resizable=yes");
152
function removeUser(aJid) {
154
var fulljid = roster.getUserByJID(aJid).fulljid;
156
var iq = new JSJaCIQ();
158
var query = iq.setQuery('jabber:iq:roster');
159
var item = query.appendChild(iq.getDoc().createElement('item'));
160
item.setAttribute('jid',fulljid);
161
item.setAttribute('subscription','remove');
166
var vcardW; // my vcardW;
167
function openUserInfo(aJid) {
168
var newin = open("vcard.html?jid="+escape(aJid),"vcardW"+makeWindowName(aJid),"width=400,height=580,scrollbars=yes");
170
if (cutResource(aJid) == cutResource(jid))
173
var user = roster.getUserByJID(cutResource(aJid));
175
user = new RosterUser(aJid);
176
roster.addUser(user);
178
if (user.roster) // groupchat(!)
179
user = user.roster.getUserByJID(aJid);
186
function openUserHistory(aJid) {
188
if (typeof(loghost) == 'undefined' || loghost == '')
191
var user = roster.getUserByJID(aJid);
196
if (!user.histW || user.histW.closed)
197
user.histW = open("userhist.html?jid="+escape(aJid),"histW"+makeWindowName(aJid),"width=600,height=400,resizable=yes,scrollbars=no");
201
function openUserNote(aJid) { /* store annotations to a user */
202
var user = roster.getUserByJID(aJid);
205
return; // unbelievable
207
if (!user.noteW || user.noteW.closed)
208
user.noteW = open("usernote.html?jid="+escape(aJid),"noteW"+makeWindowName(aJid),"width=300,height=200,resizable=yes,scrollbars=no");
213
function openSearch() {
214
if (!searchW || searchW.closed)
215
searchW = open("search.html","searchW"+makeWindowName(jid),"width=480,height=260,resizable=yes,scrollbars=yes");
221
function openEditBookmarks() {
222
if (!ebW || ebW.closed)
223
ebW = open("editbookmarks.html","ebw"+makeWindowName(jid),"width=330,height=290,resizable=yes");
228
/************************************************************************
229
* nifty helpers - always there if you need 'em
230
************************************************************************
233
/* command line history */
234
var messageHistory = new Array();
235
var historyIndex = 0;
236
function getHistory(key, message) {
237
if ((key == "up") && (historyIndex > 0)) historyIndex--;
238
if ((key == "down") && (historyIndex < messageHistory.length)) historyIndex++;
239
if (historyIndex >= messageHistory.length) {
240
if (historyIndex == messageHistory.length) return '';
243
return messageHistory[historyIndex];
247
function addtoHistory(message) {
249
messageHistory = messageHistory.concat(message);
251
messageHistory.push(message);
252
historyIndex = messageHistory.length;
256
var soundPlaying = false;
257
function soundLoaded() {
258
soundPlaying = false;
261
function playSound(action) {
265
if(!SOUNDS[action]) {
266
Debug.log("no sound for '" + action + "'",1);
270
if (onlstat != '' && onlstat != 'available' && onlstat != 'chat')
278
var frameD = frames["jwc_sound"].document;
280
var html = "<embed src=\""+SOUNDS[action]+"\" width=\"1\" height=\"1\" quality=\"high\" pluginspage=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\" type=\"application/x-shockwave-flash\">";
287
function isGateway(aJid) {
288
aJid = cutResource(aJid);
289
for (var i in disco) {
290
if (!disco[i].getNode) continue;
292
if (disco[i].getNode().getElementsByTagName('identity').item(0)) {
293
if (disco[i].getNode().getElementsByTagName('identity').item(0).getAttribute('category') == 'gateway')
300
/************************************************************************
301
* ****** CHANGESTATUS *******
302
************************************************************************
305
function sendPresence2Groupchats(gc,val,away) {
307
for (var i=0; i<gc.length; i++) {
308
aPresence = new JSJaCPresence();
309
//aPresence.setXMLNS();
310
aPresence.setTo(gc[i]);
311
if (away && away != '')
312
aPresence.setStatus(away);
313
if (val != 'available')
314
aPresence.setShow(val);
319
function changeStatus(val,away,prio) {
321
Debug.log("changeStatus: "+val+","+away+","+prio, 2);
327
if (prio && !isNaN(prio))
330
if (!con.connected() && val != 'offline') {
335
var aPresence = new JSJaCPresence();
340
aPresence.setType('invisible');
344
aPresence.setType('unavailable');
347
var img = eval(val+"Led");
348
statusLed.src = img.src;
350
statusMsg.value = away;
352
statusMsg.value = onlstatus[val];
357
val = 'available'; // needed for led in status bar
359
aPresence.setStatus(away);
360
if (prio && !isNaN(prio))
361
aPresence.setPriority(prio);
363
aPresence.setPriority(onlprio);
366
if (prio && !isNaN(prio))
367
aPresence.setPriority(prio);
369
aPresence.setPriority(onlprio);
372
aPresence.setStatus(away);
374
if (prio && !isNaN(prio))
375
aPresence.setPriority(prio);
377
aPresence.setPriority('0');
379
aPresence.setShow(val);
384
/* send presence to chatrooms
386
if (typeof(roster) != 'undefined' && onlstat != 'invisible') {
387
sendPresence2Groupchats(roster.getGroupchats(),onlstat,onlmsg);
390
var img = eval(val+"Led");
391
statusLed.src = img.src;
393
statusMsg.value = away;
395
statusMsg.value = onlstatus[val];
398
/************************************************************************
399
* ***** EVENT - HANDLER *****
400
************************************************************************
404
/************************************************************************
406
************************************************************************
408
function handleMessage(oMsg) {
410
Debug.log(oMsg.xml(),2);
412
if (oMsg.getType() == 'error')
415
/* check if this is a groupchat invite */
416
var x = oMsg.getChild('x','http://jabber.org/protocol/muc#user');
419
var from, to, reason, pass;
421
var aInvite = x.getElementsByTagName('invite').item(0);
422
from = aInvite.getAttribute('from');
423
if (aInvite.firstChild && aInvite.firstChild.nodeName == 'reason' && aInvite.firstChild.firstChild)
424
reason = aInvite.firstChild.firstChild.nodeValue;
425
if (x.getElementsByTagName('password').item(0))
426
pass = x.getElementsByTagName('password').item(0).firstChild.nodeValue;
427
Debug.log("You have been invited to " + jid + " pass " + pass + " by " + from + "\nreason:" + reason,2);
428
var user = roster.getUserByJID(cutResource(from));
429
if (!user) {// users not in roster (yet)
430
Debug.log("creating new user "+from,3);
431
user = roster.addUser(new RosterUser(cutResource(from)));
432
user.lastsrc = eval(user.status + "Led").src;
436
if (typeof(user.iwArr) == 'undefined')
437
user.iwArr = new Array();
439
user.iwArr[to] = open("groupchat_invite.html?to="+escape(to)+"&from="+escape(from)+"&pass="+escape(pass)+"&reason="+escape(reason),"iw"+makeWindowName(to),"width=320,height=320,resizable=yes");
444
var from = cutResource(oMsg.getFrom());
445
var type = oMsg.getType();
446
Debug.log("from: "+from+"\noMsg.getFrom(): "+oMsg.getFrom(),3);
448
var user = roster.getUserByJID(from);
449
if (user == null) {// users not in roster (yet)
450
Debug.log("creating new user "+from,3);
451
user = roster.addUser(new RosterUser(from));
452
user.lastsrc = eval(user.status + "Led").src;
456
Debug.log("got user jid: "+user.jid,3);
458
var aRoster = roster;
459
if (type != 'groupchat' && user.roster && from != oMsg.getFrom()) { // private groupchat message
460
aRoster = user.roster;
461
from = oMsg.getFrom(); // use from with resource (had been cut off first)
462
user = user.roster.getUserByJID(from);
465
/* change icon in roster - but not if it's a groupchat item */
466
if (type != 'groupchat') {
468
user.lastsrc = eval(user.status + "Led").src;
470
var images = aRoster.getUserIcons(from);
471
for (var i=0; i<images.length; i++)
472
images[i].src = messageImg.src;
474
/* user is not visible right now - make him pop up (lastsrc changed!) */
475
if (aRoster.usersHidden && user.status == 'unavailable')
479
// set current timestamp
481
for (var i=0; i<oMsg.getNode().getElementsByTagName('x').length; i++)
482
if (oMsg.getNode().getElementsByTagName('x').item(i).getAttribute('xmlns') == 'jabber:x:delay') {
483
x = oMsg.getNode().getElementsByTagName('x').item(i);
488
Debug.log("found offline message: "+x.getAttribute('stamp'),3);
489
var stamp = x.getAttribute('stamp');
490
oMsg.jwcTimestamp = new Date(Date.UTC(stamp.substring(0,4),stamp.substring(4,6)-1,stamp.substring(6,8),stamp.substring(9,11),stamp.substring(12,14),stamp.substring(15,17)));
492
oMsg.jwcTimestamp = new Date();
494
if (type == 'chat') {
496
user.chatmsgs = user.chatmsgs.concat(oMsg);
498
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs) {
499
user.chatW.popMsgs();
500
playSound('chat_recv');
501
} else if (autoPopup && (autoPopupAway || onlstat == "available" || onlstat == "chat")) {
502
aRoster.openChat(from);
503
playSound('chat_recv');
505
if (focusWindows) window.focus();
506
playSound('chat_queue');
508
// let arrow blink for toggled groups
509
for (var i=0; i<user.groups.length; i++) {
510
if (user.groups[i] != '') {
511
if (roster.hiddenGroups[user.groups[i]])
512
fmd.images[user.groups[i]+"Img"].src = arrow_right_blinking.src;
517
} else if (type == 'groupchat') {
519
/* handle groupchat message
522
user.chatmsgs = user.chatmsgs.concat(oMsg);
523
if (user.chatW && !user.chatW.closed && user.chatW.srcW && typeof(user.chatW.srcW.roster) != 'undefined' && user.chatW.popMsgs) {
524
user.chatW.popMsgs();
527
playSound('chat_recv');
530
if (oMsg.getBody() == '') // don't show empty messages like PEP message or stuff
532
user.messages = user.messages.concat(oMsg);
533
if (autoPopup && (autoPopupAway || onlstat == "available" || onlstat == "chat") && (!user.mW || user.mW.closed)) {
534
aRoster.openMessage(from);
535
playSound('message_recv');
536
} else if (user.mW && !user.mW.closed && user.messages.length > 0 && user.mW.document.forms[0]) {
537
user.mW.document.forms[0].nextButton.disabled = false;
538
if (focusWindows) user.mW.focus();
539
playSound('message_recv');
541
if (focusWindows) window.focus();
542
playSound('message_queue');
543
// let arrow blink for toggled groups
544
for (var i=0; i<user.groups.length; i++) {
545
if (user.groups[i] != '') {
546
if (roster.hiddenGroups[user.groups[i]])
547
fmd.images[user.groups[i]+"Img"].src = arrow_right_blinking.src;
553
// [TODO] zeank 2005-10-26
554
// archiving of single/plain messages
558
/************************************************************************
560
************************************************************************
562
var error_messages = new Array();
564
function handleMessageError(oMsg) {
566
if (oMsg.getType() != 'error')
569
Debug.log(oMsg.xml(),2);
571
var user = roster.getUserByJID(cutResource(oMsg.getFrom()));
573
if (user.chatW && !user.chatW.closed && user.chatW.putMsgHTML) {
574
var error = oMsg.getNode().getElementsByTagName('error').item(0);
576
if (error.getElementsByTagName('text').item(0)) {
577
user.chatW.putMsgHTML(oMsg);
584
error_messages = error_messages.concat(oMsg);
586
if (!errorW || errorW.closed)
587
errorW = open("error_message.html","errorW"+makeWindowName(jid),"width=360,height=270,dependent=yes,resizable=yes");
588
else if (error_messages.length > 0 && errorW.document.forms[0])
589
errorW.document.forms[0].nextButton.disabled = false;
596
/************************************************************************
598
************************************************************************
601
function handlePresence(presence) {
602
Debug.log(presence.xml(),2);
604
var from = cutResource(presence.getFrom());
605
var type = presence.getType();
606
var show = presence.getShow();
607
var status = presence.getStatus();
609
var aRoster = roster;
611
// roster subscriptions synchronisation
613
if (isGateway(from.substring(from.indexOf('@')+1))) {
615
if (presence.getChild('x', 'http://jabber.org/protocol/roster-subsync'))
616
x = presence.getChild('x', 'http://jabber.org/protocol/roster-subsync');
617
else if (presence.getChild('x', 'http://delx.cjb.net/protocol/roster-subsync'))
618
x = presence.getChild('x', 'http://delx.cjb.net/protocol/roster-subsync');
622
Debug.log("detected roster-subsync presence",2);
624
var items = x.getElementsByTagName("item");
625
for (var i=0; i<items.length; i++) {
626
var aItem = items.item(i);
627
if (type == 'subscribe' && aItem.getAttribute("subscription") == 'both') {
628
// insert into roster
629
var aIQ = new JSJaCIQ();
631
var query = aIQ.setQuery('jabber:iq:roster');
632
var bItem = query.appendChild(aIQ.getDoc().createElement('item'));
633
bItem.setAttribute('jid',from);
634
if (aItem.getAttribute('name') && aItem.getAttribute('name') != '')
635
bItem.setAttribute('name',aItem.getAttribute('name'));
637
bItem.setAttribute('name',from.substring(0,from.lastIndexOf('@')).replace(/%/,'@'));
638
var itemGroups = aItem.getElementsByTagName("group");
639
for (var j=0; j<itemGroups.length; j++)
640
bItem.appendChild(itemGroups.item(j));
642
Debug.log("roster-subsync setting roster:"+aIQ.xml(),2);
646
// Approve Subscription Request
647
var aPresence = new JSJaCPresence();
648
aPresence.setTo(from);
649
aPresence.setType('subscribed');
652
// Subscribe to gateway contact's presence
653
var bPresence = new JSJaCPresence();
654
bPresence.setTo(from);
655
bPresence.setType('subscribe');
668
if (isGateway(from)) { // automatically subscribe gateways
670
// Approve Subscription Request
671
var aPresence = new JSJaCPresence();
672
aPresence.setTo(presence.getFrom());
673
aPresence.setType('subscribed');
676
// Subscribe to Gateway's Presence
677
var bPresence = new JSJaCPresence();
678
bPresence.setTo(presence.getFrom());
679
bPresence.setType('subscribe');
683
window.open("subscriptionRequest.html?jid="+escape(from)+"&msg="+escape(status),"sr"+makeWindowName(from),"width=320,height=240");
685
window.open("subscriptionRequest.html?jid="+escape(from),"sr"+makeWindowName(from),"width=320,height=240");
689
if (!isGateway(from))
690
alert(""+presence.getFrom()+" te ha eliminado de su lista"); /* [TODO] don't use alert here */
693
var user = roster.getUserByJID(from);
694
if (user && user.chatW && !user.chatW.closed && user.chatW.putMsgHTML) {
695
if (presence.getNode().getElementsByTagName('error').item(0)) {
696
var error = presence.getNode().getElementsByTagName('error').item(0);
697
if (error.getElementsByTagName('text').item(0))
698
user.chatW.putMsgHTML(presence);
699
else if (error.firstChild && error.firstChild.nodeValue)
700
user.chatW.putMsgHTML(error.firstChild.nodeValue,new Date(),from,null,true);
706
var user = roster.getUserByJID(from);
707
if (!user) { // presence from unsubscribed user
708
Debug.log("presence from "+from+" not found on roster", 2);
712
/* handle presence for MUC */
714
for (var i=0; i<presence.getNode().getElementsByTagName('x').length; i++)
715
if (presence.getNode().getElementsByTagName('x').item(i).getAttribute('xmlns') == 'http://jabber.org/protocol/muc#user') {
716
x = presence.getNode().getElementsByTagName('x').item(i);
720
if (user.roster && x) {
721
Debug.log("muc presence detected", 2);
722
var ofrom = presence.getFrom().substring(presence.getFrom().indexOf('/')+1);
724
Debug.log("jabber.from:"+presence.getFrom()+", ofrom:"+ofrom,3);
726
var ouser = user.roster.getUserByJID(presence.getFrom());
727
if (!ouser) // no user? create one!
728
ouser = new GroupchatRosterUser(presence.getFrom(),ofrom);
730
var item = x.getElementsByTagName('item').item(0);
732
ouser.affiliation = item.getAttribute('affiliation');
733
ouser.role = item.getAttribute('role');
734
ouser.nick = item.getAttribute('nick');
735
ouser.realjid = item.getAttribute('jid');
736
if (item.getElementsByTagName('reason').item(0))
737
ouser.reason = item.getElementsByTagName('reason').item(0).firstChild.nodeValue;
738
if (actor = item.getElementsByTagName('actor').item(0)) {
739
if (actor.getAttribute('jid') != null)
740
ouser.actor = actor.getAttribute('jid');
741
else if (item.getElementsByTagName('actor').item(0).firstChild != null)
742
ouser.actor = item.getElementsByTagName('actor').item(0).firstChild.nodeValue;
744
if (ouser.role != '') {
745
ouser.add2Group(ouser.role+'s');
747
/* check if it is our own presence
748
* must be done here cause we want to be sure that role != ''
751
if (ouser.name == htmlEnc(user.roster.nick)) { // seems to be me
752
user.roster.me = ouser; // store this reference
753
if (user.chatW.updateMe)
754
user.chatW.updateMe();
758
Debug.log("ouser.jid: "+ ouser.jid + ", ouser.fulljid:" + ouser.fulljid + ", ouser.name:"+ouser.name+", user.roster.nick:"+user.roster.nick,3);
761
var nickChanged = false;
762
if (x.getElementsByTagName('status').item(0)) {
763
var code = x.getElementsByTagName('status').item(0).getAttribute('code');
765
case '201': // room created
766
/* popup dialog to ask for whether to accept default
767
* configuration or make a custom room
769
if (confirm("Una nueva sala ha sido creada pero debe ser configurada. ¿Quiere crear una configuración personalizada ahora?\nNota: Pulsa 'Cancel' para iniciar con una configuración por defecto."))
770
user.chatW.openConfig();
772
var iq = new JSJaCIQ();
775
var query = iq.setQuery('http://jabber.org/protocol/muc#owner');
777
iq.buildNode('x', {'xmlns': NS_XDATA, 'type': 'submit'}));
782
case '303': // nick change
787
var oMsg = new JSJaCMessage();
788
oMsg.setFrom(user.jid);
789
oMsg.setBody(""+ouser.name+" ahora es "+htmlEnc(ouser.nick));
790
user.chatmsgs = user.chatmsgs.concat(oMsg);
791
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs)
792
user.chatW.popMsgs();
794
// update nick if it's me
795
if (ouser.name == htmlEnc(user.roster.nick))
796
user.roster.nick = ouser.nick;
799
var aChatW = ouser.chatW;
800
user.roster.removeUser(ouser);
803
ouser = new GroupchatRosterUser(presence.getFrom().substring(0,presence.getFrom().lastIndexOf('/')+1).concat(ouser.nick),ouser.nick);
805
if (aChatW && !aChatW.closed) {
806
ouser.chatW = aChatW;
807
ouser.chatW.user = ouser;
809
user.roster.addUser(ouser);
812
case '301': // user has been kicked
813
var oMsg = new JSJaCMessage();
814
oMsg.setFrom(user.jid);
817
body = ""+ouser.name+" ha sido bloqueado por "+ouser.actor;
819
body = ""+ouser.name+" ha sido bloqueado";
821
body += ": " + ouser.reason;
823
user.chatmsgs = user.chatmsgs.concat(oMsg);
824
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs)
825
user.chatW.popMsgs();
827
playSound('chat_recv');
829
case '307': // user has been kicked
830
var oMsg = new JSJaCMessage();
831
oMsg.setFrom(user.jid);
834
body = ""+ouser.name+" ha sido expulsado por "+ouser.actor;
836
body = ""+ouser.name+" ha sido expulsado";
838
body += ": " + ouser.reason;
840
user.chatmsgs = user.chatmsgs.concat(oMsg);
841
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs)
842
user.chatW.popMsgs();
844
playSound('chat_recv');
849
Debug.log("<"+ouser.name+"> affiliation:"+ouser.affiliation+", role:"+ouser.role,3);
851
if (!user.roster.getUserByJID(presence.getFrom()) && !nickChanged) {
853
user.roster.addUser(ouser);
856
var oMsg = new JSJaCMessage();
857
oMsg.setFrom(user.jid);
858
oMsg.setBody(""+ouser.name+" está ahora disponible");
859
user.chatmsgs = user.chatmsgs.concat(oMsg);
860
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs)
861
user.chatW.popMsgs();
865
} else if (presence.getType() == 'unavailable' && !nickChanged) {
867
var oMsg = new JSJaCMessage();
868
oMsg.setFrom(user.jid);
869
var body = ""+ouser.name+" se ha ido";
870
if (presence.getStatus())
871
body += ": " + presence.getStatus();
873
user.chatmsgs = user.chatmsgs.concat(oMsg);
874
if (user.chatW && !user.chatW.closed && user.chatW.popMsgs)
875
user.chatW.popMsgs();
877
playSound('offline');
880
user.roster.updateGroups();
882
// relink roster and user
883
aRoster = user.roster;
888
if (user.status == 'unavailable')
890
// fix broken pressenc status
891
if (show != 'chat' && show != 'away' && show != 'xa' && show != 'dnd')
895
if (type == 'unsubscribe') {
896
user.subscription = 'from';
897
user.status = 'stalker';
898
} else if (user.status != 'stalker')
899
user.status = 'unavailable';
900
if (aRoster.name == 'GroupchatRoster' && !nickChanged) { // it's a groupchat roster
902
if (!user.chatW || user.chatW.closed)
903
aRoster.removeUser(user); // we don't need offline users in there
905
playSound('offline');
907
if (user.status == 'unavailable') // user was offline before
909
user.status = 'available';
912
var img = eval(user.status+"Led");
914
if (user.lastsrc) // message is pending
915
user.lastsrc = img.src;
919
user.statusMsg = status;
921
user.statusMsg = null;
923
// update presence indicator of chat window
924
if (user.chatW && !user.chatW.closed && user.chatW.updateUserPresence)
925
user.chatW.updateUserPresence();
927
aRoster.print(); // update roster
930
/************************************************************************
932
************************************************************************
935
function handleIQSet(iq) {
936
if (iq.getType() != "set") {
937
Debug.log("not handling iq:\n"+iq.xml(),3);
941
Debug.log("got iq type 'set':\n"+iq.xml(),2);
943
if (iq.getQueryXMLNS() != 'jabber:iq:roster') { // only handle roster items so far
944
Debug.log("not handling iq:\n"+iq.xml(),1);
948
for (var i=0; i<iq.getQuery().childNodes.length; i++) {
949
var item = iq.getQuery().childNodes.item(i);
950
var user = roster.getUserByJID(cutResource(item.getAttribute('jid')));
952
user.subscription = item.getAttribute('subscription');
953
if (item.getAttribute('subscription') == 'remove') {
954
Debug.log("removing user " + user.jid,2);
955
roster.removeUser(user);
956
} else { // update user
957
user.name = item.getAttribute('name')? htmlEnc(item.getAttribute('name')) : item.getAttribute('jid');
958
user.groups = new Array('');
959
for (var j=0; j<item.childNodes.length; j++)
960
if (item.childNodes.item(j).nodeName == 'group')
961
user.groups = user.groups.concat(item.childNodes.item(j).firstChild.nodeValue);
962
roster.updateGroups();
964
} else {// got a new user
965
if (isGateway(item.getAttribute('jid'))) { // auto add gateways
967
var name = cutResource(item.getAttribute('jid'));
968
for (var i in disco) {
969
if (typeof(disco[i]) != 'object') continue;
970
if (i == cutResource(item.getAttribute('jid')))
971
name = disco[i].getQuery().getElementsByTagName('identity').item(0).getAttribute('name');
975
var aUser = new RosterUser(cutResource(item.getAttribute('jid')),item.getAttribute('subscription'),["Gateways"],name);
976
//aUser.fulljid = item.getAttribute('jid');
977
roster.addUser(aUser);
979
// set name and group
980
var aIQ = new JSJaCIQ();
982
var query = aIQ.setQuery('jabber:iq:roster');
983
var aItem = query.appendChild(aIQ.getDoc().createElement('item'));
984
aItem.setAttribute('jid',item.getAttribute('jid'));
985
aItem.setAttribute('name',name);
986
aItem.appendChild(iq.getDoc().createElement('group')).appendChild(iq.getDoc().createTextNode('Gateways'));
989
} else { // new but not a gateway
990
var name = item.getAttribute('name')? item.getAttribute('name') : item.getAttribute('jid');
991
if (name.indexOf('@') != -1)
992
name = name.substring(0,name.indexOf('@'));
994
item.setAttribute('name',name);
995
var groups = new Array('');
996
for (var j=0; j<item.childNodes.length; j++)
997
if (item.childNodes.item(j).nodeName == 'group')
998
groups = groups.concat(item.childNodes.item(j).firstChild.nodeValue);
1000
roster.addUser(new RosterUser(cutResource(item.getAttribute('jid')),item.getAttribute('subscription'),groups,name));
1002
var aIQ = new JSJaCIQ();
1004
var query = aIQ.setQuery('jabber:iq:roster');
1006
var aItem = item.cloneNode(true);
1007
aItem.removeAttribute('subscription');
1008
query.appendChild(aItem);
1010
con.send(aIQ); // set stripped name
1012
if (item.getAttribute('subscription') == "from" && item.getAttribute('ask') != 'subscribe')
1013
openSubscription(item.getAttribute('jid')); // subscribe to user
1020
function handleConError(e) {
1021
switch (e.getAttribute('code')) {
1023
alert("Autorizació fallida");
1024
if (!con.connected())
1028
alert("¡Registro fallido!\n\nPor favor escoge un nombre de usuario distinto");
1031
alert("Servicio no disponible");
1034
if (!con.connected() && !logoutCalled && onlstat != 'offline')
1035
if (confirm("Error interno del servidor.\n\nDesconectado.\n\n¿Deseas reconectar?"))
1036
changeStatus(onlstat,onlmsg);
1039
alert("An Error Occured:\nCode: "+e.getAttribute('code')+"\nType: "+e.getAttribute('type')+"\nCondition: "+e.firstChild.nodeName); // this shouldn't happen :)
1044
function handleDisconnect() {
1045
if (logoutCalled || onlstat == 'offline')
1048
// disconnecting not with onunload handler triggered
1049
statusLed.src = unavailableLed.src; // offline icon
1050
statusMsg.value = '';
1052
fmd.getElementById('roster').innerHTML = '';
1054
// if (confirm("Desconectado\n\n¿Deseas reconectar?"))
1055
// changeStatus(onlstat,onlmsg);
1058
function handleConnected() {
1060
Debug.log("Connected",0);
1062
if (register && opener && opener.document.forms[0] && opener.document.forms[0].register)
1063
opener.document.forms[0].register.checked = false;
1065
/* get/setup roster */
1067
iq.setIQ(null,'get','roster_1');
1068
iq.setQuery('jabber:iq:roster');
1069
con.send(iq,getRoster); // cascading information retrieval
1072
/* *** cascading onconnect handlers *** */
1073
function getRoster(iq) {
1074
if (!iq || iq.getType() != 'result') {
1076
Debug.log("Error fetching roster:\n"+iq.xml(),1);
1078
Debug.log("Error fetching roster",1);
1082
Debug.log("got roster:\n"+iq.xml(),2);
1084
roster = new Roster(iq.getQuery().childNodes,fmd);
1085
roster.usersHidden = usersHidden;
1086
roster.nick = jid.substring(0,jid.indexOf('@')); // remember nick for 1:1 Chats
1090
iq.setIQ(null,'get','jwchat_state');
1091
var query = iq.setQuery('jabber:iq:private');
1093
iq.buildNode('jwchat', {'xmlns': 'jwchat:state'}));
1095
con.send(iq,getSavedState);
1098
function getSavedState(iq) {
1099
if (!iq || iq.getType() != 'result') {
1101
Debug.log("Error retrieving saved state:\n"+iq.xml(),1);
1103
Debug.log("Error retrieving saved state",1);
1106
Debug.log(iq.xml(), 2);
1107
var jNode = iq.getNode().getElementsByTagName('jwchat').item(0);
1108
for (var i=0; i<jNode.childNodes.length; i++) {
1109
var item = jNode.childNodes.item(i);
1111
switch (item.nodeName) {
1113
if (onlstat == '' && item.firstChild.nodeValue != 'offline')
1114
onlstat = item.firstChild.nodeValue;
1117
onlmsg = item.firstChild.nodeValue;
1119
case 'hiddenGroups':
1120
var hiddenGroups = item.firstChild.nodeValue.split(',');
1121
for (var j=0; j<hiddenGroups.length; j++)
1122
if (hiddenGroups[j] != '')
1123
roster.hiddenGroups[hiddenGroups[j]] = true;
1125
} catch(e) { Debug.log(e.toString(), 1); }
1131
iq.setIQ(null,'get','jwchat_prefs');
1132
var query = iq.setQuery('jabber:iq:private');
1134
iq.buildNode('jwchat', {'xmlns': 'jwchat:prefs'}));
1136
con.send(iq,getPrefs);
1139
function getPrefs(iq) {
1140
if (!iq || iq.getType() != 'result')
1142
Debug.log("Error retrieving preferences:\n"+iq.xml(), 1);
1144
Debug.log("Error retrieving preferences",1);
1146
if (iq && iq.getType() == 'result') {
1147
Debug.log(iq.xml() ,2);
1148
if (iq.getNode().getElementsByTagName('jwchat').item(0)) {
1149
var jNode = iq.getNode().getElementsByTagName('jwchat').item(0);
1150
for (var i=0; i<jNode.childNodes.length; i++) {
1152
switch (jNode.childNodes.item(i).nodeName) {
1154
if (eval(jNode.childNodes.item(i).firstChild.nodeValue) != usersHidden)
1155
roster.toggleHide();
1158
timerval = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1159
con.setPollInterval(timerval);
1162
autoPopup = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1164
case 'autoPopupAway':
1165
autoPopupAway = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1168
playSounds = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1170
case 'focusWindows':
1171
focusWindows = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1174
timestamps = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1177
enableLog = eval(jNode.childNodes.item(i).firstChild.nodeValue);
1180
} catch(e) { Debug.log(e.toString(),1); }
1189
onlprio = opener.prio;
1191
onlprio = DEFAULTPRIORITY;
1195
onlstat = 'available';
1196
changeStatus(onlstat,onlmsg,onlprio);
1198
playSound('connected');
1200
// Start Service Discovery
1202
iq.setIQ(con.domain,'get','disco_item_1');
1203
iq.setQuery('http://jabber.org/protocol/disco#items');
1205
con.send(iq,getDiscoItems);
1209
iq.setIQ(null,'get','storage_bookmarks');
1210
var query = iq.setQuery('jabber:iq:private');
1212
iq.buildNode('storage', {'xmlns': 'storage:bookmarks'}));
1214
con.send(iq,getBookmarks);
1218
iq.setIQ(null,'get','jwchat_notes');
1219
var query = iq.setQuery('jabber:iq:private');
1221
iq.buildNode('storage', {'xmlns': 'storage:rosternotes'}));
1223
con.send(iq,getAnnotations);
1226
function getDiscoItems(iq) {
1230
Debug.log(iq.xml(),2);
1232
disco = new Object();
1234
var items = iq.getNode().firstChild.childNodes;
1237
for (var i=0; i<items.length; i++) {
1238
if (items[i].nodeName != 'item' || !items[i].getAttribute('jid') || items[i].getAttribute('node')!=null) // skip those
1240
var aIQ = new JSJaCIQ();
1241
aIQ.setIQ(items[i].getAttribute('jid'),'get','disco_info_'+i);
1242
aIQ.setQuery("http://jabber.org/protocol/disco#info");
1244
con.send(aIQ,getDiscoInfo);
1248
function getDiscoInfo(iq) {
1249
if (!iq || iq.getType() != 'result')
1252
Debug.log(iq.xml(),2);
1253
if (iq.getType() == 'result') {
1254
disco[iq.getFrom()] = iq;
1256
// If the identity does not have a name, set the name to jid
1257
if(iq.getNode().getElementsByTagName('identity').item(0).getAttribute('name') == null)
1258
iq.getNode().getElementsByTagName('identity').item(0).setAttribute('name', iq.getFrom());
1261
if (iq.getNode().getElementsByTagName('identity').item(0)) {
1262
if (iq.getNode().getElementsByTagName('identity').item(0).getAttribute('type') == 'archive') {
1263
for (var j=0; j<iq.getNode().getElementsByTagName('feature').length; j++) {
1264
if (iq.getNode().getElementsByTagName('feature').item(j).getAttribute('var') == 'http://jabber.org/protocol/archive') {
1265
loghost = iq.getFrom();
1275
function getBookmarks(iq) {
1276
if (!iq || iq.getType() != 'result')
1279
Debug.log(iq.xml(),2);
1281
bookmarks = new Array();
1283
if (iq.getNode().getElementsByTagName('storage').item(0)) {
1284
var jNode = iq.getNode().getElementsByTagName('storage').item(0);
1285
for (var i=0; i<jNode.childNodes.length; i++) {
1286
var item = jNode.childNodes.item(i);
1287
if (item.nodeName == 'conference') {
1288
var bookmark = new Object();
1289
bookmark.jid = item.getAttribute('jid');
1290
bookmark.name = item.getAttribute('name');
1291
if (item.getAttribute('autojoin') == '1')
1292
bookmark.autojoin = '1';
1293
if (item.getElementsByTagName('nick').item(0))
1294
bookmark.nick = item.getElementsByTagName('nick').item(0).firstChild.nodeValue;
1295
if (item.getElementsByTagName('pass').item(0))
1296
bookmark.pass = item.getElementsByTagName('pass').item(0).firstChild.nodeValue;
1297
bookmarks[bookmarks.length] = bookmark;
1298
if (bookmark.autojoin == '1') {
1299
openGroupchat(bookmark.jid, bookmark.nick, bookmark.pass);
1307
function getAnnotations(iq) {
1308
if (!iq || iq.getType() != 'result')
1311
Debug.log(iq.xml(),2);
1313
annotations = new Object();
1315
if (iq.getType() == 'result') {
1316
if (iq.getNode().getElementsByTagName('storage').item(0)) {
1317
var jNode = iq.getNode().getElementsByTagName('storage').item(0);
1318
for (var i=0; i<jNode.childNodes.length; i++)
1319
if (jNode.childNodes.item(i).nodeName == 'note' && jNode.childNodes.item(i).firstChild)
1320
annotations[jNode.childNodes.item(i).getAttribute('jid')] = jNode.childNodes.item(i).firstChild.nodeValue;
1326
/************************************************************************
1327
* ****** END HANDLERS *******
1328
************************************************************************
1332
/************************************************************************
1333
* ****** INIT *******
1334
************************************************************************
1336
var con, Debug, srcW;
1339
/* initialise debugger */
1340
if (!Debug || typeof(Debug) == 'undefined' || !Debug.start) {
1341
if (typeof(Debugger) != 'undefined')
1342
Debug = new Debugger(DEBUG_LVL,'JWChat ' + cutResource(jid));
1344
Debug = new Object();
1345
Debug.log = function() {};
1346
Debug.start = function() {};
1349
if (DEBUG && (!USE_DEBUGJID || DEBUGJID == cutResource(jid)))
1352
Debug.log("jid: "+jid+"\npass: "+pass,2);
1354
/* get some refs to static elements */
1355
statusLed = frames["jwc_main"].document.getElementById('statusLed');
1356
statusMsg = frames["jwc_main"].document.getElementById('statusMsg');
1357
fmd = frames["jwc_main"].iRoster.document;
1360
document.title = "JWChat - " + nick;
1363
frames["jwc_main"].document.getElementById('myNickname').innerHTML = nick;
1365
/* init empty roster */
1366
roster = new Roster();
1369
* create new connection
1371
var oArg = {oDbg: Debug, httpbase: HTTPBASE, timerval: timerval};
1373
if (BACKEND_TYPE == 'binding')
1374
con = new JSJaCHttpBindingConnection(oArg);
1376
con = new JSJaCHttpPollingConnection(oArg);
1378
/* register handlers */
1379
con.registerHandler('iq',handleIQSet);
1380
con.registerHandler('presence',handlePresence);
1381
con.registerHandler('message',handleMessage);
1382
con.registerHandler('message',handleMessageError);
1383
con.registerHandler('ondisconnect',handleDisconnect);
1384
con.registerHandler('onconnect',handleConnected);
1385
con.registerHandler('onerror',handleConError);
1387
/* connect to remote */
1388
oArg = {domain:JABBERSERVER,username:jid.substring(0,jid.indexOf('@')),resource:jid.substring(jid.indexOf('/')+1),pass:pass,register:register}
1390
if (BACKEND_TYPE == 'binding') {
1391
if (opener.connect_port && !isNaN(opener.connect_port))
1392
oArg.port = opener.connect_port;
1393
if (opener.connect_host && opener.connect_host != '')
1394
oArg.host = opener.connect_host;
1395
if (opener && opener.connect_secure)
1401
/************************************************************************
1402
* ****** LOGOUT *******
1403
************************************************************************
1406
function cleanUp() {
1407
/* close dependent windows */
1411
if (subw && !subw.closed)
1414
if (typeof(ow) != 'undefined' && ow && !ow.closed)
1417
if (searchW && !searchW.closed)
1420
if (ebW && !ebW.closed)
1423
fmd.getElementById('roster').innerHTML = '';
1426
frames["jwc_sound"].document.open();
1427
frames["jwc_sound"].document.write();
1428
frames["jwc_sound"].document.close();
1431
var logoutCalled = false;
1433
logoutCalled = true;
1436
if (!con.connected())
1440
var iq = new JSJaCIQ();
1441
iq.setIQ(null,'set');
1442
var query = iq.setQuery('jabber:iq:private');
1443
var aNode = query.appendChild(
1444
iq.buildNode('jwchat', {'xmlns': 'jwchat:state'}));
1447
if (onlstat != 'offline')
1448
aNode.appendChild(iq.buildNode('presence', onlstat));
1451
aNode.appendChild(iq.buildNode('onlmsg', onlmsg));
1453
var hiddengroups = '';
1454
if (typeof(roster) != 'undefined') {
1455
for (var i in roster.hiddenGroups)
1456
hiddengroups += i+",";
1459
if (hiddengroups != '')
1460
aNode.appendChild(iq.buildNode('hiddenGroups', hiddengroups));
1462
Debug.log(iq.xml(), 2);
1465
var aPresence = new JSJaCPresence();
1466
aPresence.setType('unavailable');
1467
con.send(aPresence);
1472
/************************************************************************
1473
* ****** INITIALISE VARS *******
1474
************************************************************************
1484
if (opener && opener.JABBERSERVER)
1485
JABBERSERVER = opener.JABBERSERVER;
1486
else if (passedArgs['server'])
1487
JABBERSERVER = passedArgs['server'];
1489
if (opener && opener.BACKEND_TYPE)
1490
BACKEND_TYPE = opener.BACKEND_TYPE;
1491
else if (passedArgs['btype'])
1492
BACKEND_TYPE = passedArgs['btype'];
1494
if (opener && opener.HTTPBASE)
1495
HTTPBASE = opener.HTTPBASE;
1496
else if (passedArgs['base'])
1497
HTTPBASE = passedArgs['base'];
1499
if (opener && opener.pass)
1501
else if (passedArgs['pass'])
1502
pass = passedArgs['pass'];
1504
if (opener && opener.jid)
1506
else if (passedArgs['jid'])
1507
jid = passedArgs['jid'];
1509
if (opener && opener.register)
1510
register = opener.register
1511
else if (passedArgs['register'])
1512
register = eval(passedArgs['register']);
1515
alert("Falta el JID.\nAbortando...");
1519
alert("Falta la contraseña\nAbortando...");
1523
if (!isValidJID(jid))
1526
nick = jid.substring(0,jid.indexOf('@'));
1529
if (opener && opener.myStyle)
1530
stylesheet = THEMESDIR + "/" + opener.myStyle + "/" + stylesheet;
1531
else if (passedArgs['myStyle'])
1532
stylesheet = THEMESDIR + "/" + passedArgs['myStyle'] + "/" + stylesheet;
1534
function updateStyleIE() {
1536
roster.updateStyleIE();
1541
onresize = updateStyleIE;
1545
<script src="roster.js"></script>
1547
<frameset rows="100%,0,0,0,0" border="0">
1548
<frame src="roster.html" name="jwc_main" marginwidth="0" marginheight="0" scrolling="no">
1549
<frame src="empty.html" name="jwc_sound" marginwidth="0" marginheight="0" onLoad="soundLoaded();">
1552
Tu navegador debe soportar frames y JavaScript para usar esta aplicación. Por favor revise nuestro <a href="help.html">manual en línea</a> para una lista de navegadores soportados.