diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c07b1f..5ae683d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +v3.2.1 / 2017-06-02 +=== +- upgrade jsxc to v3.2.1 ([change log](https://github.com/jsxc/jsxc/blob/master/CHANGELOG.md)) + v3.1.1 / 2017-02-14 === - upgrade jsxc to v3.1.1 ([change log](https://github.com/jsxc/jsxc/blob/master/CHANGELOG.md)) diff --git a/build/css/jsxc.sogo.css b/build/css/jsxc.sogo.css index b0a7876..c8c623d 100644 --- a/build/css/jsxc.sogo.css +++ b/build/css/jsxc.sogo.css @@ -2402,7 +2402,8 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { width: 100%; } #jsxc_dialog .mfp-close, #jsxc_webrtc .mfp-close { - font-size: 23px; } + font-size: 23px; + font-weight: normal; } .mfp-bg { z-index: 9000; } @@ -2785,7 +2786,7 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { width: 14px; height: 100%; position: absolute; - left: -14px !important; + right: 100%; top: 0; z-index: 110; background-color: transparent; @@ -2997,15 +2998,14 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { position: fixed; left: 0; bottom: 0; - width: 30px; - height: 30px; } + width: 30px; } @media (max-width: 768px) { #jsxc_windowListSB { display: none; } } #jsxc_windowListSB > div { box-sizing: border-box; width: 14px; - height: 100%; + height: 30px; background-color: #cccccc; color: gray; text-align: center; @@ -3115,7 +3115,8 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { .jsxc_window .jsxc_emoticons:hover:after { opacity: 0.5; } .jsxc_window .jsxc_fade { - position: relative; } + position: relative; + overflow: hidden; } .jsxc_window .jsxc_fade .jsxc_overlay { display: none; background-color: rgba(0, 0, 0, 0.5); @@ -3165,6 +3166,31 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { text-overflow: ellipsis; } .jsxc_window .jsxc_fade .jsxc_overlay > div a:hover { text-decoration: underline; } + .jsxc_window .jsxc_fade .jsxc_mam-load-more { + display: none; + text-align: center; + font-size: 0.8em; + font-style: italic; + position: absolute; + top: -42px; + left: 0; + right: 0; + height: 42px; + cursor: pointer; + z-index: 80; + line-height: 42px; + opacity: 0; + -webkit-transition: opacity 0.5s, top 0.5s; + transition: opacity 0.5s, top 0.5s; } + .jsxc_window .jsxc_fade .jsxc_mam-load-more.jsxc_show { + top: 0; + opacity: 0.7; } + .jsxc_window .jsxc_fade .jsxc_mam-load-more.jsxc_show:hover { + opacity: 1; } + .jsxc_window .jsxc_fade.jsxc_mam-enable .jsxc_textarea { + padding-top: 42px; } + .jsxc_window .jsxc_fade.jsxc_mam-enable .jsxc_mam-load-more { + display: block; } .jsxc_window .jsxc_avatar { margin-top: 1px; } .jsxc_window .jsxc_textarea { @@ -3252,16 +3278,16 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { position: relative; outline: none; clear: both; } - .jsxc_chatmessage.jsxc_error { - opacity: 0.7; } - .jsxc_chatmessage.jsxc_error:before { - content: " "; - position: absolute; - top: 3px; - right: 3px; - width: 8px; - height: 8px; - background-color: yellow; } + .jsxc_chatmessage.jsxc_error:before { + content: attr(data-error-msg); + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(255, 255, 255, 0.7); + text-align: center; + padding: 10px 5px; } .jsxc_chatmessage a { color: #00f; text-decoration: underline; @@ -3410,26 +3436,6 @@ fieldset[disabled] #jsxc_webrtc .checkbox label { width: 1.2em; height: 1.2em; vertical-align: middle; } - .jsxc_sys.jsxc_composing { - text-align: center; - font-size: 0.9em; - font-style: italic; - display: block; - opacity: 0; - overflow: hidden; - -webkit-transition: opacity 0.6s; - transition: opacity 0.6s; } - .jsxc_sys.jsxc_composing:before { - content: " "; - width: 1.5em; - height: 1em; - display: inline-block; - background-size: 80%; - background-repeat: no-repeat; - margin: 0 3px 0 0; - background-image: url('../js/jsxc/img/composing.png'); } - .jsxc_sys.jsxc_composing.jsxc_fadein { - opacity: 1; } div.jsxc_settings { position: relative; } @@ -3466,6 +3472,35 @@ div.jsxc_transfer { div.jsxc_transfer.jsxc_enc.jsxc_trust { background-image: url('../js/jsxc/img/padlock_close_green.svg'); } +.jsxc_status-msg { + font-size: 12px; + display: none; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + height: 50%; + line-height: 17.5px; + opacity: 0.7; } + .jsxc_status-msg.jsxc_composing:before { + content: " "; + width: 1em; + height: 1em; + display: inline-block; + background-size: cover; + vertical-align: middle; + background-repeat: no-repeat; + background-image: url('../js/jsxc/img/composing.png'); } + +.jsxc_status-msg-show .jsxc_name { + height: 50%; + line-height: 20px; } + +.jsxc_status-msg-show .jsxc_status-msg { + display: block; } + +.jsxc_status-msg-show .jsxc_lastmsg { + display: none !important; } + .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_bar .jsxc_avatar, li[data-type='groupchat'] .jsxc_avatar { text-indent: 999px; background-image: url('../js/jsxc/img/group_white.svg'); @@ -3475,7 +3510,7 @@ div.jsxc_transfer { .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_fade { padding-top: 44px; } -.jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_fingerprints, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_verification, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_transfer, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_video, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_sendFile { +.jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_fingerprints, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_verification, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_transfer, .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_video { display: none; } .jsxc_windowItem.jsxc_groupchat.jsxc_normal .jsxc_members { @@ -3543,6 +3578,8 @@ div.jsxc_transfer { color: inherit; } .jsxc_windowItem .jsxc_memberlist.jsxc_expand ul > li .jsxc_avatar { margin-right: 4px; } + .jsxc_windowItem .jsxc_memberlist .jsxc_avatar :before { + display: none; } li[data-type='groupchat'] .jsxc_video { display: none; } @@ -3628,6 +3665,14 @@ li[data-type='groupchat'] .jsxc_video { background-color: #f2f2f2; padding: 10px; margin: 0 -30px 10px; } + #jsxc_dialog form fieldset h3.jsxc_experimental:after { + content: "experimental"; + font-size: 0.7em; + border-radius: 2px; + padding: 1px 5px; + background-color: orange; + margin-left: 5px; + font-weight: normal; } #jsxc_dialog legend { border: 0; font-size: 20px; } diff --git a/build/js/jsxc/jsxc.js b/build/js/jsxc/jsxc.js index 47b7bee..fb78460 100644 --- a/build/js/jsxc/jsxc.js +++ b/build/js/jsxc/jsxc.js @@ -1,5 +1,5 @@ /*! - * jsxc v3.1.1 - 2017-02-14 + * jsxc v3.2.1 - 2017-06-01 * * Copyright (c) 2017 Klaus Herberth
* Released under the MIT license @@ -7,7 +7,7 @@ * Please see http://www.jsxc.org/ * * @author Klaus Herberth - * @version 3.1.1 + * @version 3.2.1 * @license MIT */ @@ -25,7 +25,7 @@ var jsxc = null, RTC = null, RTCPeerconnection = null; */ jsxc = { /** Version of jsxc */ - version: '3.1.1', + version: '3.2.1', /** True if i'm the master */ master: false, @@ -48,9 +48,6 @@ jsxc = { /** Interval for keep-alive */ keepaliveInterval: null, - /** True if jid, sid and rid was used to connect */ - reconnect: false, - /** True if restore is complete */ restoreCompleted: false, @@ -101,7 +98,8 @@ jsxc = { }, NS: { CARBONS: 'urn:xmpp:carbons:2', - FORWARD: 'urn:xmpp:forward:0' + FORWARD: 'urn:xmpp:forward:0', + HINTS: 'urn:xmpp:hints' }, HIDDEN: 'hidden', SHOWN: 'shown', @@ -242,8 +240,8 @@ jsxc = { } // Check localStorage - if (typeof(localStorage) === 'undefined') { - jsxc.warn("Browser doesn't support localStorage."); + if (!jsxc.storage.hasSupport()) { + jsxc.error("Browser doesn't support localStorage. JSXC will be disabled."); return; } @@ -295,6 +293,7 @@ jsxc = { lng: lang, fallbackLng: 'en', resources: I18next, + returnNull: false, debug: jsxc.storage.getItem('debug') === true, interpolation: { prefix: '__', @@ -551,6 +550,10 @@ jsxc = { username = settings.xmpp.username; } + if (typeof settings.xmpp.password === 'string') { + password = settings.xmpp.password; + } + var resource = (settings.xmpp.resource) ? '/' + settings.xmpp.resource : ''; var domain = settings.xmpp.domain; var jid; @@ -604,7 +607,7 @@ jsxc = { $('#jsxc_roster').removeClass('jsxc_noConnection'); jsxc.registerLogout(); - jsxc.gui.updateAvatar($('#jsxc_roster > .jsxc_bottom'), jsxc.jidToBid(jsxc.storage.getItem('jid')), 'own'); + jsxc.gui.avatar.update($('#jsxc_roster > .jsxc_bottom'), jsxc.jidToBid(jsxc.storage.getItem('jid')), 'own'); jsxc.gui.restore(); }, @@ -672,7 +675,7 @@ jsxc = { jsxc.otr.createDSA(); } - jsxc.gui.updateAvatar($('#jsxc_roster > .jsxc_bottom'), jsxc.jidToBid(jsxc.storage.getItem('jid')), 'own'); + jsxc.gui.avatar.update($('#jsxc_roster > .jsxc_bottom'), jsxc.jidToBid(jsxc.storage.getItem('jid')), 'own'); }, /** @@ -1080,6 +1083,7 @@ jsxc.xmpp = { $(document).on('authfail.jsxc', jsxc.xmpp.onAuthFail); Strophe.addNamespace('RECEIPTS', 'urn:xmpp:receipts'); + Strophe.addNamespace('VERSION', 'jabber:iq:version'); } // Create new connection (no login) @@ -1133,8 +1137,6 @@ jsxc.xmpp = { jsxc.debug('Try to attach'); jsxc.debug('SID: ' + sid); - jsxc.reconnect = true; - jsxc.xmpp.conn.attach(jid, sid, rid, callback); } else { jsxc.debug('New connection'); @@ -1142,6 +1144,7 @@ jsxc.xmpp = { if (jsxc.xmpp.conn.caps) { // Add system handler, because user handler isn't called before // we are authenticated + // @REVIEW this could maybe retrieved from jsxc.xmpp.conn.features jsxc.xmpp.conn._addSysHandler(function(stanza) { var from = jsxc.xmpp.conn.domain, c = stanza.querySelector('c'), @@ -1182,10 +1185,13 @@ jsxc.xmpp = { // REVIEW: this should maybe moved to xmpp.disconnected // clean up - jsxc.storage.removeUserItem('buddylist'); jsxc.storage.removeUserItem('windowlist'); jsxc.storage.removeUserItem('unreadMsg'); + if (jsxc.gui.favicon) { + jsxc.gui.favicon.badge(0); + } + // Hide dropdown menu $('body').click(); @@ -1242,6 +1248,9 @@ jsxc.xmpp = { jsxc.xmpp.saveSessionParameter(); + var rosterVerSupport = $(jsxc.xmpp.conn.features).find('[xmlns="urn:xmpp:features:rosterver"]').length > 0; + jsxc.storage.setUserItem('rosterVerSupport', rosterVerSupport); + if (jsxc.options.loginForm.triggered) { switch (jsxc.options.loginForm.onConnected || 'submit') { case 'submit': @@ -1272,11 +1281,15 @@ jsxc.xmpp = { $('#jsxc_roster').removeClass('jsxc_noConnection'); + Strophe.addNamespace('VERSION', 'jabber:iq:version'); + jsxc.xmpp.conn.addHandler(jsxc.xmpp.onRosterChanged, 'jabber:iq:roster', 'iq', 'set'); jsxc.xmpp.conn.addHandler(jsxc.xmpp.onChatMessage, null, 'message', 'chat'); + jsxc.xmpp.conn.addHandler(jsxc.xmpp.onErrorMessage, null, 'message', 'error'); jsxc.xmpp.conn.addHandler(jsxc.xmpp.onHeadlineMessage, null, 'message', 'headline'); jsxc.xmpp.conn.addHandler(jsxc.xmpp.onReceived, null, 'message'); jsxc.xmpp.conn.addHandler(jsxc.xmpp.onPresence, null, 'presence'); + jsxc.xmpp.conn.addHandler(jsxc.xmpp.onVersionRequest, Strophe.NS.VERSION, 'iq', 'get'); jsxc.gui.init(); @@ -1317,19 +1330,28 @@ jsxc.xmpp = { } } + var rosterLoaded = jsxc.storage.getUserItem('rosterLoaded'); + // Only load roaster if necessary - if (!jsxc.reconnect || !jsxc.storage.getUserItem('buddylist')) { + if (rosterLoaded !== jsxc.xmpp.conn._proto.sid) { // in order to not overide existing presence information, we send // pres first after roster is ready $(document).one('cloaded.roster.jsxc', jsxc.xmpp.sendPres); $('#jsxc_roster > p:first').remove(); + var queryAttr = { + xmlns: 'jabber:iq:roster' + }; + + if (jsxc.storage.getUserItem('rosterVerSupport')) { + // @TODO check if we really cached the roster + queryAttr.ver = jsxc.storage.getUserItem('rosterVer') || ''; + } + var iq = $iq({ type: 'get' - }).c('query', { - xmlns: 'jabber:iq:roster' - }); + }).c('query', queryAttr); jsxc.xmpp.conn.sendIQ(iq, jsxc.xmpp.onRoster); } else { @@ -1357,14 +1379,12 @@ jsxc.xmpp = { }, initNewConnection: function() { - // make shure roster will be reloaded - jsxc.storage.removeUserItem('buddylist'); - jsxc.storage.removeUserItem('windowlist'); jsxc.storage.removeUserItem('own'); jsxc.storage.removeUserItem('avatar', 'own'); jsxc.storage.removeUserItem('otrlist'); jsxc.storage.removeUserItem('unreadMsg'); + jsxc.storage.removeUserItem('features'); // reset user options jsxc.storage.removeUserElement('options', 'RTCPeerConfig'); @@ -1379,6 +1399,7 @@ jsxc.xmpp = { jsxc.xmpp.conn.disco.addIdentity('client', 'web', 'JSXC'); jsxc.xmpp.conn.disco.addFeature(Strophe.NS.DISCO_INFO); jsxc.xmpp.conn.disco.addFeature(Strophe.NS.RECEIPTS); + jsxc.xmpp.conn.disco.addFeature(Strophe.NS.VERSION); } // create presence stanza @@ -1401,6 +1422,23 @@ jsxc.xmpp = { jsxc.debug('Send presence', pres.toString()); jsxc.xmpp.conn.send(pres); + + if (!jsxc.storage.getUserItem('features')) { + jsxc.xmpp.conn.flush(); + + var barJid = Strophe.getBareJidFromJid(jsxc.xmpp.conn.jid); + + jsxc.xmpp.conn.disco.info(barJid, undefined, function(stanza) { + var features = $(stanza).find('feature').map(function() { + return $(this).attr('var'); + }); + + jsxc.storage.setUserItem('features', features.toArray()); + $(document).trigger('features.jsxc'); + }); + } else { + $(document).trigger('features.jsxc'); + } }, /** @@ -1417,6 +1455,7 @@ jsxc.xmpp = { jsxc.storage.removeItem('hidden'); jsxc.storage.removeUserItem('avatar', 'own'); jsxc.storage.removeUserItem('otrlist'); + jsxc.storage.removeUserItem('features'); $(document).off('connected.jsxc', jsxc.xmpp.connected); $(document).off('attached.jsxc', jsxc.xmpp.attached); @@ -1492,13 +1531,17 @@ jsxc.xmpp = { * @private */ onRoster: function(iq) { - /* - * ... - */ - jsxc.debug('Load roster', iq); + jsxc.storage.setUserItem('rosterLoaded', jsxc.xmpp.conn._proto.sid); + + if ($(iq).find('query').length === 0) { + jsxc.debug('Use cached roster'); + + jsxc.restoreRoster(); + return; + } + var buddies = []; $(iq).find('item').each(function() { @@ -1529,6 +1572,10 @@ jsxc.xmpp = { jsxc.storage.setUserItem('buddylist', buddies); + if ($(iq).find('query').attr('ver')) { + jsxc.storage.setUserItem('rosterVer', $(iq).find('query').attr('ver')); + } + // load bookmarks jsxc.xmpp.bookmarks.load(); @@ -1608,6 +1655,10 @@ jsxc.xmpp = { } }); + if ($(iq).find('query').attr('ver')) { + jsxc.storage.setUserItem('rosterVer', $(iq).find('query').attr('ver')); + } + if (!jsxc.storage.getUserItem('buddylist') || jsxc.storage.getUserItem('buddylist').length === 0) { jsxc.gui.roster.empty(); } else { @@ -1731,9 +1782,7 @@ jsxc.xmpp = { }); } - if (data.type === 'groupchat') { - data.status = status; - } else { + if (data.type !== 'groupchat') { data.status = max; } @@ -1855,14 +1904,22 @@ jsxc.xmpp = { if (chat.length === 0) { jsxc.notice.add({ msg: $.t('Unknown_sender'), - description: $.t('You_received_a_message_from_an_unknown_sender') + ' (' + bid + ').' + description: $.t('You_received_a_message_from_an_unknown_sender_') + ' (' + bid + ').' }, 'gui.showUnknownSender', [bid]); } var msg = jsxc.removeHTML(body); msg = jsxc.escapeHTML(msg); - jsxc.storage.saveMessage(bid, 'in', msg, false, forwarded, stamp); + var messageObj = new jsxc.Message({ + bid: bid, + msg: msg, + direction: jsxc.Message.IN, + encrypted: false, + forwarded: forwarded, + stamp: stamp + }); + messageObj.save(); return true; } @@ -1899,6 +1956,7 @@ jsxc.xmpp = { var httpUploadElement = htmlBody.find('a[data-type][data-name][data-size]'); if (httpUploadElement.length === 1) { + // deprecated syntax @since 3.2.1 attachment = { type: httpUploadElement.attr('data-type'), name: httpUploadElement.attr('data-name'), @@ -1917,6 +1975,44 @@ jsxc.xmpp = { if (!attachment.type.match(/^[a-z]+\/[a-z0-9-+.*]+$/i) || !attachment.name.match(/^[\s\w.,-]+$/i) || !attachment.size.match(/^\d+$/i)) { attachment = undefined; + jsxc.warn('Invalid file type, name or size.'); + } + } else if (htmlBody.find('>a').length === 1) { + var linkElement = htmlBody.find('>a'); + var metaString = ''; + var thumbnail; + + if (linkElement.find('>img').length === 1) { + var imgElement = linkElement.find('>img'); + var src = imgElement.attr('src') || ''; + var altString = imgElement.attr('alt') || ''; + metaString = altString.replace(/^Preview:/, ''); + + if (src.match(/^\s*data:[a-z]+\/[a-z0-9-+.*]+;base64,[a-z0-9=+/]+$/i)) { + thumbnail = src; + } + } else { + metaString = linkElement.text(); + } + + var metaMatch = metaString.match(/^([a-z]+\/[a-z0-9-+.*]+)\|(\d+)\|([\s\w.,-]+)/); + + if (metaMatch) { + attachment = { + type: metaMatch[1], + size: metaMatch[2], + name: metaMatch[3], + }; + + if (thumbnail) { + attachment.thumbnail = thumbnail; + } + + if (linkElement.attr('href') && linkElement.attr('href').match(/^https?:\/\//)) { + attachment.data = linkElement.attr('href'); + body = null; + } + } else { jsxc.warn('Invalid file type, name or size.'); } } @@ -1925,12 +2021,14 @@ jsxc.xmpp = { if (jsxc.otr.objects.hasOwnProperty(bid) && body) { // @TODO check for file upload url after decryption jsxc.otr.objects[bid].receiveMsg(body, { + _uid: mid, stamp: stamp, forwarded: forwarded, attachment: attachment }); } else { jsxc.gui.window.postMessage({ + _uid: mid, bid: bid, direction: jsxc.Message.IN, msg: body, @@ -1945,6 +2043,58 @@ jsxc.xmpp = { return true; }, + onErrorMessage: function(message) { + var bid = jsxc.jidToBid($(message).attr('from')); + + if (jsxc.gui.window.get(bid).length === 0 || !$(message).attr('id')) { + return true; + } + + if ($(message).find('item-not-found').length > 0) { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send_item-not-found') + }); + } else if ($(message).find('forbidden').length > 0) { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send_forbidden') + }); + } else if ($(message).find('not-acceptable').length > 0) { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send_not-acceptable') + }); + } else if ($(message).find('remote-server-not-found').length > 0) { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send_remote-server-not-found') + }); + } else if ($(message).find('service-unavailable').length > 0) { + if ($(message).find('[xmlns="' + Strophe.NS.CHATSTATES + '"]').length === 0) { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send_resource-unavailable') + }); + } + } else { + jsxc.gui.window.postMessage({ + bid: bid, + direction: jsxc.Message.SYS, + msg: $.t('message_not_send') + }); + } + + jsxc.debug('error message for ' + bid, $(message).find('error')[0]); + + return true; + }, + /** * Process message stanzas of type headline. * @@ -1977,6 +2127,29 @@ jsxc.xmpp = { return true; }, + /** + * Respond to version request (XEP-0092). + */ + onVersionRequest: function(stanza) { + stanza = $(stanza); + + var from = stanza.attr('from'); + var id = stanza.attr('id'); + + var iq = $iq({ + type: 'result', + to: from, + id: id + }).c('query', { + xmlns: Strophe.NS.VERSION + }).c('name').t('JSXC').up() + .c('version').t(jsxc.version); + + jsxc.xmpp.conn.sendIQ(iq); + + return true; + }, + /** * Triggerd if the rid changed * @@ -2035,9 +2208,9 @@ jsxc.xmpp = { type: 'subscribe' })); - jsxc.storage.removeUserItem('add_' + bid); + jsxc.storage.removeUserItem('add', bid); } else { - jsxc.storage.setUserItem('add_' + bid, { + jsxc.storage.setUserItem('add', bid, { username: username, alias: alias || null }); @@ -2089,7 +2262,7 @@ jsxc.xmpp = { */ sendMessage: function(message) { var bid = message.bid; - var msg = message.htmlMsg; + var msg = message.msg; var mucRoomNames = (jsxc.xmpp.conn.muc && jsxc.xmpp.conn.muc.roomNames) ? jsxc.xmpp.conn.muc.roomNames : []; var isMucBid = mucRoomNames.indexOf(bid) >= 0; @@ -2123,18 +2296,14 @@ jsxc.xmpp = { id: message._uid }); - if (message.type === jsxc.Message.HTML) { - xmlMsg.c("html", { - xmlns: Strophe.NS.XHTML_IM - }); + if (message.type === jsxc.Message.HTML && msg === message.msg && message.htmlMsg) { + xmlMsg.c('body').t(msg); - // Omit StropheJS XEP-0071 limitations - var body = Strophe.xmlElement("body", { + xmlMsg.up().c('html', { + xmlns: Strophe.NS.XHTML_IM + }).c('body', { xmlns: Strophe.NS.XHTML - }); - body.innerHTML = msg; - - xmlMsg.node.appendChild(body); + }).h(message.htmlMsg).up(); } else { xmlMsg.c('body').t(msg); } @@ -2145,6 +2314,12 @@ jsxc.xmpp = { }); } + if (msg.match(/^\?OTR/)) { + xmlMsg.up().c("no-permanent-store", { + xmlns: jsxc.CONST.NS.HINTS + }); + } + if (type === 'chat' && (isBar || jsxc.xmpp.conn.caps.hasFeatureByJid(jid, Strophe.NS.RECEIPTS))) { // Add request according to XEP-0184 xmlMsg.up().c('request', { @@ -2339,330 +2514,94 @@ jsxc.xmpp.carbons = { } }; +/* global Favico, emojione*/ /** - * @namespace jsxc.fileTransfer - * @type {Object} - */ -jsxc.fileTransfer = {}; - -/** - * Make bytes more human readable. + * Handle functions for chat window's and buddylist * - * @memberOf jsxc.fileTransfer - * @param {Integer} byte - * @return {String} + * @namespace jsxc.gui */ -jsxc.fileTransfer.formatByte = function(byte) { - var s = ['', 'KB', 'MB', 'GB', 'TB']; - var i; +jsxc.gui = { + /** Smilie token to file mapping */ + emotions: [ + ['O:-) O:)', 'innocent'], + ['>:-( >:( >:-( >:(', 'angry'], + [':-) :)', 'slight_smile'], + [':-D :D', 'grin'], + [':-( :(', 'disappointed'], + [';-) ;)', 'wink'], + [':-P :P', 'stuck_out_tongue'], + ['=-O', 'astonished'], + [':kiss: :-*', 'kissing_heart'], + ['8-) :cool:', 'sunglasses'], + [':-X :X', 'zipper_mouth'], + [':yes:', 'thumbsup'], + [':no:', 'thumbsdown'], + [':beer:', 'beer'], + [':coffee:', 'coffee'], + [':devil:', 'smiling_imp'], + [':kiss: :kissing:', 'kissing'], + ['@->-- @->--', 'rose'], + [':music:', 'musical_note'], + [':love:', 'heart_eyes'], + [':heart:', 'heart'], + [':brokenheart:', 'broken_heart'], + [':zzz:', 'zzz'], + [':wait:', 'hand_splayed'] + ], - for (i = 1; i < s.length; i++) { - if (byte < 1024) { - break; - } - byte /= 1024; - } + favicon: null, - return (Math.round(byte * 10) / 10) + s[i - 1]; -}; + regShortNames: null, -/** - * Start file transfer dialog. - * - * @memberOf jsxc.fileTransfer - * @param {String} jid - */ -jsxc.fileTransfer.startGuiAction = function(jid) { - var bid = jsxc.jidToBid(jid); - var res = Strophe.getResourceFromJid(jid); + emoticonList: { + 'core': { + ':klaus:': ['klaus'], + ':jabber:': ['jabber'], + ':xmpp:': ['xmpp'], + ':jsxc:': ['jsxc'], + ':owncloud:': ['owncloud'], + ':nextcloud:': ['nextcloud'] + }, + 'emojione': emojione.emojioneList + }, - if (!res && !jsxc.xmpp.httpUpload.ready) { - jsxc.fileTransfer.selectResource(bid, jsxc.fileTransfer.startGuiAction); + /** + * Different uri query actions as defined in XEP-0147. + * + * @namespace jsxc.gui.queryActions + */ + queryActions: { + /** xmpp:JID?message[;body=TEXT] */ + message: function(jid, params) { + var bid = jsxc.jidToBid(jid); - return; - } + if (!jsxc.storage.getUserItem('buddy', bid)) { + // init contact + jsxc.storage.saveBuddy(bid, { + jid: jid, + name: bid, + status: 0, + sub: 'none', + res: [], + rnd: Math.random() + }); + } - jsxc.fileTransfer.showFileSelection(jid); -}; + var win = jsxc.gui.window.open(bid); -/** - * Show select dialog for file transfer capable resources. - * - * @memberOf jsxc.fileTransfer - * @param {String} bid - * @param {Function} success_cb Called if user selects resource - * @param {Function} error_cb Called if no resource was found or selected - */ -jsxc.fileTransfer.selectResource = function(bid, success_cb, error_cb) { - var win = jsxc.gui.window.get(bid); - var jid = win.data('jid'); - var res = Strophe.getResourceFromJid(jid); + if (params && typeof params.body === 'string') { + win.find('.jsxc_textinput').val(params.body); + } + }, - var fileCapableRes = jsxc.webrtc.getCapableRes(jid, jsxc.webrtc.reqFileFeatures); - var resources = Object.keys(jsxc.storage.getUserItem('res', bid)) || []; + /** xmpp:JID?remove */ + remove: function(jid) { + jsxc.gui.showRemoveDialog(jsxc.jidToBid(jid)); + }, - if (res === null && resources.length === 1 && fileCapableRes.length === 1) { - // only one resource is available and this resource is also capable to receive files - res = fileCapableRes[0]; - jid = bid + '/' + res; - - success_cb(jid); - } else if (fileCapableRes.indexOf(res) >= 0) { - // currently used resource is capable to receive files - success_cb(bid + '/' + res); - } else if (fileCapableRes.indexOf(res) < 0) { - // show selection dialog - jsxc.gui.window.selectResource(bid, $.t('Your_contact_uses_multiple_clients_'), function(data) { - if (data.status === 'unavailable') { - jsxc.gui.window.hideOverlay(bid); - - if (typeof error_cb === 'function') { - error_cb(); - } - } else if (data.status === 'selected') { - success_cb(bid + '/' + data.result); - } - }, fileCapableRes); - } -}; - -/** - * Show file selector. - * - * @memberOf jsxc.fileTransfer - * @param {String} jid - */ -jsxc.fileTransfer.showFileSelection = function(jid) { - var bid = jsxc.jidToBid(jid); - var msg = $('
'); - msg.addClass('jsxc_chatmessage'); - - jsxc.gui.window.showOverlay(bid, msg, true); - - // open file selection for user - msg.find('label').click(); - - msg.find('[type="file"]').change(function(ev) { - var file = ev.target.files[0]; // FileList object - - if (!file) { - return; - } - - jsxc.fileTransfer.fileSelected(jid, msg, file); - }); -}; - -/** - * Callback for file selector. - * - * @memberOf jsxc.fileTransfer - * @param {String} jid - * @param {jQuery} msg jQuery object of temporary file message - * @param {File} file selected file - */ -jsxc.fileTransfer.fileSelected = function(jid, msg, file) { - var bid = jsxc.jidToBid(jid); - - if (file.transportMethod !== 'webrtc' && jsxc.xmpp.httpUpload.ready && file.size > jsxc.options.get('httpUpload').maxSize) { - jsxc.debug('File too large for http upload.'); - - file.transportMethod = 'webrtc'; - - jsxc.fileTransfer.selectResource(bid, function(jid) { - jsxc.fileTransfer.fileSelected(jid, msg, file); - }, function() { - var maxSize = jsxc.fileTransfer.formatByte(jsxc.options.get('httpUpload').maxSize); - var fileSize = jsxc.fileTransfer.formatByte(file.size); - - jsxc.gui.window.postMessage({ - bid: bid, - direction: jsxc.Message.SYS, - msg: $.t('File_too_large') + ' (' + fileSize + ' > ' + maxSize + ')' - }); - - jsxc.gui.window.hideOverlay(bid); - }); - - return; - } else if (!jsxc.xmpp.httpUpload.ready && Strophe.getResourceFromJid(jid)) { - // http upload not available - file.transportMethod = 'webrtc'; - } - - var attachment = $('
'); - attachment.addClass('jsxc_attachment'); - attachment.addClass('jsxc_' + file.type.replace(/\//, '-')); - attachment.addClass('jsxc_' + file.type.replace(/^([^/]+)\/.*/, '$1')); - - msg.empty().append(attachment); - - if (FileReader && file.type.match(/^image\//)) { - // show image preview - var img = $('preview').attr('title', file.name); - img.attr('src', jsxc.options.get('root') + '/img/loading.gif'); - img.appendTo(attachment); - - var reader = new FileReader(); - - reader.onload = function() { - img.attr('src', reader.result); - }; - - reader.readAsDataURL(file); - } else { - attachment.text(file.name + ' (' + file.size + ' byte)'); - } - - $('\n' + @@ -12187,7 +12728,7 @@ jsxc.gui.template['bookmarkDialog'] = '

\n' + jsxc.gui.template['chatWindow'] = '
  • \n' + '
    \n' + '
    \n' + -'
    \n' + +'
    \n' + '
    \n' + '
    \n' + '
    \n' + @@ -12219,6 +12760,7 @@ jsxc.gui.template['chatWindow'] = '
  • \n' + ' \n' + ' \n' + '
  • \n' + +'
    \n' + '
    \n' + ' \n' + '
    \n' + @@ -12407,7 +12949,7 @@ jsxc.gui.template['removeDialog'] = '

    \n' + jsxc.gui.template['roster'] = '
    \n' + '
      \n' + '
      \n' + -'
      \n' + +'
      \n' + '
      \n' + ' \n' + '
      \n' + @@ -12446,7 +12988,7 @@ jsxc.gui.template['roster'] = '
      \n' + ''; jsxc.gui.template['rosterBuddy'] = '
    • \n' + -'
      \n' + +'
      \n' + '
      \n' + '
      \n' + '
      \n' + @@ -12571,6 +13113,27 @@ jsxc.gui.template['settings'] = '
      \n' + ' \n' + '
      \n' + '\n' + +'
      \n' + +'
      \n' + +'

      \n' + +'

      \n' + +'
      \n' + +'
      \n' + +'
      \n' + +' \n' + +'
      \n' + +'
      \n' + +'
      \n' + +'
      \n' + +'
      \n' + +' \n' + +'
      \n' + +'
      \n' + +'
      \n' + +'
      \n' + +'\n' + '
      \n' + '
      \n' + '

      \n' + @@ -12674,4 +13237,4 @@ jsxc.gui.template['windowList'] = '
      \n' + '
      \n' + ''; -}(jQuery)); \ No newline at end of file +}(jQuery)); diff --git a/build/js/jsxc/jsxc.min.js b/build/js/jsxc/jsxc.min.js index faa4fc9..5790534 100644 --- a/build/js/jsxc/jsxc.min.js +++ b/build/js/jsxc/jsxc.min.js @@ -1,5 +1,5 @@ /*! - * jsxc v3.1.1 - 2017-02-14 + * jsxc v3.2.1 - 2017-06-01 * * Copyright (c) 2017 Klaus Herberth
      * Released under the MIT license @@ -7,14 +7,14 @@ * Please see http://www.jsxc.org/ * * @author Klaus Herberth - * @version 3.1.1 + * @version 3.2.1 * @license MIT */ -var jsxc=null,RTC=null,RTCPeerconnection=null;!function($){"use strict";jsxc={version:"3.1.1",master:!1,role_allocation:!1,to:[],toBusy:null,toNotification:null,toNotificationDelay:500,keepaliveInterval:null,reconnect:!1,restoreCompleted:!1,triggeredFromBox:!1,triggeredFromElement:!1,triggeredFromLogout:!1,ls:[],storageNotConform:null,toSNC:null,bid:null,currentState:null,currentUIState:null,CONST:{NOTIFICATION_DEFAULT:"default",NOTIFICATION_GRANTED:"granted",NOTIFICATION_DENIED:"denied",STATUS:["offline","dnd","xa","away","chat","online"],SOUNDS:{MSG:"incomingMessage.wav",CALL:"Rotary-Phone6.mp3",NOTICE:"Ping1.mp3"},REGEX:{JID:new RegExp("\\b[^\"&'\\/:<>@\\s]+@[\\w-_.]+\\b","ig"),URL:new RegExp(/(https?:\/\/|www\.)[^\s<>'"]+/gi)},NS:{CARBONS:"urn:xmpp:carbons:2",FORWARD:"urn:xmpp:forward:0"},HIDDEN:"hidden",SHOWN:"shown",STATE:{INITIATING:0,PREVCONFOUND:1,SUSPEND:2,TRYTOINTERCEPT:3,INTERCEPTED:4,ESTABLISHING:5,READY:6},UISTATE:{INITIATING:0,READY:1}},getFormattedTime:function(unixtime){var msgDate=new Date(parseInt(unixtime)),day=("0"+msgDate.getDate()).slice(-2),month=("0"+(msgDate.getMonth()+1)).slice(-2),year=msgDate.getFullYear(),hours=("0"+msgDate.getHours()).slice(-2),minutes=("0"+msgDate.getMinutes()).slice(-2),dateNow=new Date,date="function"==typeof msgDate.toLocaleDateString?msgDate.toLocaleDateString():day+"."+month+"."+year,time="function"==typeof msgDate.toLocaleTimeString?msgDate.toLocaleTimeString():hours+":"+minutes;return dateNow.setHours(0,0,0,0),msgDate.setHours(0,0,0,0),dateNow.getTime()!==msgDate.getTime()?date+" "+time:time},debug:function(msg,data,level){if(level&&(msg="["+level+"] "+msg),data){jsxc.storage.getItem("debug")===!0&&console.log(msg,data);var d;try{d=$("").prepend($(data).clone()).html()}catch(err){try{d=JSON.stringify(data)}catch(err2){d="see js console"}}jsxc.log=jsxc.log+"$ "+msg+": "+d+"\n"}else console.log(msg),jsxc.log=jsxc.log+"$ "+msg+"\n"},warn:function(msg,data){jsxc.debug(msg,data,"WARN")},error:function(msg,data){jsxc.debug(msg,data,"ERROR")},log:"",init:function(options){if(jsxc.changeState(jsxc.CONST.STATE.INITIATING),options&&options.loginForm&&"boolean"==typeof options.loginForm.attachIfFound&&!options.loginForm.ifFound&&(options.loginForm.ifFound=options.loginForm.attachIfFound?"attach":"pause"),options&&$.extend(!0,jsxc.options,options),"undefined"==typeof localStorage)return void jsxc.warn("Browser doesn't support localStorage.");jsxc.options.get=function(key){if(jsxc.bid){var local=jsxc.storage.getUserItem("options")||{};return"undefined"!=typeof local[key]?local[key]:jsxc.options[key]}return jsxc.options[key]},jsxc.options.set=function(key,value){jsxc.storage.updateItem("options",key,value,!0)},jsxc.storageNotConform=jsxc.storage.getItem("storageNotConform"),null===jsxc.storageNotConform&&(jsxc.storageNotConform=2);var lang;lang=null!==jsxc.storage.getItem("lang")?jsxc.storage.getItem("lang"):jsxc.options.autoLang&&navigator.languages&&navigator.languages.length>0?navigator.languages[0].substr(0,2):jsxc.options.autoLang&&navigator.language?navigator.language.substr(0,2):jsxc.options.defaultLang,window.i18next.init({lng:lang,fallbackLng:"en",resources:I18next,debug:jsxc.storage.getItem("debug")===!0,interpolation:{prefix:"__",suffix:"__"}},function(){window.jqueryI18next.init(window.i18next,$,{tName:"t",i18nName:"i18next",handleName:"localize"})}),jsxc.storage.getItem("debug")===!0&&(jsxc.options.otr.debug=!0),window.addEventListener("storage",jsxc.storage.onStorage,!1),$(document).on("attached.jsxc",jsxc.registerLogout);var isStorageAttachParameters=jsxc.storage.getItem("rid")&&jsxc.storage.getItem("sid")&&jsxc.storage.getItem("jid"),isOptionsAttachParameters=jsxc.options.xmpp.rid&&jsxc.options.xmpp.sid&&jsxc.options.xmpp.jid,isForceLoginForm=jsxc.options.loginForm&&"force"===jsxc.options.loginForm.ifFound&&jsxc.isLoginForm();if(!isStorageAttachParameters&&!isOptionsAttachParameters||isForceLoginForm){if(jsxc.storage.removeItem("rid"),jsxc.storage.removeItem("sid"),!jsxc.isLoginForm())return jsxc.changeState(jsxc.CONST.STATE.SUSPEND),void(jsxc.options.displayRosterMinimized()&&(jsxc.storage.setUserItem("roster","hidden"),jsxc.gui.roster.init(),jsxc.gui.roster.noConnection()));jsxc.changeState(jsxc.CONST.STATE.TRYTOINTERCEPT),"function"==typeof jsxc.options.formFound&&jsxc.options.formFound.call();var form=jsxc.options.loginForm.form=$(jsxc.options.loginForm.form),events=form.data("events")||{submit:[]},submits=[];$.each(events.submit,function(index,val){submits.push(val.handler)}),form.data("submits",submits),form.off("submit"),form.submit(function(ev){return ev.preventDefault(),jsxc.prepareLogin(function(settings){if(settings!==!1){var enabled=settings.loginForm&&settings.loginForm.enable||settings.xmpp&&settings.xmpp.onlogin;if(enabled="true"===enabled||enabled===!0)return jsxc.options.loginForm.triggered=!0,void jsxc.xmpp.login(jsxc.options.xmpp.jid,jsxc.options.xmpp.password)}jsxc.submitLoginForm()}),!1}),jsxc.changeState(jsxc.CONST.STATE.INTERCEPTED)}else(!jsxc.isLoginForm()||jsxc.options.loginForm&&"attach"===jsxc.options.loginForm.ifFound)&&(jsxc.changeState(jsxc.CONST.STATE.PREVCONFOUND),"undefined"==typeof jsxc.storage.getItem("alive")?jsxc.onMaster():jsxc.checkMaster())},start:function(){var args=arguments;return jsxc.role_allocation&&!jsxc.master?(jsxc.debug("There is an other master tab"),!1):jsxc.xmpp.conn&&jsxc.xmpp.connected?(jsxc.debug("We are already connected"),!1):(3===args.length&&$(document).one("attached.jsxc",function(){jsxc.xmpp.onRidChange(jsxc.xmpp.conn._proto.rid),jsxc.onMaster()}),void jsxc.checkMaster(function(){jsxc.xmpp.login.apply(this,args)}))},registerLogout:function(){if(null!==jsxc.options.logoutElement&&$(jsxc.options.logoutElement).length>0){var logout=function(ev){ev.stopPropagation(),ev.preventDefault(),jsxc.options.logoutElement=$(this),jsxc.triggeredFromLogout=!0,jsxc.xmpp.logout()};jsxc.options.logoutElement=$(jsxc.options.logoutElement),jsxc.options.logoutElement.off("click",null,logout).one("click",logout)}},isLoginForm:function(){return jsxc.options.loginForm.form&&jsxc.el_exists(jsxc.options.loginForm.form)&&jsxc.el_exists(jsxc.options.loginForm.jid)&&jsxc.el_exists(jsxc.options.loginForm.pass)},prepareLogin:function(username,password,cb){"function"==typeof username&&(cb=username,username=null),username=username||$(jsxc.options.loginForm.jid).val(),password=password||$(jsxc.options.loginForm.pass).val(),jsxc.triggeredFromBox||"dialog"!==jsxc.options.loginForm.onConnecting&&"undefined"!=typeof jsxc.options.loginForm.onConnecting||jsxc.gui.showWaitAlert($.t("Logging_in"));var settings;"function"==typeof jsxc.options.loadSettings?(settings=jsxc.options.loadSettings.call(this,username,password,function(s){jsxc._prepareLogin(username,password,cb,s)}),"undefined"!=typeof settings&&jsxc._prepareLogin(username,password,cb,settings)):jsxc._prepareLogin(username,password,cb)},_prepareLogin:function(username,password,cb,loadedSettings){if(loadedSettings===!1)return jsxc.warn("No settings provided"),void cb(!1);var settings=$.extend(!0,{},jsxc.options);loadedSettings?settings=$.extend(!0,settings,loadedSettings):loadedSettings={},"string"==typeof settings.xmpp.username&&(username=settings.xmpp.username);var jid,resource=settings.xmpp.resource?"/"+settings.xmpp.resource:"",domain=settings.xmpp.domain;jid=username.match(/@(.*)$/)?username.match(/\/(.*)$/)?username:username+resource:username+"@"+domain+resource,"function"==typeof jsxc.options.loginForm.preJid&&(jid=jsxc.options.loginForm.preJid(jid)),jsxc.bid=jsxc.jidToBid(jid),settings.xmpp.username=jid.split("@")[0],settings.xmpp.domain=jid.split("@")[1].split("/")[0],settings.xmpp.resource=jid.split("@")[1].split("/")[1]||"",loadedSettings.xmpp||(loadedSettings.xmpp={}),$.each(loadedSettings,function(key){var old=jsxc.options.get(key),val=settings[key];val=$.extend(!0,old,val),jsxc.options.set(key,val)}),jsxc.options.xmpp.jid=jid,jsxc.options.xmpp.password=password,cb(settings)},onSlave:function(){jsxc.debug("I am the slave."),jsxc.role_allocation=!0,jsxc.bid=jsxc.jidToBid(jsxc.storage.getItem("jid")),jsxc.gui.init(),$("#jsxc_roster").removeClass("jsxc_noConnection"),jsxc.registerLogout(),jsxc.gui.updateAvatar($("#jsxc_roster > .jsxc_bottom"),jsxc.jidToBid(jsxc.storage.getItem("jid")),"own"),jsxc.gui.restore()},onMaster:function(){jsxc.debug("I am master."),jsxc.master=!0,jsxc.storage.setItem("alive",0),jsxc.storage.setItem("alive_busy",0),jsxc.startKeepAlive(),jsxc.role_allocation=!0,jsxc.xmpp.login()},checkMaster:function(cb){jsxc.debug("check master"),cb=cb&&"function"==typeof cb?cb:jsxc.onMaster,"undefined"==typeof jsxc.storage.getItem("alive")?cb.call():(jsxc.to.push(window.setTimeout(cb,1e3)),jsxc.keepAlive("slave"))},masterActions:function(){if(jsxc.xmpp.conn&&jsxc.xmpp.conn.authenticated){var noti=jsxc.storage.getUserItem("notification");noti="number"==typeof noti?noti:2,jsxc.options.notification&¬i>0&&jsxc.notification.hasSupport()?jsxc.notification.hasPermission()?jsxc.notification.init():jsxc.notification.prepareRequest():jsxc.options.notification=!1,jsxc.options.get("otr").enable&&jsxc.otr.createDSA(),jsxc.gui.updateAvatar($("#jsxc_roster > .jsxc_bottom"),jsxc.jidToBid(jsxc.storage.getItem("jid")),"own")}},startKeepAlive:function(){jsxc.keepaliveInterval=window.setInterval(jsxc.keepAlive,jsxc.options.timeout-1e3)},keepAlive:function(role){var next=parseInt(jsxc.storage.getItem("alive"))+1;role=role||"master",jsxc.storage.setItem("alive",next+":"+role)},keepBusyAlive:function(){jsxc.toBusy&&window.clearTimeout(jsxc.toBusy),jsxc.keepaliveInterval&&window.clearInterval(jsxc.keepaliveInterval),jsxc.storage.ink("alive_busy"),jsxc.toBusy=window.setTimeout(jsxc.startKeepAlive,jsxc.options.busyTimeout-1e3)},random:function(max){return Math.floor(Math.random()*max)},el_exists:function(selector){return $(selector).length>0},jidToCid:function(jid){jsxc.warn("jsxc.jidToCid is deprecated!");var cid=Strophe.getBareJidFromJid(jid).replace("@","-").replace(/\./g,"-").toLowerCase();return cid},jidToBid:function(jid){return Strophe.unescapeNode(Strophe.getBareJidFromJid(jid).toLowerCase())},restoreRoster:function(){var buddies=jsxc.storage.getUserItem("buddylist");return buddies&&0!==buddies.length?($.each(buddies,function(index,value){jsxc.gui.roster.add(value)}),jsxc.gui.roster.loaded=!0,void $(document).trigger("cloaded.roster.jsxc")):(jsxc.debug("No saved buddylist."),void jsxc.gui.roster.empty())},restoreWindows:function(){var windows=jsxc.storage.getUserItem("windowlist");null!==windows&&$.each(windows,function(index,bid){var win=jsxc.storage.getUserItem("window",bid);return win?(jsxc.gui.window.init(bid),win.minimize?jsxc.gui.window.hide(bid):jsxc.gui.window.show(bid),void jsxc.gui.window.setText(bid,win.text)):(jsxc.debug("Associated window-element is missing: "+bid),!0)})},submitLoginForm:function(){var form=$(jsxc.options.loginForm.form).off("submit"),submits=form.data("submits")||[];$.each(submits,function(index,val){form.submit(val)}),form.find("#submit").length>0?form.find("#submit").click():form.get(0)&&"function"==typeof form.get(0).submit?form.submit():form.find('[type="submit"]').length>0?form.find('[type="submit"]').click():jsxc.warn("Could not submit login form.")},escapeHTML:function(text){return text=text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),text.replace(/&/g,"&").replace(//g,">")},removeHTML:function(text){return $("").html(text).text()},switchEvents:function(obj){var ns=Math.random().toString(36).substr(2,12),self=this;return $.each(obj,function(key,val){$(document).one(key+"."+ns,function(){$(document).off("."+ns),val.apply(self,arguments)})}),ns},isHidden:function(){var hidden=!1;return"undefined"!=typeof document.hidden?hidden=document.hidden:"undefined"!=typeof document.webkitHidden?hidden=document.webkitHidden:"undefined"!=typeof document.mozHidden?hidden=document.mozHidden:"undefined"!=typeof document.msHidden&&(hidden=document.msHidden),hidden&&jsxc.master?jsxc.storage.ink("hidden",0):hidden||jsxc.master||jsxc.storage.ink("hidden"),hidden},hasFocus:function(){var focus=!0;return"function"==typeof document.hasFocus&&(focus=document.hasFocus()),!focus&&jsxc.master?jsxc.storage.ink("focus",0):focus&&!jsxc.master&&jsxc.storage.ink("focus"),focus},exec:function(fnName,fnParams){var i,fnList=fnName.split("."),fn=jsxc[fnList[0]];for(i=1;i",data)}),jsxc.xmpp.conn.nextValidRid=jsxc.xmpp.onRidChange;var callback=function(status,condition){switch(jsxc.debug(Object.getOwnPropertyNames(Strophe.Status)[status]+": "+condition),status){case Strophe.Status.CONNECTING:$(document).trigger("connecting.jsxc");break;case Strophe.Status.CONNECTED:jsxc.bid=jsxc.jidToBid(jsxc.xmpp.conn.jid.toLowerCase()),$(document).trigger("connected.jsxc");break;case Strophe.Status.ATTACHED:$(document).trigger("attached.jsxc");break;case Strophe.Status.DISCONNECTED:$(document).trigger("disconnected.jsxc");break;case Strophe.Status.CONNFAIL:$(document).trigger("connfail.jsxc");break;case Strophe.Status.AUTHFAIL:$(document).trigger("authfail.jsxc")}};jsxc.xmpp.conn.caps&&(jsxc.xmpp.conn.caps.node="http://jsxc.org/"),jsxc.changeState(jsxc.CONST.STATE.ESTABLISHING),sid&&rid?(jsxc.debug("Try to attach"),jsxc.debug("SID: "+sid),jsxc.reconnect=!0,jsxc.xmpp.conn.attach(jid,sid,rid,callback)):(jsxc.debug("New connection"),jsxc.xmpp.conn.caps&&jsxc.xmpp.conn._addSysHandler(function(stanza){var from=jsxc.xmpp.conn.domain,c=stanza.querySelector("c"),ver=c.getAttribute("ver"),node=c.getAttribute("node"),_jidNodeIndex=JSON.parse(localStorage.getItem("strophe.caps._jidNodeIndex"))||{};jsxc.xmpp.conn.caps._jidVerIndex[from]=ver,_jidNodeIndex[from]=node,localStorage.setItem("strophe.caps._jidVerIndex",JSON.stringify(jsxc.xmpp.conn.caps._jidVerIndex)),localStorage.setItem("strophe.caps._jidNodeIndex",JSON.stringify(_jidNodeIndex))},Strophe.NS.CAPS),jsxc.xmpp.conn.connect(jid,password||jsxc.options.xmpp.password,callback))},logout:function(complete){if(jsxc.triggeredFromElement="boolean"!=typeof complete||complete,!jsxc.master)return jsxc.storage.removeItem("sid"),!0;if(jsxc.storage.removeUserItem("buddylist"),jsxc.storage.removeUserItem("windowlist"),jsxc.storage.removeUserItem("unreadMsg"),$("body").click(),!jsxc.xmpp.conn||!jsxc.xmpp.conn.authenticated)return!0;$.each(jsxc.storage.getUserItem("otrlist")||{},function(i,val){jsxc.otr.create(val)});var numOtr=Object.keys(jsxc.otr.objects||{}).length+1,disReady=function(){--numOtr<=0&&(jsxc.xmpp.conn.flush(),setTimeout(function(){jsxc.xmpp.conn.disconnect()},600))};return $.each(jsxc.otr.objects||{},function(key,obj){obj.msgstate===OTR.CONST.MSGSTATE_ENCRYPTED?obj.endOtr.call(obj,function(){obj.init.call(obj),jsxc.otr.backup(key),disReady()}):disReady()}),disReady(),!1},connected:function(){if(jsxc.xmpp.conn.pause(),jsxc.xmpp.initNewConnection(),jsxc.xmpp.saveSessionParameter(),jsxc.options.loginForm.triggered)switch(jsxc.options.loginForm.onConnected||"submit"){case"submit":return void jsxc.submitLoginForm();case!1:return}jsxc.gui.dialog.close(),jsxc.xmpp.conn.resume(),jsxc.onMaster(),jsxc.changeState(jsxc.CONST.STATE.READY),$(document).trigger("attached.jsxc")},attached:function(){$("#jsxc_roster").removeClass("jsxc_noConnection"),jsxc.xmpp.conn.addHandler(jsxc.xmpp.onRosterChanged,"jabber:iq:roster","iq","set"),jsxc.xmpp.conn.addHandler(jsxc.xmpp.onChatMessage,null,"message","chat"),jsxc.xmpp.conn.addHandler(jsxc.xmpp.onHeadlineMessage,null,"message","headline"),jsxc.xmpp.conn.addHandler(jsxc.xmpp.onReceived,null,"message"),jsxc.xmpp.conn.addHandler(jsxc.xmpp.onPresence,null,"presence"),jsxc.gui.init();var caps=jsxc.xmpp.conn.caps,domain=jsxc.xmpp.conn.domain;if(caps){var conditionalEnable=function(){};if(jsxc.options.get("carbons").enable&&(conditionalEnable=function(){jsxc.xmpp.conn.caps.hasFeatureByJid(domain,jsxc.CONST.NS.CARBONS)&&jsxc.xmpp.carbons.enable()},$(document).on("caps.strophe",function onCaps(ev,from){from===domain&&(conditionalEnable(),$(document).off("caps.strophe",onCaps))})),"undefined"==typeof caps._knownCapabilities[caps._jidVerIndex[domain]]){var _jidNodeIndex=JSON.parse(localStorage.getItem("strophe.caps._jidNodeIndex"))||{};jsxc.debug("Request server capabilities"),caps._requestCapabilities(jsxc.xmpp.conn.domain,_jidNodeIndex[domain],caps._jidVerIndex[domain])}else conditionalEnable()}if(jsxc.reconnect&&jsxc.storage.getUserItem("buddylist"))jsxc.xmpp.sendPres(),jsxc.restoreCompleted||jsxc.gui.restore();else{$(document).one("cloaded.roster.jsxc",jsxc.xmpp.sendPres),$("#jsxc_roster > p:first").remove();var iq=$iq({type:"get"}).c("query",{xmlns:"jabber:iq:roster"});jsxc.xmpp.conn.sendIQ(iq,jsxc.xmpp.onRoster)}jsxc.xmpp.saveSessionParameter(),jsxc.masterActions(),jsxc.changeState(jsxc.CONST.STATE.READY)},saveSessionParameter:function(){var nomJid=Strophe.getBareJidFromJid(jsxc.xmpp.conn.jid).toLowerCase()+"/"+Strophe.getResourceFromJid(jsxc.xmpp.conn.jid);jsxc.storage.setItem("sid",jsxc.xmpp.conn._proto.sid),jsxc.storage.setItem("jid",nomJid)},initNewConnection:function(){jsxc.storage.removeUserItem("buddylist"),jsxc.storage.removeUserItem("windowlist"),jsxc.storage.removeUserItem("own"),jsxc.storage.removeUserItem("avatar","own"),jsxc.storage.removeUserItem("otrlist"),jsxc.storage.removeUserItem("unreadMsg"),jsxc.storage.removeUserElement("options","RTCPeerConfig")},sendPres:function(){jsxc.xmpp.conn.disco&&(jsxc.xmpp.conn.disco.addIdentity("client","web","JSXC"),jsxc.xmpp.conn.disco.addFeature(Strophe.NS.DISCO_INFO),jsxc.xmpp.conn.disco.addFeature(Strophe.NS.RECEIPTS));var pres=$pres();jsxc.xmpp.conn.caps&&pres.c("c",jsxc.xmpp.conn.caps.generateCapsAttrs()).up();var presState=jsxc.storage.getUserItem("presence")||"online";"online"!==presState&&pres.c("show").t(presState).up();var priority=jsxc.options.get("priority");priority&&"undefined"!=typeof priority[presState]&&0!==parseInt(priority[presState])&&pres.c("priority").t(priority[presState]).up(),jsxc.debug("Send presence",pres.toString()),jsxc.xmpp.conn.send(pres)},disconnected:function(){jsxc.debug("disconnected"),jsxc.storage.removeItem("jid"),jsxc.storage.removeItem("sid"),jsxc.storage.removeItem("rid"),jsxc.storage.removeItem("hidden"),jsxc.storage.removeUserItem("avatar","own"),jsxc.storage.removeUserItem("otrlist"),$(document).off("connected.jsxc",jsxc.xmpp.connected),$(document).off("attached.jsxc",jsxc.xmpp.attached),$(document).off("disconnected.jsxc",jsxc.xmpp.disconnected),$(document).off("connfail.jsxc",jsxc.xmpp.onConnfail),$(document).off("authfail.jsxc",jsxc.xmpp.onAuthFail),jsxc.xmpp.conn=null,$("#jsxc_windowList").remove(),jsxc.triggeredFromElement?($(document).trigger("toggle.roster.jsxc",["hidden",0]),jsxc.gui.roster.ready=!1,$("#jsxc_roster").remove(),jsxc.triggeredFromLogout&&(window.location=jsxc.options.logoutElement.attr("href"))):jsxc.gui.roster.noConnection(),window.clearInterval(jsxc.keepaliveInterval),jsxc.role_allocation=!1,jsxc.master=!1,jsxc.storage.removeItem("alive"),jsxc.changeState(jsxc.CONST.STATE.SUSPEND)},onConnfail:function(ev,condition){jsxc.debug("XMPP connection failed: "+condition),jsxc.options.loginForm.triggered&&jsxc.submitLoginForm()},onAuthFail:function(){if(jsxc.options.loginForm.triggered)switch(jsxc.options.loginForm.onAuthFail||"ask"){case"ask":jsxc.gui.showAuthFail();break;case"submit":jsxc.submitLoginForm();break;case"quiet":case!1:return}},onRoster:function(iq){jsxc.debug("Load roster",iq);var buddies=[];$(iq).find("item").each(function(){var jid=$(this).attr("jid"),name=$(this).attr("name")||jid,bid=jsxc.jidToBid(jid),sub=$(this).attr("subscription");buddies.push(bid),jsxc.storage.removeUserItem("res",bid),jsxc.storage.saveBuddy(bid,{jid:jid,name:name,status:0,sub:sub,res:[],rnd:Math.random()}),jsxc.gui.roster.add(bid)}),0===buddies.length&&jsxc.gui.roster.empty(),jsxc.storage.setUserItem("buddylist",buddies),jsxc.xmpp.bookmarks.load(),jsxc.gui.roster.loaded=!0,jsxc.debug("Roster loaded"),$(document).trigger("cloaded.roster.jsxc"),jsxc.changeUIState(jsxc.CONST.UISTATE.READY)},onRosterChanged:function(iq){var iqSender=$(iq).attr("from"),ownBareJid=Strophe.getBareJidFromJid(jsxc.xmpp.conn.jid);return!(!iqSender||iqSender===ownBareJid)||(jsxc.debug("onRosterChanged",iq),$(iq).find("item").each(function(){var jid=$(this).attr("jid"),name=$(this).attr("name")||jid,bid=jsxc.jidToBid(jid),sub=$(this).attr("subscription");if("remove"===sub)jsxc.gui.roster.purge(bid);else{var bl=jsxc.storage.getUserItem("buddylist");bl.indexOf(bid)<0&&(bl.push(bid),jsxc.storage.setUserItem("buddylist",bl));var temp=jsxc.storage.saveBuddy(bid,{jid:jid,name:name,sub:sub});"updated"===temp?(jsxc.gui.update(bid),jsxc.gui.roster.reorder(bid)):jsxc.gui.roster.add(bid)}if("from"===sub||"both"===sub){var notice,notices=jsxc.storage.getUserItem("notices"),noticeKey=null;for(noticeKey in notices)notice=notices[noticeKey],"gui.showApproveDialog"===notice.fnName&¬ice.fnParams[0]===jid&&(jsxc.debug("Remove notice with key "+noticeKey),jsxc.notice.remove(noticeKey))}}),jsxc.storage.getUserItem("buddylist")&&0!==jsxc.storage.getUserItem("buddylist").length?$("#jsxc_roster > p:first").remove():jsxc.gui.roster.empty(),!0)},onPresence:function(presence){jsxc.debug("onPresence",presence);var ptype=$(presence).attr("type"),from=$(presence).attr("from"),jid=Strophe.getBareJidFromJid(from).toLowerCase(),r=Strophe.getResourceFromJid(from),bid=jsxc.jidToBid(jid),data=jsxc.storage.getUserItem("buddy",bid)||{},res=jsxc.storage.getUserItem("res",bid)||{},status=null,xVCard=$(presence).find('x[xmlns="vcard-temp:x:update"]');if(jid===Strophe.getBareJidFromJid(jsxc.storage.getItem("jid")))return!0;if("error"===ptype){$(document).trigger("error.presence.jsxc",[from,presence]);var error=$(presence).find("error");return jsxc.error("[XMPP] "+error.attr("code")+" "+error.find(">:first-child").prop("tagName")),!0}if("subscribe"===ptype){var bl=jsxc.storage.getUserItem("buddylist");return bl.indexOf(bid)>-1?(jsxc.debug("Auto approve contact request, because he is already in our contact list."),jsxc.xmpp.resFriendReq(jid,!0),"to"!==data.sub&&jsxc.xmpp.addBuddy(jid,data.name),!0):(jsxc.storage.setUserItem("friendReq",{jid:jid,approve:-1}),jsxc.notice.add({msg:$.t("Friendship_request"),description:$.t("from")+" "+jid,type:"contact"},"gui.showApproveDialog",[jid]),!0)}if("unavailable"===ptype||"unsubscribed"===ptype)status=jsxc.CONST.STATUS.indexOf("offline");else{var show=$(presence).find("show").text();status=""===show?jsxc.CONST.STATUS.indexOf("online"):jsxc.CONST.STATUS.indexOf(show)}0===status?delete res[r]:r&&(res[r]=status);var maxVal=[],max=0,prop=null;for(prop in res)res.hasOwnProperty(prop)&&max<=res[prop]&&(max!==res[prop]&&(maxVal=[],max=res[prop]),maxVal.push(prop));if(0===data.status&&max>0&&jsxc.notification.notify({title:data.name,msg:$.t("has_come_online"),source:bid}),"groupchat"===data.type?data.status=status:data.status=max,data.res=maxVal,data.jid=jid,xVCard.length>0&&"groupchat"!==data.type){var photo=xVCard.find("photo");photo.length>0&&photo.text()!==data.avatar&&(jsxc.storage.removeUserItem("avatar",data.avatar),data.avatar=photo.text())}return jsxc.gui.window.get(bid).length>0&&jsxc.gui.window.get(bid).data("jid",jid),jsxc.storage.setUserItem("buddy",bid,data),jsxc.storage.setUserItem("res",bid,res),jsxc.debug("Presence ("+from+"): "+jsxc.CONST.STATUS[status]),jsxc.gui.update(bid),jsxc.gui.roster.reorder(bid),$(document).trigger("presence.jsxc",[from,status,presence]),!0},onChatMessage:function(stanza){var message,carbon,forwarded=$(stanza).find('forwarded[xmlns="'+jsxc.CONST.NS.FORWARD+'"]'),originalSender=$(stanza).attr("from");if(forwarded.length>0){if(message=forwarded.find("> message"),forwarded=!0,carbon=$(stanza).find('> [xmlns="'+jsxc.CONST.NS.CARBONS+'"]'),0===carbon.length)carbon=!1;else if(originalSender!==Strophe.getBareJidFromJid(jsxc.xmpp.conn.jid))return!0;jsxc.debug("Incoming forwarded message",message)}else message=stanza,forwarded=!1,carbon=!1,jsxc.debug("Incoming message",message);var body=$(message).find("body:first").text(),htmlBody=$(message).find('body[xmlns="'+Strophe.NS.XHTML+'"]');if(!body||body.match(/\?OTR/i)&&forwarded)return!0;var bid,type=$(message).attr("type"),from=$(message).attr("from"),mid=$(message).attr("id"),delay=$(message).find('delay[xmlns="urn:xmpp:delay"]'),stamp=delay.length>0?new Date(delay.attr("stamp")):new Date;if(stamp=stamp.getTime(),carbon){var direction="sent"===carbon.prop("tagName")?jsxc.Message.OUT:jsxc.Message.IN;return bid=jsxc.jidToBid("out"===direction?$(message).attr("to"):from),jsxc.gui.window.postMessage({bid:bid,direction:direction,msg:body,encrypted:!1,forwarded:forwarded,stamp:stamp}),!0}forwarded&&(body=from+" "+$.t("to")+" "+$(stanza).attr("to")+'"'+body+'"',from=$(stanza).attr("from"));var jid=Strophe.getBareJidFromJid(from);bid=jsxc.jidToBid(jid);var data=jsxc.storage.getUserItem("buddy",bid),request=$(message).find("request[xmlns='urn:xmpp:receipts']");if(null===data){var chat=jsxc.storage.getUserItem("chat",bid)||[];0===chat.length&&jsxc.notice.add({msg:$.t("Unknown_sender"),description:$.t("You_received_a_message_from_an_unknown_sender")+" ("+bid+")."},"gui.showUnknownSender",[bid]);var msg=jsxc.removeHTML(body);return msg=jsxc.escapeHTML(msg),jsxc.storage.saveMessage(bid,"in",msg,!1,forwarded,stamp),!0}var win=jsxc.gui.window.init(bid);"chat"===type&&(win.data("jid",from),jsxc.storage.updateUserItem("buddy",bid,{jid:from})),$(document).trigger("message.jsxc",[from,body]),jsxc.master&&!jsxc.otr.objects[bid]&&jsxc.otr.create(bid),forwarded||null===mid||!request.length||null===data||"both"!==data.sub&&"from"!==data.sub||"chat"!==type||jsxc.xmpp.conn.send($msg({to:from}).c("received",{xmlns:"urn:xmpp:receipts",id:mid}));var attachment;if(1===htmlBody.length){var httpUploadElement=htmlBody.find("a[data-type][data-name][data-size]");1===httpUploadElement.length&&(attachment={type:httpUploadElement.attr("data-type"),name:httpUploadElement.attr("data-name"),size:httpUploadElement.attr("data-size")},httpUploadElement.attr("data-thumbnail")&&httpUploadElement.attr("data-thumbnail").match(/^\s*data:[a-z]+\/[a-z0-9-+.*]+;base64,[a-z0-9=+\/]+$/i)&&(attachment.thumbnail=httpUploadElement.attr("data-thumbnail")),httpUploadElement.attr("href")&&httpUploadElement.attr("href").match(/^https:\/\//)&&(attachment.data=httpUploadElement.attr("href"),body=null),attachment.type.match(/^[a-z]+\/[a-z0-9-+.*]+$/i)&&attachment.name.match(/^[\s\w.,-]+$/i)&&attachment.size.match(/^\d+$/i)||(attachment=void 0,jsxc.warn("Invalid file type, name or size.")))}return jsxc.otr.objects.hasOwnProperty(bid)&&body?jsxc.otr.objects[bid].receiveMsg(body,{stamp:stamp,forwarded:forwarded,attachment:attachment}):jsxc.gui.window.postMessage({bid:bid,direction:jsxc.Message.IN,msg:body,encrypted:!1,forwarded:forwarded,stamp:stamp,attachment:attachment}),!0},onHeadlineMessage:function(stanza){stanza=$(stanza);var from=stanza.attr("from"),domain=Strophe.getDomainFromJid(from);if(domain!==from){if(!jsxc.storage.getUserItem("buddy",jsxc.jidToBid(from)))return!0}else if(domain!==Strophe.getDomainFromJid(jsxc.xmpp.conn.jid))return!0;var subject=stanza.find("subject:first").text()||$.t("Notification"),body=stanza.find("body:first").text();return jsxc.notice.add({msg:subject,description:body,type:domain===from?"announcement":null},"gui.showNotification",[subject,body,from]),!0},onRidChange:function(rid){jsxc.storage.setItem("rid",rid)},resFriendReq:function(from,approve){jsxc.master?(jsxc.xmpp.conn.send($pres({to:from,type:approve?"subscribed":"unsubscribed"})),jsxc.storage.removeUserItem("friendReq"),jsxc.gui.dialog.close()):jsxc.storage.updateUserItem("friendReq","approve",approve)},addBuddy:function(username,alias){var bid=jsxc.jidToBid(username);if(jsxc.master){var iq=$iq({type:"set"}).c("query",{xmlns:"jabber:iq:roster"}).c("item",{jid:username,name:alias||""});jsxc.xmpp.conn.sendIQ(iq),jsxc.xmpp.conn.send($pres({to:username,type:"subscribe"})),jsxc.storage.removeUserItem("add_"+bid)}else jsxc.storage.setUserItem("add_"+bid,{username:username,alias:alias||null})},removeBuddy:function(jid){var bid=jsxc.jidToBid(jid),iq=$iq({type:"set"}).c("query",{xmlns:"jabber:iq:roster"}).c("item",{jid:Strophe.getBareJidFromJid(jid),subscription:"remove"});jsxc.xmpp.conn.sendIQ(iq),jsxc.gui.roster.purge(bid)},onReceived:function(stanza){var received=$(stanza).find("received[xmlns='urn:xmpp:receipts']");if(received.length){var receivedId=received.attr("id"),message=new jsxc.Message(receivedId);message.received()}return!0},sendMessage:function(message){var bid=message.bid,msg=message.htmlMsg,mucRoomNames=jsxc.xmpp.conn.muc&&jsxc.xmpp.conn.muc.roomNames?jsxc.xmpp.conn.muc.roomNames:[],isMucBid=mucRoomNames.indexOf(bid)>=0;jsxc.otr.objects.hasOwnProperty(bid)&&!isMucBid?jsxc.otr.objects[bid].sendMsg(msg,message):jsxc.xmpp._sendMessage(jsxc.gui.window.get(bid).data("jid"),msg,message)},_sendMessage:function(jid,msg,message){var data=jsxc.storage.getUserItem("buddy",jsxc.jidToBid(jid))||{},isBar=Strophe.getBareJidFromJid(jid)===jid,type=data.type||"chat";message=message||{};var xmlMsg=$msg({to:jid,type:type,id:message._uid});if(message.type===jsxc.Message.HTML){xmlMsg.c("html",{xmlns:Strophe.NS.XHTML_IM});var body=Strophe.xmlElement("body",{xmlns:Strophe.NS.XHTML});body.innerHTML=msg,xmlMsg.node.appendChild(body)}else xmlMsg.c("body").t(msg);jsxc.xmpp.carbons.enabled&&msg.match(/^\?OTR/)&&xmlMsg.up().c("private",{xmlns:jsxc.CONST.NS.CARBONS}),"chat"===type&&(isBar||jsxc.xmpp.conn.caps.hasFeatureByJid(jid,Strophe.NS.RECEIPTS))&&xmlMsg.up().c("request",{xmlns:"urn:xmpp:receipts"}),jsxc.xmpp.conn.chatstates&&!jsxc.xmpp.chatState.isDisabled()&&xmlMsg.up().c("active",{xmlns:Strophe.NS.CHATSTATES}),jsxc.xmpp.conn.send(xmlMsg)},loadVcard:function(bid,cb,error_cb){jsxc.master?jsxc.xmpp.conn.vcard.get(cb,bid,error_cb):(jsxc.storage.setUserItem("vcard",bid,"request:"+(new Date).getTime()),$(document).one("loaded.vcard.jsxc",function(ev,result){result&&"success"===result.state?cb($(result.data).get(0)):error_cb()}))},getCapabilitiesByJid:function(jid){ -if(jsxc.xmpp.conn)return jsxc.xmpp.conn.caps.getCapabilitiesByJid(jid);var jidVerIndex=JSON.parse(localStorage.getItem("strophe.caps._jidVerIndex"))||{},knownCapabilities=JSON.parse(localStorage.getItem("strophe.caps._knownCapabilities"))||{};return jidVerIndex[jid]?knownCapabilities[jidVerIndex[jid]]:null},hasFeatureByJid:function(jid,feature,cb){var conn=jsxc.xmpp.conn;if(cb=cb||function(){},!feature)return!1;$.isArray(feature)||(feature=$.makeArray(feature));var check=function(knownCapabilities){if(!knownCapabilities)return null;var i;for(i=0;i=0?success_cb(bid+"/"+res):fileCapableRes.indexOf(res)<0&&jsxc.gui.window.selectResource(bid,$.t("Your_contact_uses_multiple_clients_"),function(data){"unavailable"===data.status?(jsxc.gui.window.hideOverlay(bid),"function"==typeof error_cb&&error_cb()):"selected"===data.status&&success_cb(bid+"/"+data.result)},fileCapableRes)},jsxc.fileTransfer.showFileSelection=function(jid){var bid=jsxc.jidToBid(jid),msg=$('
      ');msg.addClass("jsxc_chatmessage"),jsxc.gui.window.showOverlay(bid,msg,!0),msg.find("label").click(),msg.find('[type="file"]').change(function(ev){var file=ev.target.files[0];file&&jsxc.fileTransfer.fileSelected(jid,msg,file)})},jsxc.fileTransfer.fileSelected=function(jid,msg,file){var bid=jsxc.jidToBid(jid);if("webrtc"!==file.transportMethod&&jsxc.xmpp.httpUpload.ready&&file.size>jsxc.options.get("httpUpload").maxSize)return jsxc.debug("File too large for http upload."),file.transportMethod="webrtc",void jsxc.fileTransfer.selectResource(bid,function(jid){jsxc.fileTransfer.fileSelected(jid,msg,file)},function(){var maxSize=jsxc.fileTransfer.formatByte(jsxc.options.get("httpUpload").maxSize),fileSize=jsxc.fileTransfer.formatByte(file.size);jsxc.gui.window.postMessage({bid:bid,direction:jsxc.Message.SYS,msg:$.t("File_too_large")+" ("+fileSize+" > "+maxSize+")"}),jsxc.gui.window.hideOverlay(bid)});!jsxc.xmpp.httpUpload.ready&&Strophe.getResourceFromJid(jid)&&(file.transportMethod="webrtc");var attachment=$("
      ");if(attachment.addClass("jsxc_attachment"),attachment.addClass("jsxc_"+file.type.replace(/\//,"-")),attachment.addClass("jsxc_"+file.type.replace(/^([^\/]+)\/.*/,"$1")),msg.empty().append(attachment),FileReader&&file.type.match(/^image\//)){var img=$('preview').attr("title",file.name);img.attr("src",jsxc.options.get("root")+"/img/loading.gif"),img.appendTo(attachment);var reader=new FileReader;reader.onload=function(){img.attr("src",reader.result)},reader.readAsDataURL(file)}else attachment.text(file.name+" ("+file.size+" byte)");$("
    • "),$("#jsxc_dialog ul.jsxc_vCard").append("
    • "+$.t("Client")+": "+client+"
    • "),$("#jsxc_dialog ul.jsxc_vCard").append("
    • "+$.t("Status")+": "+$.t(jsxc.CONST.STATUS[status])+"
    • ")}}var printProp=function(el,depth){var content="";if(el.each(function(){var item=$(this),children=$(this).children();content+="
    • ";var prop=$.t(item[0].tagName);" "!==prop&&(content+=""+prop+": "),"PHOTO"===item[0].tagName||(children.length>0?(content+="
        ",content+=printProp(children,depth+1),content+="
      "):""!==item.text()&&(content+=jsxc.escapeHTML(item.text()))),content+="
    • ",0===depth&&$("#jsxc_dialog ul.jsxc_vCard").length>0&&($("#jsxc_dialog ul.jsxc_vCard li.jsxc_sep:first").length>0?$("#jsxc_dialog ul.jsxc_vCard li.jsxc_sep:first").before(content):$("#jsxc_dialog ul.jsxc_vCard").append(content),content="")}),depth>0)return content},failedToLoad=function(){if(0!==$("#jsxc_dialog ul.jsxc_vCard").length){$("#jsxc_dialog p").remove();var content="

      ";content+=$.t("Sorry_your_buddy_doesnt_provide_any_information"),content+="

      ",$("#jsxc_dialog").append(content)}};jsxc.xmpp.loadVcard(bid,function(stanza){if(0!==$("#jsxc_dialog ul.jsxc_vCard").length){$("#jsxc_dialog p").remove();var photo=$(stanza).find("vCard > PHOTO");if(photo.length>0){var img=photo.find("BINVAL").text(),type=photo.find("TYPE").text(),src="data:"+type+";base64,"+img;photo.find("EXTVAL").length>0&&(src=photo.find("EXTVAL").text()),src=src.replace(/[\t\r\n\f]/gi,"");var img_el=$('avatar');img_el.attr("src",src),$("#jsxc_dialog h3").before(img_el)}return 0===$(stanza).find("vCard").length||1===$(stanza).find("vcard > *").length&&1===photo.length?void failedToLoad():void printProp($(stanza).find("vcard > *"),0)}},failedToLoad)},showSettings:function(){jsxc.gui.dialog.open(jsxc.gui.template.get("settings")),"false"!==jsxc.options.get("xmpp").overwrite&&jsxc.options.get("xmpp").overwrite!==!1||$(".jsxc_fieldsetXmpp").parent().hide(),$("#jsxc_dialog form").each(function(){var self=$(this);self.find('input[type!="submit"]').each(function(){var id=this.id.split("-"),prop=id[0],key=id[1],type=this.type,data=jsxc.options.get(prop);data&&"undefined"!=typeof data[key]&&("checkbox"===type?"false"!==data[key]&&data[key]!==!1&&(this.checked="checked"):$(this).val(data[key]))})}),$("#jsxc_dialog form").submit(function(){var self=$(this),data={};self.find('input[type!="submit"]').each(function(){var val,id=this.id.split("-"),prop=id[0],key=id[1],type=this.type;val="checkbox"===type?this.checked:$(this).val(),data[prop]||(data[prop]={}),data[prop][key]=val}),$.each(data,function(key,val){jsxc.options.set(key,val)});var cb=function(success){"string"==typeof self.attr("data-onsubmit")&&jsxc.exec(self.attr("data-onsubmit"),[success]),setTimeout(function(){success?self.find('button[type="submit"]').switchClass("btn-primary","btn-success"):self.find('button[type="submit"]').switchClass("btn-primary","btn-danger"),setTimeout(function(){self.find('button[type="submit"]').switchClass("btn-danger btn-success","btn-primary")},2e3)},200)};return jsxc.options.saveSettinsPermanent.call(this,data,cb),!1})},showRequestNotification:function(){jsxc.switchEvents({"notificationready.jsxc":function(){jsxc.gui.dialog.close(),jsxc.notification.init(),jsxc.storage.setUserItem("notification",1)},"notificationfailure.jsxc":function(){jsxc.gui.dialog.close(),jsxc.options.notification=!1,jsxc.storage.setUserItem("notification",0)}}),jsxc.gui.showConfirmDialog($.t("Should_we_notify_you_"),function(){jsxc.gui.dialog.open(jsxc.gui.template.get("pleaseAccept"),{noClose:!0}),jsxc.notification.requestPermission()},function(){$(document).trigger("notificationfailure.jsxc")})},showUnknownSender:function(bid){var confirmationText=$.t("You_received_a_message_from_an_unknown_sender_",{sender:bid});jsxc.gui.showConfirmDialog(confirmationText,function(){jsxc.gui.dialog.close(),jsxc.storage.saveBuddy(bid,{jid:bid,name:bid,status:0,sub:"none",res:[]}),jsxc.gui.window.open(bid)},function(){jsxc.storage.removeUserItem("chat",bid)})},showSelectionDialog:function(header,msg,primary,option,primaryLabel,optionLabel){var opt;opt=1===arguments.length&&"object"==typeof header&&null!==header?header:{header:header,msg:msg,primary:{label:primaryLabel,cb:primary},option:{label:optionLabel,cb:option}};var dialog=jsxc.gui.dialog.open(jsxc.gui.template.get("selectionDialog"),{noClose:!0});opt.header?dialog.find("h3").text(opt.header):dialog.find("h3").hide(),opt.msg?dialog.find("p").text(opt.msg):dialog.find("p").hide(),opt.primary&&opt.primary.label&&dialog.find(".btn-primary").text(opt.primary.label),opt.primary&&opt.option.label&&dialog.find(".btn-default").text(opt.option.label),opt.primary&&opt.primary.cb&&dialog.find(".btn-primary").click(opt.primary.cb),opt.primary&&opt.option.cb&&dialog.find(".btn-primary").click(opt.option.cb)},showNotification:function(subject,body,from){var dialog=jsxc.gui.dialog.open(jsxc.gui.template.get("notification"));dialog.find("h3").text(subject),dialog.find(".jsxc_msg").text(body),from?dialog.find(".jsxc_meta").text($.t("from")+" "+from):dialog.find(".jsxc_meta").hide()},changePresence:function(pres,external){external!==!0&&jsxc.storage.setUserItem("presence",pres),jsxc.master&&jsxc.xmpp.sendPres(),$("#jsxc_presence > span").text($("#jsxc_presence .jsxc_inner ul .jsxc_"+pres).text()),jsxc.gui.updatePresence("own",pres)},updatePresence:function(bid,pres){"own"===bid&&("dnd"===pres?($("#jsxc_menu .jsxc_muteNotification").addClass("jsxc_disabled"),jsxc.notification.muteSound(!0)):($("#jsxc_menu .jsxc_muteNotification").removeClass("jsxc_disabled"),jsxc.options.get("muteNotification")||jsxc.notification.unmuteSound(!0))),$('[data-bid="'+bid+'"]').each(function(){var el=$(this);el.attr("data-status",pres),el.find(".jsxc_avatar").length>0&&(el=el.find(".jsxc_avatar")),el.removeClass("jsxc_"+jsxc.CONST.STATUS.join(" jsxc_")).addClass("jsxc_"+pres)})},unreadMsg:function(bid){var winData=jsxc.storage.getUserItem("window",bid)||{},count=winData&&winData.unread||0;count=count===!0?1:count+1,winData.unread=count,jsxc.storage.setUserItem("window",bid,winData);var total=jsxc.storage.getUserItem("unreadMsg")||0;total++,jsxc.storage.setUserItem("unreadMsg",total),jsxc.gui.favicon&&jsxc.gui.favicon.badge(total),jsxc.gui._unreadMsg(bid,count)},_unreadMsg:function(bid,count){var win=jsxc.gui.window.get(bid);if("number"!=typeof count){var winData=jsxc.storage.getUserItem("window",bid);count=winData&&winData.unread||1,count=count===!0?1:count}var el=jsxc.gui.roster.getItem(bid).add(win);el.addClass("jsxc_unreadMsg"),el.find(".jsxc_unread").text(count)},readMsg:function(bid){var win=jsxc.gui.window.get(bid),winData=jsxc.storage.getUserItem("window",bid),count=winData&&winData.unread||0;count=count===!0?0:count;var el=jsxc.gui.roster.getItem(bid).add(win);if(el.removeClass("jsxc_unreadMsg"),el.find(".jsxc_unread").text(0),count>0){var total=jsxc.storage.getUserItem("unreadMsg")||0;total-=count,jsxc.storage.setUserItem("unreadMsg",total),jsxc.gui.favicon&&jsxc.gui.favicon.badge(total),jsxc.storage.updateUserItem("window",bid,"unread",0)}},detectUriScheme:function(container){container=$(container?container:"body"),container.find("a[href^='xmpp:']").each(function(){var action,element=$(this),href=element.attr("href").replace(/^xmpp:/,""),jid=href.split("?")[0],params={};if(href.indexOf("?")<0)action="message";else{var pairs=href.substring(href.indexOf("?")+1).split(";");action=pairs[0];var i,key,value;for(i=1;i0?pairs[i].substring(pairs[i].indexOf("=")+1):null,params[decodeURIComponent(key)]=decodeURIComponent(value)}"function"==typeof jsxc.gui.queryActions[action]&&(element.addClass("jsxc_uriScheme jsxc_uriScheme_"+action),element.off("click").click(function(ev){return ev.stopPropagation(),jsxc.gui.queryActions[action].call(jsxc,jid,params),!1}))})},detectEmail:function(container){container=$(container?container:"body"),container.find('a[href^="mailto:"],a[href^="xmpp:"]').each(function(){var spot=$("X").addClass("jsxc_spot"),href=$(this).attr("href").replace(/^ *(mailto|xmpp):/,"").trim();if(""!==href&&href!==Strophe.getBareJidFromJid(jsxc.storage.getItem("jid"))){var bid=jsxc.jidToBid(href),self=$(this),s=self.prev();s.hasClass("jsxc_spot")||(s=spot.clone().attr("data-bid",bid),self.before(s)),s.off("click"),jsxc.storage.getUserItem("buddy",bid)?(jsxc.gui.update(bid),s.click(function(){return jsxc.gui.window.open(bid),!1})):s.click(function(){return jsxc.gui.showContactDialog(href),!1})}})},avatarPlaceholder:function(el,seed,text){text=text||seed;var options=jsxc.options.get("avatarplaceholder")||{},hash=jsxc.hashStr(seed),hue=Math.abs(hash)%360,saturation=options.saturation||90,lightness=options.lightness||65;el.css({"background-color":"hsl("+hue+", "+saturation+"%, "+lightness+"%)",color:"#fff","font-weight":"bold","text-align":"center","line-height":el.height()+"px","font-size":.6*el.height()+"px"}),"string"==typeof text&&text.length>0&&el.text(text[0].toUpperCase())},shortnameToImage:function(str){str=str.replace(jsxc.gui.regShortNames,function(shortname){if(!("undefined"!=typeof shortname&&""!==shortname&&(shortname in jsxc.gui.emoticonList.emojione||shortname in jsxc.gui.emoticonList.core)))return shortname;var src,filename;jsxc.gui.emoticonList.core[shortname]?(filename=jsxc.gui.emoticonList.core[shortname][jsxc.gui.emoticonList.core[shortname].length-1].replace(/^:([^:]+):$/,"$1"),src=jsxc.options.root+"/img/emotions/"+filename+".svg"):jsxc.gui.emoticonList.emojione[shortname]&&(filename=jsxc.gui.emoticonList.emojione[shortname].fname,src=jsxc.options.root+"/lib/emojione/assets/svg/"+filename+".svg");var div=$("
      ");return div.addClass("jsxc_emoticon"),div.css("background-image","url("+src+")"),div.attr("title",shortname),div.prop("outerHTML")});var obj=$("
      "+str+"
      ");return 1===obj.find(".jsxc_emoticon").length&&0===obj.text().replace(/ /,"").length&&1===obj.find("*").length&&(obj.find(".jsxc_emoticon").addClass("jsxc_large"),str=obj.prop("outerHTML")),str},restore:function(){jsxc.restoreRoster(),jsxc.restoreWindows(),jsxc.restoreCompleted=!0,$(document).trigger("restoreCompleted.jsxc"),jsxc.changeUIState(jsxc.CONST.UISTATE.READY)}},jsxc.gui.roster={ready:!1,loaded:!1,init:function(){$(jsxc.options.rosterAppend+":first").append($(jsxc.gui.template.get("roster"))),jsxc.options.get("hideOffline")&&($("#jsxc_menu .jsxc_hideOffline").text($.t("Show_offline")),$("#jsxc_buddylist").addClass("jsxc_hideOffline")),$("#jsxc_menu .jsxc_settings").click(function(){jsxc.gui.showSettings()}),$("#jsxc_menu .jsxc_hideOffline").click(function(){var hideOffline=!jsxc.options.get("hideOffline");hideOffline?$("#jsxc_buddylist").addClass("jsxc_hideOffline"):$("#jsxc_buddylist").removeClass("jsxc_hideOffline"), -$(this).text(hideOffline?$.t("Show_offline"):$.t("Hide_offline")),jsxc.options.set("hideOffline",hideOffline)}),jsxc.options.get("muteNotification")&&jsxc.notification.muteSound(),$("#jsxc_menu .jsxc_muteNotification").click(function(){if("dnd"!==jsxc.storage.getUserItem("presence")){var mute=!jsxc.options.get("muteNotification");mute?jsxc.notification.muteSound():jsxc.notification.unmuteSound()}}),$("#jsxc_roster .jsxc_addBuddy").click(function(){jsxc.gui.showContactDialog()}),$("#jsxc_roster .jsxc_onlineHelp").click(function(){window.open(jsxc.options.onlineHelp,"onlineHelp")}),$("#jsxc_roster .jsxc_about").click(function(){jsxc.gui.showAboutDialog()}),$("#jsxc_toggleRoster").click(function(){jsxc.gui.roster.toggle()}),$("#jsxc_presence li").click(function(){var self=$(this),pres=self.data("pres");"offline"===pres?jsxc.xmpp.logout(!1):jsxc.gui.changePresence(pres)}),$("#jsxc_buddylist").slimScroll({distance:"3px",height:$("#jsxc_roster").height()-31+"px",width:$("#jsxc_buddylist").width()+"px",color:"#fff",opacity:"0.5"}),$("#jsxc_roster > .jsxc_bottom > div").each(function(){jsxc.gui.toggleList.call($(this))});var rosterState=jsxc.storage.getUserItem("roster")||(jsxc.options.get("loginForm").startMinimized?"hidden":"shown");$("#jsxc_roster").addClass("jsxc_state_"+rosterState),$("#jsxc_windowList").addClass("jsxc_roster_"+rosterState);var pres=jsxc.storage.getUserItem("presence")||"online";$("#jsxc_presence > span").text($("#jsxc_presence .jsxc_"+pres).text()),jsxc.gui.updatePresence("own",pres),jsxc.gui.tooltip("#jsxc_roster"),jsxc.notice.load(),jsxc.gui.roster.ready=!0,$(document).trigger("ready.roster.jsxc")},add:function(bid){var data=jsxc.storage.getUserItem("buddy",bid),bud=jsxc.gui.buddyTemplate.clone().attr("data-bid",bid).attr("data-type",data.type||"chat");$("#jsxc_roster > p").remove(),jsxc.gui.roster.insert(bid,bud),bud.click(function(){jsxc.gui.window.open(bid)}),bud.find(".jsxc_msg").click(function(){return jsxc.gui.window.open(bid),!1}),bud.find(".jsxc_rename").click(function(){return jsxc.gui.roster.rename(bid),!1}),"groupchat"!==data.type&&bud.find(".jsxc_delete").click(function(){return jsxc.gui.showRemoveDialog(bid),!1});var expandClick=function(){return bud.trigger("extra.jsxc"),$("body").click(),bud.find(".jsxc_menu").hasClass("jsxc_open")||(bud.find(".jsxc_menu").addClass("jsxc_open"),$("body").one("click",function(){bud.find(".jsxc_menu").removeClass("jsxc_open")})),!1};bud.find(".jsxc_more").click(expandClick),bud.find(".jsxc_vcard").click(function(){return jsxc.gui.showVcard(data.jid),!1}),jsxc.gui.update(bid),$("#jsxc_buddylist").slimScroll({scrollTo:"0px"});for(var history=jsxc.storage.getUserItem("history",bid)||[],i=0;history.length>i;){var message=new jsxc.Message(history[i]);if(message.direction!==jsxc.Message.SYS){$('[data-bid="'+bid+'"]').find(".jsxc_lastmsg .jsxc_text").html(message.msg);break}i++}$(document).trigger("add.roster.jsxc",[bid,data,bud])},getItem:function(bid){return $("#jsxc_buddylist > li[data-bid='"+bid+"']")},insert:function(bid,li){var data=jsxc.storage.getUserItem("buddy",bid),listElements=$("#jsxc_buddylist > li"),insert=!1;data.name||(data.name=bid);var status="both"===data.sub?data.status:-1;listElements.each(function(){var thisStatus="both"===$(this).data("sub")?$(this).data("status"):-1;if($(this).data("name").toLowerCase()>data.name.toLowerCase()&&thisStatus===status||thisStatus');$("body").click(),options.hide(),name=name.replaceWith(input),input.val(name.text()),input.keypress(function(ev){13===ev.which&&(options.css("display",""),input.replaceWith(name),jsxc.gui.roster._rename(bid,$(this).val()),$("html").off("click"))}),input.click(function(){return!1}),$("html").one("click",function(){options.css("display",""),input.replaceWith(name),jsxc.gui.roster._rename(bid,input.val())})},_rename:function(bid,newname){if(jsxc.master){var d=jsxc.storage.getUserItem("buddy",bid)||{};if("chat"===d.type){var iq=$iq({type:"set"}).c("query",{xmlns:"jabber:iq:roster"}).c("item",{jid:Strophe.getBareJidFromJid(d.jid),name:newname});jsxc.xmpp.conn.sendIQ(iq)}else"groupchat"===d.type&&jsxc.xmpp.bookmarks.add(bid,newname,d.nickname,d.autojoin)}jsxc.storage.updateUserItem("buddy",bid,"name",newname),jsxc.gui.update(bid)},toggle:function(state){var duration,roster=$("#jsxc_roster"),wl=$("#jsxc_windowList");return state||(state=jsxc.storage.getUserItem("roster")===jsxc.CONST.HIDDEN?jsxc.CONST.SHOWN:jsxc.CONST.HIDDEN),"shown"===state&&jsxc.isExtraSmallDevice()&&jsxc.gui.window.hide(),jsxc.storage.setUserItem("roster",state),roster.removeClass("jsxc_state_hidden jsxc_state_shown").addClass("jsxc_state_"+state),wl.removeClass("jsxc_roster_hidden jsxc_roster_shown").addClass("jsxc_roster_"+state),duration=1e3*parseFloat(roster.css("transitionDuration")||0),setTimeout(function(){jsxc.gui.updateWindowListSB()},duration),$(document).trigger("toggle.roster.jsxc",[state,duration]),duration},noConnection:function(){$("#jsxc_roster").addClass("jsxc_noConnection"),$("#jsxc_buddylist").empty(),$("#jsxc_roster").append($("

      "+$.t("no_connection")+"

      ").append(" "+$.t("relogin")+"").click(function(){jsxc.gui.showLoginBox()}))},empty:function(){var text=$("

      "+$.t("Your_roster_is_empty_add_")+"

      "),link=text.find("a");link.click(function(){jsxc.gui.showContactDialog()}),text.append(link),text.append("."),$("#jsxc_roster").prepend(text)}},jsxc.gui.dialog={open:function(data,o){var opt=$.extend({name:""},o),src=$('
      ').append(data);return $.magnificPopup.open({items:{src:src},type:"inline",modal:opt.noClose,callbacks:{beforeClose:function(){$(document).trigger("cleanup.dialog.jsxc")},afterClose:function(){$(document).trigger("close.dialog.jsxc")},open:function(){$("#jsxc_dialog .jsxc_close").click(function(ev){ev.preventDefault(),jsxc.gui.dialog.close()}),$("#jsxc_dialog form").each(function(){var form=$(this);form.find("button[data-jsxc-loading-text]").each(function(){var btn=$(this);btn.on("btnloading.jsxc",function(){btn.prop("disabled")||(btn.prop("disabled",!0),btn.data("jsxc_value",btn.text()),btn.text(btn.attr("data-jsxc-loading-text")))}),btn.on("btnfinished.jsxc",function(){btn.prop("disabled")&&(btn.prop("disabled",!1),btn.text(btn.data("jsxc_value")))})})}),jsxc.gui.dialog.resize(),$(document).trigger("complete.dialog.jsxc")}}}),$("#jsxc_dialog")},close:function(name){jsxc.debug("close dialog"),"string"==typeof name&&name.length>0&&!jsxc.el_exists("#jsxc_dialog[data-name="+name+"]")||$.magnificPopup.close()},resize:function(){}},jsxc.gui.window={init:function(bid){function resizeTextarea(){$(this).data("originalHeight")||$(this).data("originalHeight",$(this).outerHeight()),$(this).outerHeight()0)return jsxc.gui.window.get(bid);var win=jsxc.gui.windowTemplate.clone().attr("data-bid",bid).appendTo("#jsxc_windowList > ul"),data=jsxc.storage.getUserItem("buddy",bid);win.data("jid",data.jid);var expandClick=function(){return win.trigger("extra.jsxc"),$("body").click(),win.find(".jsxc_menu").hasClass("jsxc_open")||(win.find(".jsxc_menu").addClass("jsxc_open"),$("body").one("click",function(){win.find(".jsxc_menu").removeClass("jsxc_open")})),!1};win.find(".jsxc_more").click(expandClick),win.find(".jsxc_menu").click(function(){$("body").click()}),win.find(".jsxc_verification").click(function(){jsxc.gui.showVerification(bid)}),win.find(".jsxc_fingerprints").click(function(){jsxc.gui.showFingerprints(bid)}),win.find(".jsxc_transfer").click(function(){jsxc.otr.toggleTransfer(bid)}),win.find(".jsxc_bar").click(function(){jsxc.gui.window.toggle(bid)}),win.find(".jsxc_close").click(function(){jsxc.gui.window.close(bid)}),win.find(".jsxc_clear").click(function(){jsxc.gui.window.clear(bid)}),win.find(".jsxc_sendFile").click(function(){$("body").click(),jsxc.gui.window.sendFile(bid)}),win.find(".jsxc_tools").click(function(){return!1});var textinputBlurTimeout;if(win.find(".jsxc_textinput").keyup(function(ev){var body=$(this).val();13!==ev.which&&jsxc.xmpp.chatState.startComposing(bid),13!==ev.which||ev.shiftKey||(body="",jsxc.xmpp.chatState.endComposing(bid)),jsxc.storage.updateUserItem("window",bid,"text",body),27===ev.which&&jsxc.gui.window.close(bid)}).keypress(function(ev){return 13!==ev.which||ev.shiftKey||!$(this).val()?void resizeTextarea.call(this):(jsxc.gui.window.postMessage({bid:bid,direction:jsxc.Message.OUT,msg:$(this).val()}),$(this).css("height","").val(""),void ev.preventDefault())}).focus(function(){textinputBlurTimeout&&clearTimeout(textinputBlurTimeout),jsxc.gui.readMsg(bid),resizeTextarea.call(this)}).blur(function(){var self=$(this);textinputBlurTimeout=setTimeout(function(){self.css("height","")},1200)}).mouseenter(function(){$("#jsxc_windowList").data("isOver",!0)}).mouseleave(function(){$("#jsxc_windowList").data("isOver",!1)}),win.find(".jsxc_textarea").click(function(){"function"!=typeof getSelection||getSelection().toString()||win.find(".jsxc_textinput").focus()}),win.find(".jsxc_textarea").slimScroll({height:"234px",distance:"3px"}),win.find(".jsxc_name").disableSelection(),win.find(".slimScrollDiv").resizable({handles:"w, nw, n",minHeight:234,minWidth:250,resize:function(event,ui){jsxc.gui.window.resize(win,ui)},start:function(){win.removeClass("jsxc_normal")},stop:function(){win.addClass("jsxc_normal")}}),win.find(".jsxc_window").css("bottom",-1*win.find(".jsxc_fade").height()),$.inArray(bid,jsxc.storage.getUserItem("windowlist"))<0){var wl=jsxc.storage.getUserItem("windowlist")||[];wl.push(bid),jsxc.storage.setUserItem("windowlist",wl),jsxc.storage.setUserItem("window",bid,{minimize:!0,text:"",unread:0}),jsxc.gui.window.hide(bid)}else jsxc.storage.getUserItem("window",bid).unread&&jsxc.gui._unreadMsg(bid);return $.each(jsxc.gui.emotions,function(i,val){var ins=val[0].split(" ")[0],li=$("
    • ");li.append(jsxc.gui.shortnameToImage(":"+val[1]+":")),li.find("div").attr("title",ins),li.click(function(){win.find(".jsxc_textinput").val(win.find(".jsxc_textinput").val()+ins),win.find(".jsxc_textinput").focus()}),win.find(".jsxc_emoticons ul").prepend(li)}),jsxc.gui.toggleList.call(win.find(".jsxc_emoticons")),jsxc.gui.window.restoreChat(bid),jsxc.gui.update(bid),jsxc.gui.updateWindowListSB(),jsxc.master&&!jsxc.otr.objects[bid]?jsxc.otr.create(bid):jsxc.otr.enable(bid),$(document).trigger("init.window.jsxc",[win]),win},resize:function(win,ui,outer){var bid;if("object"==typeof win)bid=win.attr("data-bid");else{if("string"!=typeof win)return void jsxc.warn("jsxc.gui.window.resize has to be called either with bid or window object.");bid=win,win=jsxc.gui.window.get(bid)}win.attr("data-default-height")||win.attr("data-default-height",win.find(".ui-resizable").height()),win.attr("data-default-width")||win.attr("data-default-width",win.find(".ui-resizable").width());var outer_height_diff=outer?win.find(".jsxc_window").outerHeight()-win.find(".ui-resizable").height():0;ui=$.extend({size:{width:parseInt(win.attr("data-default-width")),height:parseInt(win.attr("data-default-height"))+outer_height_diff}},ui||{}),outer&&(ui.size.height-=outer_height_diff),win.find(".slimScrollDiv").css({width:ui.size.width,height:ui.size.height}),win.width(ui.size.width),win.find(".jsxc_textarea").slimScroll({height:ui.size.height}),$(document).trigger("resize.window.jsxc",[win,bid,ui.size])},fullsize:function(bid){var win=jsxc.gui.window.get(bid),size=jsxc.options.viewport.getSize();size.width-=10,size.height-=win.find(".jsxc_bar").outerHeight()+win.find(".jsxc_textinput").outerHeight(),jsxc.gui.window.resize(win,{size:size})},get:function(id){return $("li.jsxc_windowItem[data-bid='"+jsxc.jidToBid(id)+"']")},open:function(bid){var win=jsxc.gui.window.init(bid);return jsxc.gui.window.show(bid),jsxc.gui.window.highlight(bid),win},close:function(bid){return 0===jsxc.gui.window.get(bid).length?void jsxc.warn("Want to close a window, that is not open."):(jsxc.storage.removeUserElement("windowlist",bid),jsxc.storage.removeUserItem("window",bid),jsxc.storage.getUserItem("buddylist").indexOf(bid)<0&&(jsxc.storage.removeUserItem("buddy",bid),jsxc.storage.removeUserItem("chat",bid)),void jsxc.gui.window._close(bid))},_close:function(bid){jsxc.gui.window.get(bid).remove(),jsxc.gui.updateWindowListSB()},toggle:function(bid){var win=jsxc.gui.window.get(bid);0!==win.parents("#jsxc_windowList").length&&(win.hasClass("jsxc_min")?jsxc.gui.window.show(bid):jsxc.gui.window.hide(bid),jsxc.gui.updateWindowListSB())},show:function(bid){return jsxc.storage.updateUserItem("window",bid,"minimize",!1),jsxc.gui.window._show(bid)},_show:function(bid){var win=jsxc.gui.window.get(bid),duration=0;jsxc.isExtraSmallDevice()&&(parseFloat($("#jsxc_roster").css("right"))>=0&&(duration=jsxc.gui.roster.toggle()),jsxc.gui.window.hide(),jsxc.gui.window.fullsize(bid)),win.removeClass("jsxc_min").addClass("jsxc_normal"),win.find(".jsxc_window").css("bottom","0"),setTimeout(function(){var padding=$("#jsxc_windowListSB").width(),innerWidth=$("#jsxc_windowList>ul").width(),outerWidth=$("#jsxc_windowList").width()-padding;if(innerWidth>outerWidth){var offset=parseInt($("#jsxc_windowList>ul").css("right")),width=win.outerWidth(!0),right=innerWidth-win.position().left-width+offset,left=outerWidth-(innerWidth-win.position().left)-offset;left<0&&jsxc.gui.scrollWindowListBy(left*-1),right<0&&jsxc.gui.scrollWindowListBy(right)}},duration),jsxc.gui.window.scrollDown(bid),jsxc.restoreCompleted&&win.find(".jsxc_textinput").focus(),win.trigger("show.window.jsxc")},hide:function(bid){var hide=function(bid){jsxc.storage.updateUserItem("window",bid,"minimize",!0),jsxc.gui.window._hide(bid)};bid?hide(bid):$("#jsxc_windowList > ul > li").each(function(){var el=$(this);el.hasClass("jsxc_min")||hide(el.attr("data-bid"))})},_hide:function(bid){var win=jsxc.gui.window.get(bid);win.removeClass("jsxc_normal").addClass("jsxc_min"),win.find(".jsxc_window").css("bottom",-1*win.find(".jsxc_fade").height()),win.trigger("hidden.window.jsxc")},highlight:function(bid){var el=jsxc.gui.window.get(bid).find(" .jsxc_bar");el.is(":animated")||el.effect("highlight",{color:"orange"},2e3)},scrollDown:function(bid){var chat=jsxc.gui.window.get(bid).find(".jsxc_textarea");0!==chat.length&&chat.slimScroll({scrollTo:chat.get(0).scrollHeight+"px"})},postMessage:function(message){"object"!=typeof message||message instanceof jsxc.Message||(message=new jsxc.Message(message));var data=jsxc.storage.getUserItem("buddy",message.bid);!message.htmlMsg&&message.msg&&(message.htmlMsg=message.msg),message.msg=jsxc.removeHTML(message.msg),message.msg=jsxc.escapeHTML(message.msg),message.direction===jsxc.Message.OUT&&data.msgstate===OTR.CONST.MSGSTATE_FINISHED&&message.forwarded!==!0&&(message.direction=jsxc.Message.SYS,message.msg=$.t("your_message_wasnt_send_please_end_your_private_conversation")),message.direction===jsxc.Message.OUT&&data.msgstate===OTR.CONST.MSGSTATE_FINISHED&&(message.direction="sys",message.msg=$.t("unencrypted_message_received")+" "+message.msg),message.encrypted="boolean"==typeof message.encrypted?message.encrypted:data.msgstate===OTR.CONST.MSGSTATE_ENCRYPTED;try{message.save()}catch(err){jsxc.warn("Unable to save message.",err),message=new jsxc.Message({msg:"Unable to save that message. Please clear some chat histories.",direction:jsxc.Message.SYS})}return"in"!==message.direction||jsxc.gui.window.get(message.bid).find(".jsxc_textinput").is(":focus")||(jsxc.gui.unreadMsg(message.bid),$(document).trigger("postmessagein.jsxc",[message.bid,message.htmlMsg])),message.direction===jsxc.Message.OUT&&jsxc.master&&message.forwarded!==!0&&message.htmlMsg&&jsxc.xmpp.sendMessage(message),jsxc.gui.window._postMessage(message),"out"===message.direction&&"?"===message.msg&&jsxc.options.get("theAnswerToAnything")!==!1&&("undefined"==typeof jsxc.options.get("theAnswerToAnything")||100*Math.random()%42<1)&&(jsxc.options.set("theAnswerToAnything",!0),jsxc.gui.window.postMessage(new jsxc.Message({bid:message.bid,direction:jsxc.Message.SYS,msg:"42"}))),message},_postMessage:function(message,restore){var bid=message.bid,win=jsxc.gui.window.get(bid),msg=message.msg,direction=message.direction,uid=message._uid;win.find(".jsxc_textinput").is(":not(:focus)")&&direction===jsxc.Message.IN&&!restore&&jsxc.gui.window.highlight(bid),msg=msg.replace(jsxc.CONST.REGEX.URL,function(url){var href=url.match(/^https?:\/\//i)?url:"http://"+url;return''+url+""}),msg=msg.replace(new RegExp("(xmpp:)?("+jsxc.CONST.REGEX.JID.source+")(\\?[^\\s]+\\b)?","i"),function(match,protocol,jid,action){return"xmpp:"===protocol?("string"==typeof action&&(jid+=action),'xmpp:'+jid+""):'mailto:'+jid+""}),$.each(jsxc.gui.emotions,function(i,val){msg=msg.replace(val[2],":"+val[1]+":")}),msg=jsxc.gui.shortnameToImage(msg),msg=msg.replace(/(\r\n|\r|\n)/g,"
      ");var bidData=jsxc.storage.getUserItem("buddy",bid)||{};"in"===direction&&(msg=msg.replace(/^\/me /,''+jsxc.removeHTML(bidData.name||bid)+" ")),msg.match(/^\?OTR([:,|?]|[?v0-9x]+)/)&&(msg=''+$.t("Unreadable_OTR_message")+"");var msgDiv=$("
      "),msgTsDiv=$("
      ");if(msgDiv.addClass("jsxc_chatmessage jsxc_"+direction),msgDiv.attr("id",uid.replace(/:/g,"-")),msgDiv.html("
      "+msg+"
      "),msgTsDiv.addClass("jsxc_timestamp"),msgTsDiv.text(jsxc.getFormattedTime(message.stamp)),message.isReceived()?msgDiv.addClass("jsxc_received"):msgDiv.removeClass("jsxc_received"),message.forwarded?msgDiv.addClass("jsxc_forwarded"):msgDiv.removeClass("jsxc_forwarded"),message.encrypted?msgDiv.addClass("jsxc_encrypted"):msgDiv.removeClass("jsxc_encrypted"),message.error?msgDiv.addClass("jsxc_error"):msgDiv.removeClass("jsxc_error"),msgDiv.attr("title",message.error),message.attachment&&message.attachment.name){var attachment=$("
      ");attachment.addClass("jsxc_attachment"),attachment.addClass("jsxc_"+message.attachment.type.replace(/\//,"-")),attachment.addClass("jsxc_"+message.attachment.type.replace(/^([^\/]+)\/.*/,"$1")),message.attachment.persistent===!1&&attachment.addClass("jsxc_notPersistent"),message.attachment.data&&attachment.addClass("jsxc_data"),message.attachment.type.match(/^image\//)&&message.attachment.thumbnail?$('preview').attr("src",message.attachment.thumbnail).attr("title",message.attachment.name).appendTo(attachment):attachment.text(message.attachment.name),message.attachment.data&&(attachment=$("").append(attachment),attachment.attr("href",message.attachment.data),attachment.attr("download",message.attachment.name),message.attachment.data===message.msg&&msgDiv.find("div").first().empty()),msgDiv.find("div").first().append(attachment)}if("sys"===direction?jsxc.gui.window.get(bid).find(".jsxc_textarea").append('
      '):"undefined"!=typeof message.stamp&&msgDiv.append(msgTsDiv),"sys"!==direction&&$('[data-bid="'+bid+'"]').find(".jsxc_lastmsg .jsxc_text").html(msg),jsxc.Message.getDOM(uid).length>0?jsxc.Message.getDOM(uid).replaceWith(msgDiv):win.find(".jsxc_textarea").append(msgDiv),"object"==typeof message.sender&&null!==message.sender){var title="",avatarDiv=$("
      ");if(avatarDiv.addClass("jsxc_avatar").prependTo(msgDiv),"string"==typeof message.sender.jid){msgDiv.attr("data-bid",jsxc.jidToBid(message.sender.jid));var data=jsxc.storage.getUserItem("buddy",jsxc.jidToBid(message.sender.jid))||{};jsxc.gui.updateAvatar(msgDiv,jsxc.jidToBid(message.sender.jid),data.avatar),title=jsxc.jidToBid(message.sender.jid)}"string"==typeof message.sender.name&&(msgDiv.attr("data-name",message.sender.name),"string"!=typeof message.sender.jid&&jsxc.gui.avatarPlaceholder(avatarDiv,message.sender.name),""!==title&&(title="\n"+title),title=message.sender.name+title,msgTsDiv.text(msgTsDiv.text()+" "+message.sender.name)),avatarDiv.attr("title",jsxc.escapeHTML(title)),msgDiv.prev().length>0&&msgDiv.prev().find(".jsxc_avatar").attr("title")===avatarDiv.attr("title")&&avatarDiv.css("visibility","hidden")}jsxc.gui.detectUriScheme(win),jsxc.gui.detectEmail(win),jsxc.gui.window.scrollDown(bid)},setText:function(bid,text){jsxc.gui.window.get(bid).find(".jsxc_textinput").val(text)},restoreChat:function(bid){var chat=jsxc.storage.getUserItem("chat",bid);if(chat){for(;null!==chat&&chat.length>0;){var c=chat.pop();c.bid=bid,c._uid=c.uid,delete c.uid;var message=new jsxc.Message(c);message.save(),jsxc.gui.window._postMessage(message,!0)}jsxc.storage.removeUserItem("chat",bid)}for(var history=jsxc.storage.getUserItem("history",bid);null!==history&&history.length>0;){var uid=history.pop();jsxc.gui.window._postMessage(new jsxc.Message(uid),!0)}},clear:function(bid){jsxc.storage.removeUserItem("chat",bid);var history=jsxc.storage.getUserItem("history",bid)||[];history.map(function(id){jsxc.storage.removeUserItem("msg",id)}),jsxc.storage.setUserItem("history",bid,[]);var win=jsxc.gui.window.get(bid);win.length>0&&win.find(".jsxc_textarea").empty()},receivedMessage:function(bid,uid){jsxc.warn("Using deprecated receivedMessage.");var message=new jsxc.Message(uid);message.received()},updateProgress:function(message,sent,size){var div=message.getDOM(),span=div.find(".jsxc_timestamp span");0===span.length&&(div.find(".jsxc_timestamp").append(""),span=div.find(".jsxc_timestamp span")),span.text(" "+Math.round(sent/size*100)+"%"),sent===size&&span.remove()},showOverlay:function(bid,content,allowClose){var win=jsxc.gui.window.get(bid);win.find(".jsxc_overlay .jsxc_body").empty().append(content),win.find(".jsxc_overlay .jsxc_close").off("click").click(function(){jsxc.gui.window.hideOverlay(bid)}),allowClose!==!0?win.find(".jsxc_overlay .jsxc_close").hide():win.find(".jsxc_overlay .jsxc_close").show(),win.addClass("jsxc_showOverlay")},hideOverlay:function(bid){var win=jsxc.gui.window.get(bid);win.removeClass("jsxc_showOverlay")},selectResource:function(bid,text,cb,res){if(res=res||jsxc.storage.getUserItem("res",bid)||[],cb=cb||function(){},res.length>0){var i,li,content=$("
      "),list=$("