From f496a2959ac39817b508eadd5e7ebb1729aabb8f Mon Sep 17 00:00:00 2001 From: luoye <397379429@qq.com> Date: Tue, 17 Apr 2018 09:56:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=84=BF=E4=BF=9D=E9=AB=98=E5=8D=B1=E6=8C=87?= =?UTF-8?q?=E5=AF=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- littleApp_child/app.js | 263 +- littleApp_child/app.wxss | 20 +- littleApp_child/pages/Setting/Setting.js | 62 +- littleApp_child/pages/articleLists/articleLists.js | 9 +- littleApp_child/pages/doctor/doctor.js | 71 +- littleApp_child/pages/doctor/home.js | 66 - littleApp_child/pages/doctor/home.json | 1 - littleApp_child/pages/doctor/home.wxml | 2 - littleApp_child/pages/doctor/home.wxss | 1 - littleApp_child/pages/home/home.js | 47 +- littleApp_child/pages/home/home.wxml | 2 +- littleApp_child/pages/risk_guide/risk_guide.wxml | 2 +- littleApp_child/pages/vipService/vipService.js | 5 - littleApp_child/utils/AnalysisBluetooth.js | 136 - littleApp_child/utils/BLEManager.js | 196 - littleApp_child/utils/BloodSugarBluetooth.js | 151 - littleApp_child/utils/WebIM.js | 266 - littleApp_child/utils/WebIMConfig.js | 81 - littleApp_child/utils/bluetooth_connect.js | 402 -- littleApp_child/utils/index.js | 1 - littleApp_child/utils/network_util.js | 6 +- littleApp_child/utils/qiniuUploader.js | 157 - littleApp_child/utils/sdk/README.md | 10 - littleApp_child/utils/sdk/gulpfile.js | 53 - littleApp_child/utils/sdk/index.js | 1 - littleApp_child/utils/sdk/package.json | 35 - littleApp_child/utils/sdk/src/connection.js | 2686 --------- littleApp_child/utils/sdk/src/message.js | 310 - littleApp_child/utils/sdk/src/queue.js | 151 - littleApp_child/utils/sdk/src/status.js | 87 - littleApp_child/utils/sdk/src/utils.js | 832 --- littleApp_child/utils/strophe.js | 6027 -------------------- littleApp_child/utils/xmldom/.npmignore | 5 - littleApp_child/utils/xmldom/.travis.yml | 22 - littleApp_child/utils/xmldom/LICENSE | 8 - littleApp_child/utils/xmldom/__package__.js | 4 - littleApp_child/utils/xmldom/changelog | 14 - littleApp_child/utils/xmldom/component.json | 10 - littleApp_child/utils/xmldom/dom-parser.js | 261 - littleApp_child/utils/xmldom/dom.js | 1154 ---- littleApp_child/utils/xmldom/package.json | 139 - littleApp_child/utils/xmldom/readme.md | 219 - littleApp_child/utils/xmldom/sax.js | 614 -- 43 files changed, 97 insertions(+), 14492 deletions(-) delete mode 100644 littleApp_child/pages/doctor/home.js delete mode 100644 littleApp_child/pages/doctor/home.json delete mode 100644 littleApp_child/pages/doctor/home.wxml delete mode 100644 littleApp_child/pages/doctor/home.wxss delete mode 100644 littleApp_child/utils/AnalysisBluetooth.js delete mode 100644 littleApp_child/utils/BLEManager.js delete mode 100644 littleApp_child/utils/BloodSugarBluetooth.js delete mode 100644 littleApp_child/utils/WebIM.js delete mode 100644 littleApp_child/utils/WebIMConfig.js delete mode 100644 littleApp_child/utils/bluetooth_connect.js delete mode 100644 littleApp_child/utils/index.js delete mode 100755 littleApp_child/utils/qiniuUploader.js delete mode 100644 littleApp_child/utils/sdk/README.md delete mode 100644 littleApp_child/utils/sdk/gulpfile.js delete mode 100644 littleApp_child/utils/sdk/index.js delete mode 100644 littleApp_child/utils/sdk/package.json delete mode 100644 littleApp_child/utils/sdk/src/connection.js delete mode 100644 littleApp_child/utils/sdk/src/message.js delete mode 100644 littleApp_child/utils/sdk/src/queue.js delete mode 100644 littleApp_child/utils/sdk/src/status.js delete mode 100644 littleApp_child/utils/sdk/src/utils.js delete mode 100644 littleApp_child/utils/strophe.js delete mode 100644 littleApp_child/utils/xmldom/.npmignore delete mode 100644 littleApp_child/utils/xmldom/.travis.yml delete mode 100644 littleApp_child/utils/xmldom/LICENSE delete mode 100644 littleApp_child/utils/xmldom/__package__.js delete mode 100644 littleApp_child/utils/xmldom/changelog delete mode 100644 littleApp_child/utils/xmldom/component.json delete mode 100644 littleApp_child/utils/xmldom/dom-parser.js delete mode 100644 littleApp_child/utils/xmldom/dom.js delete mode 100644 littleApp_child/utils/xmldom/package.json delete mode 100644 littleApp_child/utils/xmldom/readme.md delete mode 100644 littleApp_child/utils/xmldom/sax.js diff --git a/littleApp_child/app.js b/littleApp_child/app.js index e8feaf3..0b14dfb 100644 --- a/littleApp_child/app.js +++ b/littleApp_child/app.js @@ -1,20 +1,6 @@ //app.js -require('./utils/strophe.js') -var WebIM = require('./utils/WebIM.js').default App({ - getRoomPage: function () { - return this.getPage("pages/chatroom/chatroom") - }, - getPage: function (pageName) { - var pages = getCurrentPages() - - console.log("pages:" + pages) - return pages.find(function (page) { - - console.log("getPage:" + page.__route__) - return page.__route__ == pageName - }) - }, + onLaunch: function (option) { var that = this //调用API从本地缓存中获取数据 @@ -56,253 +42,6 @@ App({ } }) - WebIM.conn.listen({ - onOpened: function (message) { - console.log("onOpened") - wx.setStorageSync('isHxOpend', true) - // WebIM.conn.setPresence() - // WebIM.conn.getRoster(rosters) - }, - onPresence: function (message) { - console.log('onPresence', message) - var pages = getCurrentPages() - if (message.type == "unsubscribe") { - pages[0].moveFriend(message) - } - if (message.type === "subscribe") { - //console.log('MMMMMMMMMMMMMM',message.status) - if (message.status === '[resp:true]') { - return - } else { - pages[0].handleFriendMsg(message) - } - } - }, - onRoster: function (message) { - console.log('onRoster', message) - var pages = getCurrentPages() - if (pages[0]) { - pages[0].onShow() - } - }, - onAudioMessage: function (message) { - console.log('onAudioMessage', message) - var page = that.getRoomPage() - console.log(page) - if (message) { - if (page && page.data != null && page.data.yourname && message.from == page.data.yourname) { - page.receiveMsg(message, 'audio') - } else { - var chatMsg = that.globalData.chatMsg || [] - // if (message.type == 'txt') { - // var value = WebIM.parseEmoji(message.data.replace(/\n/mg, '')) - // } else if (type == 'emoji') { - // var value = msg.data - // } - var time = WebIM.time() - var msgData = { - info: { - from: message.from, - to: message.to - }, - username: message.from, - yourname: message.from, - msg: { - type: 'audio', - // data: value, - url: message.url - }, - style: '', - time: time, - mid: 'audio' + message.id - } - chatMsg = wx.getStorageSync(msgData.yourname + message.to) || [] - chatMsg.push(msgData) - wx.setStorage({ - key: msgData.yourname + message.to, - data: chatMsg, - success: function () { - //console.log('success') - } - }) - } - } - }, - onTextMessage: function (message) { - console.log('onTextMessage', message) - var page = that.getRoomPage() - // console.log("yourname:", page.data.yourname) - if (message) { - if (page && page.data != null && page.data.yourname && message.from == page.data.yourname) { - page.receiveMsg(message, 'txt') - } else { - var chatMsg = that.globalData.chatMsg || [] - var value = WebIM.parseEmoji(message.data.replace(/\n/mg, '')) - var time = WebIM.time() - var msgData = { - info: { - from: message.from, - to: message.to - }, - username: message.from, - yourname: message.from, - msg: { - type: 'txt', - data: value - }, - style: '', - time: time, - mid: 'txt' + message.id - } - chatMsg = wx.getStorageSync(msgData.yourname + message.to) || [] - chatMsg.push(msgData) - wx.setStorage({ - key: msgData.yourname + message.to, - data: chatMsg, - success: function () { - console.log('setStorage success') - } - }) - } - } - }, - onEmojiMessage: function (message) { - console.log('onEmojiMessage', message) - var page = that.getRoomPage() - //console.log(pages) - if (message) { - if (page && page.data != null && page.data.yourname && message.from == page.data.yourname) { - page.receiveMsg(message, 'emoji') - } else { - var chatMsg = that.globalData.chatMsg || [] - var time = WebIM.time() - var msgData = { - info: { - from: message.from, - to: message.to - }, - username: message.from, - yourname: message.from, - msg: { - type: 'emoji', - data: message.data - }, - style: '', - time: time, - mid: 'emoji' + message.id - } - msgData.style = '' - chatMsg = wx.getStorageSync(msgData.yourname + message.to) || [] - chatMsg.push(msgData) - //console.log(chatMsg) - wx.setStorage({ - key: msgData.yourname + message.to, - data: chatMsg, - success: function () { - //console.log('success') - } - }) - } - } - }, - onPictureMessage: function (message) { - console.log('Picture', message); - var page = that.getRoomPage() - if (message) { - if (page && page.data != null && page.data.yourname && message.from == page.data.yourname) { - //console.log("wdawdawdawdqwd") - page.receiveImage(message, 'img') - } else { - var chatMsg = that.globalData.chatMsg || [] - var time = WebIM.time() - var msgData = { - info: { - from: message.from, - to: message.to - }, - username: message.from, - yourname: message.from, - msg: { - type: 'img', - data: message.url - }, - style: '', - time: time, - mid: 'img' + message.id - } - msgData.style = '' - chatMsg = wx.getStorageSync(msgData.yourname + message.to) || [] - chatMsg.push(msgData) - wx.setStorage({ - key: msgData.yourname + message.to, - data: chatMsg, - success: function () { - //console.log('success') - } - }) - } - } - }, - onClosed: function (message) { - console.log("onClosed:", message) - wx.setStorageSync('isHxOpend', false) - }, - // 各种异常 - onError: function (error) { - console.log("error:", error) - // 16: server-side close the websocket connection - - if (error.type == WebIM.statusCode.WEBIM_CONNCTION_DISCONNECTED) { - console.log('WEBIM_CONNCTION_DISCONNECTED 123', WebIM.conn.autoReconnectNumTotal, WebIM.conn.autoReconnectNumMax); - if (WebIM.conn.autoReconnectNumTotal < WebIM.conn.autoReconnectNumMax) { - return; - } - // wx.('Error', 'server-side close the websocket connection') - // NavigationActions.login()/ - - wx.showToast({ - title: 'server-side close the websocket connection', - duration: 1000 - }); - // wx.redirectTo({ - // url: '../login/login' - // }); - return; - } - - // 8: offline by multi login - if (error.type == WebIM.statusCode.WEBIM_CONNCTION_SERVER_ERROR) { - console.log('WEBIM_CONNCTION_SERVER_ERROR'); - // Alert.alert('Error', 'offline by multi login') - // NavigationActions.login() - - wx.showModal({ - title: '提示', - content: '你的帐号在其他设备上登录,如需使用聊天,请重新进入首页', - showCancel: false, - success: function (res) { - } - }) - // wx.showToast({ - // title: 'offline by multi login', - // duration: 1000 - // }) - // wx.redirectTo({ - // url: '../login/login' - // }) - return; - } - }, - onOffline: function () { - console.log("onOffline:") - }, - onOnline: function () { - console.log("onOnline:") - } - }) - - - }, getUserInfo: function (cb) { var that = this diff --git a/littleApp_child/app.wxss b/littleApp_child/app.wxss index af1d8af..dcc7ca4 100644 --- a/littleApp_child/app.wxss +++ b/littleApp_child/app.wxss @@ -8,24 +8,24 @@ flex-direction: column; align-items: center; justify-content: space-between; - padding: 200rpx 0; + padding: 100px 0; box-sizing: border-box; -} +} .backgroundView { - height: 100%; + height: 100%; width: 100%; background-color: rgb(244, 244, 244); } .horizontalCenter { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; } -page{ +page { height:100%; background: rgb(244, 244, 244); } @@ -49,7 +49,7 @@ page{ text-align: center; font-size: 12px; width: 100%; - background: rgba(0, 0, 0, 0); + background: rgba(0, 0, 0, 0); /* background: rebeccapurple; */ color: rgb(22, 22, 22) } @@ -60,7 +60,7 @@ page{ height: 10px; } -/*// 不换行*/ +/*不换行*/ .not_line_feed{ overflow: hidden; text-overflow: ellipsis; diff --git a/littleApp_child/pages/Setting/Setting.js b/littleApp_child/pages/Setting/Setting.js index 236a4d0..0f81f63 100644 --- a/littleApp_child/pages/Setting/Setting.js +++ b/littleApp_child/pages/Setting/Setting.js @@ -3,17 +3,12 @@ // 网络请求工具类 var networkUtil = require('../../utils/network_util.js') var api = require('../../utils/apiFile.js') -var qiniuUploader = require('../../utils/qiniuUploader.js') +// var qiniuUploader = require('../../utils/qiniuUploader.js') // 获取应用实例 var app = getApp() Page({ data: { setList: [ - // { icon: '../../source/jianchajilu.png', text: '我的预约', right_text:'',margin:0}, - // { icon: '../../source/jianchajilu.png', text: '儿童档案', right_text: '', margin: 10 }, - // { icon: '../../source/jianchajilu.png', text: '消息提醒', right_text: '', margin: 0 }, - // { icon: '../../source/jianchajilu.png', text: '交易记录', right_text: '', margin: 0 }, - // { icon: '../../source/jianchajilu.png', text: '我的收藏', right_text: '', margin: 10 }, { icon: '../../source/feedback_icon.png', text: '用户反馈', right_text: '', margin: 0 }, { icon: '../../source/clear_cach.png', text: '清除缓存', right_text: '', margin:10} ], isShowOne: false, @@ -24,7 +19,6 @@ Page({ }, onLoad: function (option) { - this.getUserInfo() }, onShow:function(){ @@ -67,33 +61,33 @@ Page({ }) }, - selectPhoto(){ - var that = this - wx.showActionSheet({ - itemList: ['手机拍照','本地相册'], - success: function (res) { - if (!res.tapIndex) { - return - } - var imgType = 'camera' - if (res.tapIndex == 1) { - imgType = 'album' - } - wx.chooseImage({ - count: 1, // 默认9 - sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 - sourceType: [imgType], // 可以指定来源是相册还是相机,默认二者都有 - success: function (res) { - // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 - that.qiniuToken(res.tempFilePaths[0]) - } - }) - }, - fail: function (res) { - console.log(res.errMsg) - } - }) - }, + // selectPhoto(){ + // var that = this + // wx.showActionSheet({ + // itemList: ['手机拍照','本地相册'], + // success: function (res) { + // if (!res.tapIndex) { + // return + // } + // var imgType = 'camera' + // if (res.tapIndex == 1) { + // imgType = 'album' + // } + // wx.chooseImage({ + // count: 1, // 默认9 + // sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 + // sourceType: [imgType], // 可以指定来源是相册还是相机,默认二者都有 + // success: function (res) { + // // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 + // that.qiniuToken(res.tempFilePaths[0]) + // } + // }) + // }, + // fail: function (res) { + // console.log(res.errMsg) + // } + // }) + // }, clickPage(e){ console.log(e) var index = e.currentTarget.dataset.index diff --git a/littleApp_child/pages/articleLists/articleLists.js b/littleApp_child/pages/articleLists/articleLists.js index a9f9bab..28d2f96 100644 --- a/littleApp_child/pages/articleLists/articleLists.js +++ b/littleApp_child/pages/articleLists/articleLists.js @@ -77,7 +77,10 @@ Page({ var self = this isRefresh = true networkUtil.showLoading() - var param = { page: page, limit: 15, type: 2,categoryId:self.data.id} + var param = { page: page, limit: 15, type: 2,categoryId:self.data.id,days:getApp().globalData.days} + if (!param.categoryId){ + param.categoryId = 4316 + } networkUtil._get(api.articleList,param,function(res){ console.log(res) isRefresh = false @@ -146,3 +149,7 @@ Page({ }) }, }) + + + + diff --git a/littleApp_child/pages/doctor/doctor.js b/littleApp_child/pages/doctor/doctor.js index 3727acf..684eb12 100644 --- a/littleApp_child/pages/doctor/doctor.js +++ b/littleApp_child/pages/doctor/doctor.js @@ -4,9 +4,6 @@ var networkUtil = require('../../utils/network_util.js') var api = require('../../utils/apiFile.js') -var strophe = require('../../utils/strophe.js') - -var WebIM = require('../../utils/WebIM.js').default Page({ data: { doctorInfo: {}, @@ -22,73 +19,7 @@ Page({ networkUtil.showLoading() this.requestData(options.hospitalId, options.doctorId) }, - chatWithDoctor() { - var self = this - if (!self.data.hxName) { - networkUtil.showErrorToast('暂时无法咨询该医生哦') - return; - } - // var member = wx.getStorageSync('member') - // var isinclude = false - // for (var i = 0; i < member.length; i++) { - // if (member[i].name == self.data.hxName) { - // isinclude = true - // break; - // } - // } - // if (isinclude) { - // self.addFriend(self.data.hxName) - // } - self.addFriend(self.data.hxName) - var my = wx.getStorageSync('hxName') - var nameList = { - myName: my, - your: self.data.hxName, - yourName: self.data.doctorInfo.username, - yourIcon: self.data.doctorInfo.avatar, - } - wx.navigateTo({ - url: '../chatroom/chatroom?username=' + JSON.stringify(nameList) - }) - }, - addFriend(hxName) { - // console.log("hxName:" + hxName) - // console.log("userName:" + wx.getStorageSync('hxName')) - var self = this - networkUtil._get(api.doctorAddFriend, { userName: wx.getStorageSync('hxName'),friendName: hxName }, function (res) { - console.log(res) - self.getRoster() - }, function (res) { - - }) - }, - getRoster() { - var that = this - WebIM.conn.getRoster({ - success: function (roster) { - var member = [] - for (var i = 0; i < roster.length; i++) { - // if (roster[i].subscription == "both") { - // member.push(roster[i]) - // } - member.push(roster[i]) - } - // console.log("getRoster member home:", member) - that.setData({ - member: member - }) - wx.setStorage({ - key: 'member', - data: that.data.member - }) - // console.log("getRoster member home success:", roster) - }, - error: function (err) { - console.log("getRoster erro:", err) - } - }); - - }, + /*---------自定义函数--------*/ requestData(hospitalId, doctorId) { var self = this diff --git a/littleApp_child/pages/doctor/home.js b/littleApp_child/pages/doctor/home.js deleted file mode 100644 index f453c86..0000000 --- a/littleApp_child/pages/doctor/home.js +++ /dev/null @@ -1,66 +0,0 @@ -// pages/doctor/home.js -Page({ - - /** - * 页面的初始数据 - */ - data: { - - }, - - /** - * 生命周期函数--监听页面加载 - */ - onLoad: function (options) { - - }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady: function () { - - }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow: function () { - - }, - - /** - * 生命周期函数--监听页面隐藏 - */ - onHide: function () { - - }, - - /** - * 生命周期函数--监听页面卸载 - */ - onUnload: function () { - - }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh: function () { - - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom: function () { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage: function () { - - } -}) \ No newline at end of file diff --git a/littleApp_child/pages/doctor/home.json b/littleApp_child/pages/doctor/home.json deleted file mode 100644 index 9e26dfe..0000000 --- a/littleApp_child/pages/doctor/home.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/littleApp_child/pages/doctor/home.wxml b/littleApp_child/pages/doctor/home.wxml deleted file mode 100644 index d939a45..0000000 --- a/littleApp_child/pages/doctor/home.wxml +++ /dev/null @@ -1,2 +0,0 @@ - -{{page}}.wxml diff --git a/littleApp_child/pages/doctor/home.wxss b/littleApp_child/pages/doctor/home.wxss deleted file mode 100644 index 59ee071..0000000 --- a/littleApp_child/pages/doctor/home.wxss +++ /dev/null @@ -1 +0,0 @@ -/* pages/doctor/home.wxss */ \ No newline at end of file diff --git a/littleApp_child/pages/home/home.js b/littleApp_child/pages/home/home.js index 901f008..b6ea708 100644 --- a/littleApp_child/pages/home/home.js +++ b/littleApp_child/pages/home/home.js @@ -1,8 +1,8 @@ /*首页*/ -var strophe = require('../../utils/strophe.js') -var WebIM = require('../../utils/WebIM.js').default // 网络请求工具类 + + var networkUtil = require('../../utils/network_util.js') var api = require('../../utils/apiFile.js') // 数字类数据处理 @@ -44,7 +44,9 @@ Page({ { title: '检查预约提醒', icon: 'chakanyuyuetixing', content: '每次检查后,医生会结合当前检查实际情况为儿童预约下次检查时间,届时提前通知家长带孩子进行相关检查。' }, { title: '随访提醒', icon: 'suifangtixing', content: '依据新生儿特有的生理情况,结合其每天都会快速生长发育的特点,对可能遇到的生理病理问题,提供精确到天的健康教育。新生儿期过后,结合婴幼儿体格生长发育特点,针对不同月龄,进行喂养方式、营养补充、辅食添加、动作发育、习惯培养等宣教指导。' }, { title: '查看检查记录', icon: 'chakanjilv', content: '医生依据新生儿娩出情况、新生儿患病情况及新生儿先天性疾病筛查结果辨识、诊断高危儿。针对医生的高危诊断,结合高危儿的月龄、生理因素、高危状态、检查结果、需监测指标等提供精准医疗服务。向早产儿、低出生体重儿、发育迟缓等特殊婴幼儿家长提供育儿帮助。' }, - { title: '高危指导', icon: 'gaoweizhidao', content: '随时随地可查看因幼儿问诊检查、儿科检查、一般检查、辅助检查的各项指标,以及相关指标存在的异常情况。' }] + { title: '高危指导', icon: 'gaoweizhidao', content: '随时随地可查看因幼儿问诊检查、儿科检查、一般检查、辅助检查的各项指标,以及相关指标存在的异常情况。' }], + // 是否开通高危精准指导 + riskGuide:false }, /*---------生命周期--------*/ onLoad: function () { @@ -227,6 +229,7 @@ Page({ this.requestHomeInfo() var that = this var right = true + this.requestVipData() if (app.globalData.userId.length == 1) { right = false } @@ -257,6 +260,44 @@ Page({ url: '../vipService/vipService', }) }, + toRiskGuidePage() { + if (!this.data.riskGuide){ + wx.navigateTo({ + url: "../articleLists/articleLists?category=精准指导", + }) + } else { + wx.showModal({ + title: '温馨提示', + content: '您还没有开通该项服务哦', + confirmText:'立即开通', + success: function (res) { + if (res.confirm) { + wx.navigateTo({ + url: '../vipService/vipService', + }) + } + } + }) + } + }, + requestVipData() { + var self = this + var param = {} + networkUtil._get(api.goods, param, function (res) { + console.log(res) + res.data.data.map(function(item){ + if(item.id == 7){ + if(item.status == 1){ + self.setData({ + riskGuide: true, + }) + } + } + }) + }, function (res) { + + }) + }, calculatePageSize() { var windowWidth = wx.getSystemInfoSync().windowWidth // var smallWidth = ((windowWidth - 10) / 2 - 10) diff --git a/littleApp_child/pages/home/home.wxml b/littleApp_child/pages/home/home.wxml index dfb3805..8ea1b77 100644 --- a/littleApp_child/pages/home/home.wxml +++ b/littleApp_child/pages/home/home.wxml @@ -60,7 +60,7 @@ 育儿知识 - + 精准指导 diff --git a/littleApp_child/pages/risk_guide/risk_guide.wxml b/littleApp_child/pages/risk_guide/risk_guide.wxml index c566e70..160a8c0 100644 --- a/littleApp_child/pages/risk_guide/risk_guide.wxml +++ b/littleApp_child/pages/risk_guide/risk_guide.wxml @@ -40,7 +40,7 @@ 新生儿 健康宝宝 - 健康宝宝 + 49周 diff --git a/littleApp_child/pages/vipService/vipService.js b/littleApp_child/pages/vipService/vipService.js index a45df09..f2ca6af 100644 --- a/littleApp_child/pages/vipService/vipService.js +++ b/littleApp_child/pages/vipService/vipService.js @@ -10,11 +10,6 @@ var app = getApp() Page({ data: { vipList: [], - // { title: '高危指导', icon: 'gaoweizhidao', content: '医生依据新生儿娩出情况、新生儿患病情况及新生儿先天性疾病筛查结果辨识、诊断高危儿。针对医生的高危诊断,结合高危儿的月龄、生理因素、高危状态、检查结果、需监测指标等提供精准医疗服务。向早产儿、低出生体重儿、发育迟缓等特殊婴幼儿家长提供育儿帮助。', isVip: true,price:1}, - // { title: '精准医疗服务', icon: 'jingzunyiliao', content: '依据新生儿特有的生理情况,结合其每天都会快速生长发育的特点,对可能遇到的生理病理问题,提供精确到天的健康教育。新生儿期过后,结合婴幼儿体格生长发育特点,针对不同月龄,进行喂养方式、营养补充、辅食添加、动作发育、习惯培养等宣教指导。', isVip: true, price: 0 }, - // { title: '检查预约提醒', icon: 'chakanyuyuetixing', content: '每次检查后,医生会结合当前检查实际情况为儿童预约下次检查时间,届时提前通知家长带孩子进行相关检查。', isVip: true, price: 0 }, - // { title: '随访提醒', icon: 'suifangtixing', content: '针对健康婴幼儿以及不同高危儿,有不同的随访管理流程,当儿童达到随访月龄或满足随访的其他条件时会提前通知婴幼儿到医院进行随访。', isVip: false, price: 0 }, - // { title: '查看检查记录', icon: 'chakanjilv', content: '随时随地可查看因幼儿问诊检查、儿科检查、一般检查、辅助检查的各项指标,以及相关指标存在的异常情况。', isVip: false, price: 0 } isVip: false, phone: '', }, diff --git a/littleApp_child/utils/AnalysisBluetooth.js b/littleApp_child/utils/AnalysisBluetooth.js deleted file mode 100644 index 4e55e91..0000000 --- a/littleApp_child/utils/AnalysisBluetooth.js +++ /dev/null @@ -1,136 +0,0 @@ -var responseData = {code : '', - status:'测量中...', - data:{}} - -var save_point = 0 -// 数据包 -var packetArr = [] - - -// function appendPacket(dataStr){ -// var dataArr = packetArr -// // 拆分成数组 -// while (i < dataStr.length) { - -// dataArr.push(dataStr.substr(i, 2)) -// i += 2 -// if (dataArr[0] == '55' && dataArr.length >= 8 && dataArr[2] == '03') { - -// } -// } -// if (dataStr.substr(0,2) == '55'){ -// packetStr = dataStr -// save_point = packetStr.length -// if (save_point > 8) { -// save_point = 0 -// return true -// } -// return false   -// } -// packetStr = packetStr + dataStr -// return false -// } - -function bioland_analysisPacket_bloodPressure(dataStr, callBack){ - - // 第6位才能区分包类别 低于6位肯定不是正确数据 - if (dataStr.length > 6) { - var dataArr = [] - var i = 0 - // 拆分成数组 - while (i < dataStr.length) { - dataArr.push(dataStr.substr(i, 2)) - i += 2 - } - // 固定码不对 证明不是正确数据 - if (dataArr[0] != '55') { - responseData = {} - return - } - // 信息包 过程 结果 错误 结束 - switch (dataArr[2]) { - case '00': - deviceInfo(dataArr) - break - case '02': - measuring[dataArr] - break - case '03': - // console.log('结果包', dataArr) - measurementComplete(dataArr) - break - case 'ee': - errorData(dataArr) - console.log('错误包') - break - case '05': - transmitComplete(dataArr) - console.log('结束包') - break - } - callBack(responseData) - } -} - -function deviceInfo(dataArr) { - if(dataArr.length < 10) return - responseData.code = '0' - responseData.status = '成功获取到设备信息' - if(dataArr[5] != '01'){ - responseData.code = 'e' - responseData.status = '设备不匹配,请连接指定血压计' - } -} - -function errorData(dataArr) { - hexToDecimal(dataArr) - responseData.code = 'e' - responseData.status = '测量出错' - responseData.data.errorCode = dataArr[3] -} -// 获取到测量结果 -function measurementComplete(dataArr) { - responseData.code = '3' - responseData.status = '测量完成' - // 收缩压 数据的高字节加低字节 - // console.log('结果包', dataArr) - responseData.systolic = parseInt(dataArr[10] + dataArr[9], 16) - // 舒张压 - responseData.diastolic = parseInt(dataArr[11], 16) - responseData.pulse = parseInt(dataArr[12], 16) -} -// 测量中 -function measuring(dataArr) { - responseData.code = '2' - responseData.status = '测量中...' - // 压力值 - // responseData.data.pressure = dataArr[5] + dataArr[6] - // responseData.data.heartbeat = dataArr[3] -} -// 传输完成 -function transmitComplete(dataArr) { - responseData.code = '5' - responseData.status = '测量完成' -} - -function responseDataChange(){ - callBack(responseData) -} - -// 把包类别之后的16进制数据转换为10进制数据 -function hexToDecimal(dataArr) { - dataArr.map(function (item,index) { - if(index > 2){ - item = parseInt(item, 16) - } - return item - }) -} - -function clearData(){ - -} - -module.exports = { - bioland_analysisPacket_bloodPressure: bioland_analysisPacket_bloodPressure -} \ No newline at end of file diff --git a/littleApp_child/utils/BLEManager.js b/littleApp_child/utils/BLEManager.js deleted file mode 100644 index 1c0af0b..0000000 --- a/littleApp_child/utils/BLEManager.js +++ /dev/null @@ -1,196 +0,0 @@ - -var device_QHC_UUID = '0000ffb0-0000-1000-8000-00805f9b34fb' // 蓝牙电子秤uuid -var weighing_scale_type = '0BFF2608AC01' // 体重秤id -var weighing_scale_close = 'ac01fe010000cccb'// 体重秤灯熄灭 -var weighing_scale_measure_end = 'ca'// 体重秤灯熄灭 -var devList = [] -var notOpenBle = false - -function openBluetoothAdapter(success,fail) { - - getBLEData(success, fail) - wx.onBluetoothAdapterStateChange(function (res) { - // callback - if (res.available == false) { - notOpenBle = true - fail('设备链接已断开') - } else { - console.log('蓝牙连接开启') - if(notOpenBle){ - getBLEData(success, fail) - } - } - }) -} - -function getBLEData(success, fail) { - wx.openBluetoothAdapter({ - success: function (res) { - // success - notOpenBle = false - wx.getBluetoothAdapterState({ - success: function (res) { - console.log('蓝牙适配器状态', res) - if (res.discovering == true){ - console.log('正在搜索') - findingDevice(0, function (dev) { - success(dev) - }) - } else { - searchDevice(success, fail) - } - } - }) - console.log('初始化蓝牙适配器') - }, - fail: function (res) { - console.log(res) - if (res.errMsg.indexOf("already opened") != -1){ - notOpenBle = false - wx.getBluetoothAdapterState({ - success: function (res) { - if (res.discovering == true) { - console.log('正在搜索') - findingDevice(0, function (dev) { - success(dev) - }) - } else { - console.log('开始搜索') - searchDevice(success, fail) - } - } - }) - console.log('初始化蓝牙适配器') - return - } - notOpenBle = true - fail('请检查蓝牙是否打开') - } - }) -} - -function searchDevice(success, fail){ - // 开始扫描 - // var uuid = device_QHC_UUID - // var system = wx.getSystemInfoSync() - // if (system.platform == 'android'){ - // var str = new String(system.system) - // console.log('系统版本', parseInt(str)) - // } - wx.startBluetoothDevicesDiscovery({ - // services: [device_QHC_UUID], - allowDuplicatesKey: true, - success: function (res) { - console.log('开始扫描',res) - findingDevice(0, function (dev) { - success(dev) - }) - }, - fail: function (res) { - console.log('扫描报错',res) - console.log(res) - } - }) -} - -// 搜索到设备 -function findingDevice(filter,valueChange){ - - var response = {}; - response.status = '设备已连接,请站上体重秤' - valueChange(response) - console.log('开启搜索监听') - wx.onBluetoothDeviceFound(function(res) { - // console.log('扫描到',res) - var same = false - var currentDev ; - if(res.deviceId){ // android - currentDev = res - } else if (res.devices){ // ios - currentDev = res.devices[0] - } - // 解析广播数据 - var data; - if (wx.getSystemInfoSync().version == '6.5.7'){ - data = wx.base64ToArrayBuffer(currentDev.advertisData) - } else { - data = currentDev.advertisData - } - - var str = buf2hex(data).toLowerCase() - if (res.deviceId) { // android - str = buf2hex(currentDev.advertisData).toLowerCase() - } - var index = str.indexOf(weighing_scale_type.toLowerCase()) - // console.log(str) - if (index == -1){ // 过滤电子秤 - // console.log('不是电子秤') - return - } - if (str.indexOf(weighing_scale_close) != -1) { - - console.log('设备休眠') - return - } - for(var i = 0;i < devList.length;i++){ - var item = devList[i] - if(item.deviceId == currentDev.deviceId){ - same = true - - var dataStr = str.substr(index + weighing_scale_type.length - 4,16) - // console.log('测量数据', dataStr) - var weightH = dataStr.substr(4,2) - var weightL = dataStr.substr(6,2) - - var weightInt = parseInt(weightH.substr(1, 1) + weightL, 16) / 10 - // 转成str加上小数点 - var wStr = weightInt.toString() - response.weight = weightInt - if (wStr.indexOf('.') == -1){ - response.weight = wStr + '.0' - } - console.log('测量数据', weightInt) - if (dataStr.toLowerCase().indexOf(weighing_scale_measure_end) != -1) { - response.status = '测量完成' - if(weightInt > 150){ - return - } - valueChange(response) - return - } - // console.log('返回测量数据', dataStr) - response.status = '设备已连接,测量中' - } - } - if(!same){ - devList.push(currentDev) - response.devList = devList - response.status = '搜索到设备,正在连接' - } - response.devList = devList - valueChange(response) - }) -} - -function buf2hex(buffer) { // buffer is an ArrayBuffer - return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); -} - -function closeBLE(){ - wx.stopBluetoothDevicesDiscovery({ - complete: function (res) { - console.log('停止搜索', res) - }, - }) - wx.closeBluetoothAdapter({ - complete: function (res) { - console.log('关闭蓝牙',res) - }, - }) -} - -module.exports = { - openBluetoothAdapter: openBluetoothAdapter, - findingDevice : findingDevice, - closeBLE: closeBLE -} diff --git a/littleApp_child/utils/BloodSugarBluetooth.js b/littleApp_child/utils/BloodSugarBluetooth.js deleted file mode 100644 index d492124..0000000 --- a/littleApp_child/utils/BloodSugarBluetooth.js +++ /dev/null @@ -1,151 +0,0 @@ -var responseData = {code : '', - status:'', - mgdl:'', - mmoll:'', - data:{}} - -var save_point = 0 -// 数据包 -var packetArr = [] - - -// function appendPacket(dataStr){ -// var dataArr = packetArr -// // 拆分成数组 -// while (i < dataStr.length) { - -// dataArr.push(dataStr.substr(i, 2)) -// i += 2 -// if (dataArr[0] == '55' && dataArr.length >= 8 && dataArr[2] == '03') { - -// } -// } -// if (dataStr.substr(0,2) == '55'){ -// packetStr = dataStr -// save_point = packetStr.length -// if (save_point > 8) { -// save_point = 0 -// return true -// } -// return false -// } -// packetStr = packetStr + dataStr -// return false -// } -function clearData(){ - responseData = { - code: '', - status: '', - mgdl: '', - mmoll: '', - data: {} - } - - packetArr = [] -} -function bioland_analysisPacket_bloodPressure(dataStr, callBack){ - - // 第6位才能区分包类别 低于6位肯定不是正确数据 - if (dataStr.length > 6) { - var dataArr = [] - var i = 0 - // 拆分成数组 - while (i < dataStr.length) { - dataArr.push(dataStr.substr(i, 2)) - i += 2 - } - // 固定码不对 证明不是正确数据 - if (dataArr[0] != '55') { - responseData = {} - return - } - // 信息包 过程 结果 错误 结束 - switch (dataArr[2]) { - case '00': - deviceInfo(dataArr) - console.log('信息包') - break - case '02': - measuring[dataArr] - break - case '03': - console.log('结果包', dataArr) - measurementComplete(dataArr) - break - case 'ee': - errorData(dataArr) - console.log('错误包') - break - case '05': - transmitComplete(dataArr) - console.log('结束包') - break - } - callBack(responseData) - } -} - -function deviceInfo(dataArr) { - responseData.code = '0' - responseData.status = '成功获取到设备信息' -// if(dataArr[5] != '02'){ -// responseData.code = 'e' -// responseData.status = '设备不匹配,请连接指定血压计' -// } -} - -function errorData(dataArr) { - hexToDecimal(dataArr) - responseData.code = 'e' - responseData.status = '测量出错' - responseData.data.errorCode = dataArr[3] -} -// 获取到测量结果 -function measurementComplete(dataArr) { - responseData.code = '3' - responseData.status = '测量完成' - console.log("measurementComplete:",dataArr) - - var munber = parseInt(dataArr[10] + dataArr[9], 16) - responseData.mgdl = munber - responseData.mmoll = (munber/18).toFixed(1) - // // 收缩压 数据的高字节加低字节 - // responseData.data.systolic = parseInt(dataArr[10] + dataArr[9], 16) - - // // 舒张压 - // responseData.data.diastolic = parseInt(dataArr[11], 16) - // responseData.data.pulse = parseInt(dataArr[12], 16) -} -// 测量中 -function measuring(dataArr) { - responseData.code = '2' - responseData.status = '测量中...' - // 压力值 - // responseData.data.pressure = dataArr[5] + dataArr[6] - // responseData.data.heartbeat = dataArr[3] -} -// 传输完成 -function transmitComplete(dataArr) { - responseData.code = '5' - responseData.status = '测量完成' -} - -function responseDataChange(){ - callBack(responseData) -} - -// 把包类别之后的16进制数据转换为10进制数据 -function hexToDecimal(dataArr) { - dataArr.map(function (item,index) { - if(index > 2){ - item = parseInt(item, 16) - } - return item - }) -} - - -module.exports = { - bioland_analysisPacket_bloodPressure: bioland_analysisPacket_bloodPressure, - clearData: clearData -} \ No newline at end of file diff --git a/littleApp_child/utils/WebIM.js b/littleApp_child/utils/WebIM.js deleted file mode 100644 index d86d865..0000000 --- a/littleApp_child/utils/WebIM.js +++ /dev/null @@ -1,266 +0,0 @@ -'use strict'; - -import Strophe from 'strophe.js' -import websdk from 'sdk/index' -import xmldom from 'xmldom/dom-parser' -import config from 'WebIMConfig' - -// init DOMParser / document for strophe and sdk -// window.WebIM.config.isDebug = true -// console = - -// var originalStringify = JSON.stringify; -// JSON.stringify = function (obj) { -// var seen = []; -// -// var result = originalStringify(obj, function (key, val) { -// if (val instanceof HTMLElement) { -// return val.outerHTML -// } -// if (typeof val == "object") { -// if (seen.indexOf(val) >= 0) { -// return "[Circular]"; -// } -// seen.push(val); -// } -// return val; -// }); -// return result; -// }; - - -// var oriConsole = console -// console.log = function () { -// oriConsole.log.call(oriConsole, [123]) -// } - - -console.group = console.group || {} -console.groupEnd = console.groupEnd || {} - -var window = {} -let WebIM = window.WebIM = websdk; -window.WebIM.config = config; -var DOMParser = window.DOMParser = xmldom.DOMParser; -let document = window.document = new DOMParser().parseFromString("\n", 'text/xml'); - -if (WebIM.config.isDebug) { - - function ts() { - var d = new Date(); - var Hours = d.getHours(); //获取当前小时数(0-23) - var Minutes = d.getMinutes(); //获取当前分钟数(0-59) - var Seconds = d.getSeconds(); //获取当前秒数(0-59) - return (Hours < 10 ? "0" + Hours : Hours) + ':' + (Minutes < 10 ? "0" + Minutes : Minutes) + ':' + (Seconds < 10 ? "0" + Seconds : Seconds) + ' '; - } - - Strophe.Strophe.log = function (level, msg) { - // console.log(ts(), level, msg); - }; - - Strophe.Strophe.Connection.prototype.rawOutput = function (data) { - try { - console.group('%csend # ' + ts(), 'color: blue; font-size: large') - console.log('%c' + data, 'color: blue'); - console.groupEnd(); - } catch (e) { - console.log(e) - } - }; -} - -/** - * Set autoSignIn as true (autoSignInName and autoSignInPwd are configured below), - * You can auto signed in each time when you refresh the page in dev model. - */ -WebIM.config.autoSignIn = false; -if (WebIM.config.autoSignIn) { - WebIM.config.autoSignInName = 'lwz2'; - WebIM.config.autoSignInPwd = '1'; -} - - -// var stropheConn = new window.Strophe.Connection("ws://im-api.easemob.com/ws/", { -// inactivity: 30, -// maxRetries: 5, -// pollingTime: 4500 -// }); -// -// stropheConn.connect( -// '$t$' + 'YWMtmbQEBKKIEeaGmMtXyg5n1wAAAVlkQvGO2WOJGlMCEJKM4VV9GCMnb_XLCXU', -// function() { -// console.log(arguments, 'ggogogo'); -// }, stropheConn.wait, stropheConn.hold); -WebIM.parseEmoji = function (msg) { - if (typeof WebIM.Emoji === 'undefined' || typeof WebIM.Emoji.map === 'undefined') { - return msg; - } else { - var emoji = WebIM.Emoji, - reg = null; - var msgList = []; - var objList = []; - for (var face in emoji.map) { - if (emoji.map.hasOwnProperty(face)) { - while (msg.indexOf(face) > -1) { - msg = msg.replace(face, "^" + emoji.map[face] + "^"); - } - } - } - var ary = msg.split('^') - var reg = /^e.*g$/ - for (var i = 0; i < ary.length; i++) { - if (ary[i] != '') { - msgList.push(ary[i]) - } - } - for (var i = 0; i < msgList.length; i++) { - if (reg.test(msgList[i])) { - var obj = {} - obj['data'] = msgList[i] - obj['type'] = 'emoji' - objList.push(obj) - } else { - var obj = {} - obj['data'] = msgList[i] - obj['type'] = 'txt' - objList.push(obj) - } - } - console.log(objList) - return objList; - } -} - -WebIM.time = function () { - var date = new Date() - var Hours = date.getHours(); - var Minutes = date.getMinutes(); - var Seconds = date.getSeconds(); - var time = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' - + (Hours < 10 ? "0" + Hours : Hours) + ':' + (Minutes < 10 ? "0" + Minutes : Minutes) + ':' + (Seconds < 10 ? "0" + Seconds : Seconds) - return time -} - -WebIM.Emoji = { - path: '../../source/imageSource/faces/', - map: { - '[):]': 'ee_1.png', - '[:D]': 'ee_2.png', - '[;)]': 'ee_3.png', - '[:-o]': 'ee_4.png', - '[:p]': 'ee_5.png', - '[(H)]': 'ee_6.png', - '[:@]': 'ee_7.png', - '[:s]': 'ee_8.png', - '[:$]': 'ee_9.png', - '[:(]': 'ee_10.png', - '[:\'(]': 'ee_11.png', - '[:|]': 'ee_12.png', - '[(a)]': 'ee_13.png', - '[8o|]': 'ee_14.png', - '[8-|]': 'ee_15.png', - '[+o(]': 'ee_16.png', - '[ dispatch({type: Types.ON_OPEND}) -// }) - -// export default WebIM; -module.exports = { - 'default': WebIM -} diff --git a/littleApp_child/utils/WebIMConfig.js b/littleApp_child/utils/WebIMConfig.js deleted file mode 100644 index f4d7ed1..0000000 --- a/littleApp_child/utils/WebIMConfig.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; - -/** - * git do not control webim.config.js - * everyone should copy webim.config.js to webim.config.js - * and have their own configs. - * In this way , others won't be influenced by this config while git pull. - * - */ - -// for react native -let location = { - protocol: 'https' -} - -let config = { - /* - * XMPP server - */ - xmppURL: 'wss://im-api.easemob.com/ws/', - // xmppURL: '172.17.3.122:5280', - /* - * Backend REST API URL - */ - // apiURL: (location.protocol === 'https:' ? 'https:' : 'http:') + '//a1.easemob.com', - // ios must be https!!! by lwz - apiURL: 'https://a1.easemob.com', - // apiURL: (location.protocol === 'https:' ? 'https:' : 'http:') + '//172.17.3.155:8080', - /* - * Application AppKey - */ - appkey: '1123170414115195#mommybaby',//测试版 - // appkey: '1123170414115195#mommybabyfinalversion',//正式版 - /* - * Whether to use HTTPS '1177161227178308#xcx' - * @parameter {Boolean} true or false - */ - https: true, - /* - * isMultiLoginSessions - * true: A visitor can sign in to multiple webpages and receive messages at all the webpages. - * false: A visitor can sign in to only one webpage and receive messages at the webpage. - */ - isMultiLoginSessions: true, - /** - * Whether to use window.doQuery() - * @parameter {Boolean} true or false - */ - isWindowSDK: false, - /** - * isSandBox=true: xmppURL: 'im-api.sandbox.easemob.com', apiURL: '//a1.sdb.easemob.com', - * isSandBox=false: xmppURL: 'im-api.easemob.com', apiURL: '//a1.easemob.com', - * @parameter {Boolean} true or false - */ - isSandBox: false, - /** - * Whether to console.log in strophe.log() - * @parameter {Boolean} true or false - */ - isDebug: true, - /** - * will auto connect the xmpp server autoReconnectNumMax times in background when client is offline. - * won't auto connect if autoReconnectNumMax=0. - */ - autoReconnectNumMax: 20, - /** - * the interval secons between each atuo reconnectting. - * works only if autoReconnectMaxNum >= 2. - */ - autoReconnectInterval: 2, - /** - * webrtc supports WebKit and https only - */ - isWebRTC: false, - /* - * Set to auto sign-in - */ - isAutoLogin: true -}; - -export default config; diff --git a/littleApp_child/utils/bluetooth_connect.js b/littleApp_child/utils/bluetooth_connect.js deleted file mode 100644 index a88eaf8..0000000 --- a/littleApp_child/utils/bluetooth_connect.js +++ /dev/null @@ -1,402 +0,0 @@ -// 连接模式蓝牙 -var util = require('util.js') -var data = { - bioland_device_uuid: '00001000-0000-1000-8000-00805f9b34fb', // 血压uuid - list:[], - deviceIdStr: '' -} - - -var characteristic_write_uuid = '00001001-0000-1000-8000-00805F9B34FB' // 数据写入接口特征值 -var service_write_uuid = '00001000-0000-1000-8000-00805F9B34FB' // 数据写入接口服务服务值 -var characteristic_notify_uuid = '00001002-0000-1000-8000-00805F9B34FB' // 数据读取接口特征值 -var service_notify_uuid = '00001000-0000-1000-8000-00805F9B34FB' // 数据读取接口服务值 - -var responseData = { - code: '', - status: '', - data: {} -} -var notOpenBle = false -var callBack; -var notification; - -// 401蓝牙设备中断连接 201连接设备 200蓝牙状态成功 402连接失败 - -function openBluetooth(data, callBackFun){ - var self = this - callBack = callBackFun - var system = wx.getSystemInfoSync() - if (system.platform == 'android'){ - toLower() - } - responseData = { - code: '', - status: '', - data: {} - } - getBLEData() - wx.onBluetoothAdapterStateChange(function (res) { - // callback - if (res.available == false) { - notOpenBle = true - responseData.status = '设备蓝牙未开启' - responseData.code = '404' - callBack(responseData) - } else { - - if (notOpenBle) { - responseData.code = '200' - getBLEData() - } - } - }) -} - -function getBLEData() { - console.log('获取蓝牙适配器') - wx.openBluetoothAdapter({ - success: function (res) { - // success - notOpenBle = false - wx.getBluetoothAdapterState({ - success: function (res) { - console.log('蓝牙适配器状态', res) - if (res.discovering == true) { - console.log('正在搜索') - foundDevice() - } else { - console.log('开始获取连接设备') - getConnectedDevice() - } - }, - fail: function (res) { - responseData.status = '未能成功获取到蓝牙信息' - callBack(responseData) - console.log(res) - } - }) - }, - fail: function (res) { - console.log(res) - if (res.errMsg.indexOf("already opened") != -1) { - notOpenBle = false - wx.getBluetoothAdapterState({ - success: function (res) { - if (res.discovering == true) { - console.log('正在搜索') - foundDevice() - } else { - console.log('开始获取连接设备') - getConnectedDevice() - } - } - }) - console.log('初始化蓝牙适配器') - return - } - notOpenBle = true - responseData.status = '请检查蓝牙是否打开' - callBack(responseData) - } - }) -} - -// 获取已经连接的设备 -function getConnectedDevice() { - var self = this - responseData.code = '200' - wx.getConnectedBluetoothDevices({ - services: [data.bioland_device_uuid], - success: function (res) { - // success - console.log('获取之前已经连接的蓝牙', res) - if (res.devices.length == 0) { - console.log('之前没有设备连接,开始搜索') - searchDevices() - } else { - var currentDev; - if (res.deviceId) { // android - currentDev = res - } else if (res.devices) { // ios - currentDev = res.devices[0] - } - wx.closeBLEConnection({ - deviceId: res.devices[0].deviceId, - success: function (res) { - console.log('断开之前已经连接的设备,开始搜索') - searchDevices() - }, - }) - } - }, - fail: function (res) { - // fail - console.log('获取已经连接蓝牙失败', res) - searchDevices() - }, - complete: function (res) { - // complete - } - }) -} - -// 搜索设备 -function searchDevices(){ - var self = this - wx.startBluetoothDevicesDiscovery({ - services: [data.bioland_device_uuid], - success: function (res) { - // success - console.log(`开始搜索设备`, res) - foundDevice() - }, - fail: function (res) { - // fail - responseData.status = '未能搜索到设备' - callBack(responseData) - console.log('搜索失败', res) - } - }) -} - -// 找到设备 -function foundDevice(){ - var self = this - responseData.status = '搜索设备中...' - responseData.code = '200' - callBack(responseData) - wx.onBluetoothDeviceFound(function (res) { - console.log('搜索到',res) - var same = false - var currentDev; - if (res.deviceId) { // android - currentDev = res - } else if (res.devices) { // ios - currentDev = res.devices[0] - } - for (var i = 0; i < data.list.length; i++) { - var item = data.list[i] - if (item.deviceId == currentDev.deviceId) { - same = true - } - } - if (!same) { - // var list = data.list - // list.push(currentDev) - responseData.data.currentDev = currentDev - callBack(responseData) - } - }) -} - -function addNotification(notificationFun){ - notification = notificationFun -} - -// 选择设备 -function connectionDevice(deviceId, callbackFun){ - var self = this - data.deviceIdStr = deviceId - wx.stopBluetoothDevicesDiscovery({ - success: function (res) { - console.log('成功停止搜索') - }, - fail: function (res) { - console.log('未能成功停止搜索') - } - }) - responseData.status = '开始连接设备' - callbackFun(responseData) - wx.createBLEConnection({ - deviceId: data.deviceIdStr, - success: function (res) { - // success - console.log('成功连接') - getDeviceService() - }, - fail: function (res) { - // fail - console.log('连接失败',res) - responseData.status = '未能连接到设备' - responseData.code = '402' - callbackFun(responseData) - } - }) -} - -function getDeviceService(){ - var self = this - wx.getBLEDeviceServices({ - deviceId: data.deviceIdStr, - success: function (res) { - // success - console.log('成功获取服务') - res.services.map(function (item) { - if (item.uuid == service_write_uuid || item.uuid.toLowerCase() == service_write_uuid) { - // 如果是大写 就全部转换成大写 - if (util.checkIsContainCapital(item.uuid)) { - toCapital() - } else { - toLower() - } - getDeviceServiceCharacteristics(item.uuid) - } - }) - }, - fail: function (res) { - responseData.status = '未能连接到设备' - callBack(responseData) - } - }) - wx.onBLEConnectionStateChanged(function (res) { - // 该方法回调中可以用于处理连接意外断开等异常情况 - if (res.connected == false){ - responseData.status = '设备连接已断开' - responseData.code = '401' - callBack(responseData) - } - console.log(`device ${res.deviceId} state has changed, connected: ${res}`) - }) -} - -function getDeviceServiceCharacteristics(serviceId){ - var self = this - wx.getBLEDeviceCharacteristics({ - deviceId: data.deviceIdStr, - serviceId: serviceId, - success: function (res) { - // success - console.log('成功获取特征') - res.characteristics.map(function (item) { - if (item.uuid == characteristic_notify_uuid || item.uuid.toLowerCase() == characteristic_notify_uuid) { - console.log('打开监听',item) - openNotify() - } - responseData.code = '201' - responseData.status = '成功连接设备' - callBack(responseData) - }) - }, fail: function (res) { - console.log('失败获取特征',res) - } - }) -} -// 获取设备特征值信息 -function getDeviceServiceCharacteristicsValue(serviceId, characteristicsUuid){ - var self = this - wx.readBLECharacteristicValue({ - deviceId: data.deviceIdStr, - serviceId: service_notify_uuid, - characteristicId: characteristic_notify_uuid, - success: function (res) { - // success - console.log('成功duqu特征') - }, - fail: function (res) { - // fail - responseData.status = '未能获取到设备信息' - callBack(responseData) - } - }) - wx.onBLECharacteristicValueChange(function (res) { - var dataStr = buf2hex(res.value) - if (dataStr) { - notification(dataStr) - } - // 55 0F 00 0A 00 01 00 00 64 00 00 00 00 00 D5 - }) -} - -// 开启监听 -function openNotify(){ - var self = this - console.log(service_notify_uuid) - console.log(characteristic_notify_uuid) - wx.notifyBLECharacteristicValueChanged({ - deviceId: data.deviceIdStr, - serviceId: service_notify_uuid, - characteristicId: characteristic_notify_uuid, - state: true, - success: function (res) { - }, - fail: function (res) { - // fail - console.log('notifyBLECharacteristicValueChange fail --', res) - // responseData.status = '未能获取到设备信息' - callBack(responseData) - } - }) -} - -function writeDataWithStr(str){ - var self = this - var typedArray = new Uint8Array(str.match(/[\da-f]{2}/gi).map(function (h) { - return parseInt(h, 16) - })) - var buffer = typedArray.buffer - - wx.writeBLECharacteristicValue({ - deviceId: data.deviceIdStr, - serviceId: service_write_uuid, - characteristicId: characteristic_write_uuid, - value: buffer, - success: function (res) { - // success - }, - fail: function (res) { - // fail - }, - complete: function (res) { - // complete - getDeviceServiceCharacteristicsValue() - } - }) -} - -function closeBLE() { - - wx.stopBluetoothDevicesDiscovery({ - complete: function (res) { - console.log('停止搜索', res) - }, - }) - wx.closeBLEConnection({ - deviceId: data.deviceIdStr, - complete: function(res) { - console.log('断开该设备的蓝牙', res) - } - }) - wx.closeBluetoothAdapter({ - complete: function (res) { - console.log('关闭蓝牙', res) - }, - }) -} - -function buf2hex(buffer) { // buffer is an ArrayBuffer - return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); -} - -function toCapital() { - characteristic_write_uuid = characteristic_write_uuid.toUpperCase() - service_write_uuid = service_write_uuid.toUpperCase() - characteristic_notify_uuid = characteristic_notify_uuid.toUpperCase() - service_notify_uuid = service_notify_uuid.toUpperCase() -} - -function toLower() { - characteristic_write_uuid = characteristic_write_uuid.toLowerCase() - service_write_uuid = service_write_uuid.toLowerCase() - characteristic_notify_uuid = characteristic_notify_uuid.toLowerCase() - service_notify_uuid = service_notify_uuid.toLowerCase() -} - - -module.exports = { - writeDataWithStr: writeDataWithStr, - openBluetooth: openBluetooth, - connectionDevice: connectionDevice, - closeBLE: closeBLE, - addNotification: addNotification -} \ No newline at end of file diff --git a/littleApp_child/utils/index.js b/littleApp_child/utils/index.js deleted file mode 100644 index 5a3b9c7..0000000 --- a/littleApp_child/utils/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('websdk-1.1.3.js'); \ No newline at end of file diff --git a/littleApp_child/utils/network_util.js b/littleApp_child/utils/network_util.js index 1912a7e..d91474c 100644 --- a/littleApp_child/utils/network_util.js +++ b/littleApp_child/utils/network_util.js @@ -2,7 +2,7 @@ // 测试用户‘花雪莲’,手机号15928512992,验证码666666 // 0测试环境 1正式环境 2演示环境 3衡水 -var Builing_Release_AppStore = 0 +var Builing_Release_AppStore = 1 // 获取服务器地址 function kServerBaseUrl() { switch (Builing_Release_AppStore) { @@ -19,9 +19,9 @@ function kServerBaseUrl() { /* * port: 接口名称 类型字符串 -* params: 参数 类型json +* params: 参数 类型json * success: 成功回调 类型function -* fail: 失败回调 类型function +* fail: 失败回调 类型function */ function _get(port, params, success, fail) { console.log('---------------request_get-----------url:' + kServerBaseUrl() + port) diff --git a/littleApp_child/utils/qiniuUploader.js b/littleApp_child/utils/qiniuUploader.js deleted file mode 100755 index 1c3c9bc..0000000 --- a/littleApp_child/utils/qiniuUploader.js +++ /dev/null @@ -1,157 +0,0 @@ -// created by gpake -(function() { - -var config = { - qiniuRegion: '', - qiniuImageURLPrefix: '', - qiniuUploadToken: '', - qiniuUploadTokenURL: '', - qiniuUploadTokenFunction: null, - qiniuShouldUseQiniuFileName: false -} - -module.exports = { - init: init, - upload: upload, -} - -// 在整个程序生命周期中,只需要 init 一次即可 -// 如果需要变更参数,再调用 init 即可 -function init(options) { - config = { - qiniuRegion: '', - qiniuImageURLPrefix: '', - qiniuUploadToken: '', - qiniuUploadTokenURL: '', - qiniuUploadTokenFunction: null, - qiniuShouldUseQiniuFileName: false - }; - updateConfigWithOptions(options); -} - -function updateConfigWithOptions(options) { - if (options.region) { - config.qiniuRegion = options.region; - } else { - console.error('qiniu uploader need your bucket region'); - } - if (options.uptoken) { - config.qiniuUploadToken = options.uptoken; - } else if (options.uptokenURL) { - config.qiniuUploadTokenURL = options.uptokenURL; - } else if(options.uptokenFunc) { - config.qiniuUploadTokenFunction = options.uptokenFunc; - } - if (options.domain) { - config.qiniuImageURLPrefix = options.domain; - } - config.qiniuShouldUseQiniuFileName = options.shouldUseQiniuFileName -} - -function upload(filePath, success, fail, options) { - if (null == filePath) { - console.error('qiniu uploader need filePath to upload'); - return; - } - if (options) { - updateConfigWithOptions(options); - } - if (config.qiniuUploadToken) { - doUpload(filePath, success, fail, options); - } else if (config.qiniuUploadTokenURL) { - getQiniuToken(function() { - doUpload(filePath, success, fail, options); - }); - } else if (config.qiniuUploadTokenFunction) { - config.qiniuUploadToken = config.qiniuUploadTokenFunction(); - if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { - console.error('qiniu UploadTokenFunction result is null, please check the return value'); - return - } - } else { - console.error('qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]'); - return; - } -} - -function doUpload(filePath, success, fail, options) { - if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { - console.error('qiniu UploadToken is null, please check the init config or networking'); - return - } - var url = uploadURLFromRegionCode(config.qiniuRegion); - var fileName = filePath.split('//')[1]; - if (options && options.key) { - fileName = options.key; - } - var formData = { - 'token': config.qiniuUploadToken - }; - if (!config.qiniuShouldUseQiniuFileName) { - formData['key'] = fileName - } - wx.uploadFile({ - url: url, - filePath: filePath, - name: 'file', - formData: formData, - success: function (res) { - var dataString = res.data - try { - var dataObject = JSON.parse(dataString); - //do something - var imageUrl = config.qiniuImageURLPrefix + '/' + dataObject.key; - dataObject.imageURL = imageUrl; - console.log(dataObject); - if (success) { - success(dataObject); - } - } catch(e) { - console.log('parse JSON failed, origin String is: ' + dataString) - if (fail) { - fail(e); - } - } - }, - fail: function (error) { - console.error(error); - if (fail) { - fail(error); - } - } - }) -} - -function getQiniuToken(callback) { - wx.request({ - url: config.qiniuUploadTokenURL, - success: function (res) { - var token = res.data.uptoken; - if (token && token.length > 0) { - config.qiniuUploadToken = token; - if (callback) { - callback(); - } - } else { - console.error('qiniuUploader cannot get your token, please check the uptokenURL or server') - } - }, - fail: function (error) { - console.error('qiniu UploadToken is null, please check the init config or networking: ' + error); - } - }) -} - -function uploadURLFromRegionCode(code) { - var uploadURL = null; - switch(code) { - case 'ECN': uploadURL = 'https://up.qbox.me'; break; - case 'NCN': uploadURL = 'https://up-z1.qbox.me'; break; - case 'SCN': uploadURL = 'https://up-z2.qbox.me'; break; - case 'NA': uploadURL = 'https://up-na0.qbox.me'; break; - default: console.error('please make the region is with one of [ECN, SCN, NCN, NA]'); - } - return uploadURL; -} - -})(); \ No newline at end of file diff --git a/littleApp_child/utils/sdk/README.md b/littleApp_child/utils/sdk/README.md deleted file mode 100644 index c69f2aa..0000000 --- a/littleApp_child/utils/sdk/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog - -## 1.1.4 - -* add browser version support umd -* remove strophe from sdk because it't too big for webpack or other compiler - -## todo - -* version semver \ No newline at end of file diff --git a/littleApp_child/utils/sdk/gulpfile.js b/littleApp_child/utils/sdk/gulpfile.js deleted file mode 100644 index 1eeb415..0000000 --- a/littleApp_child/utils/sdk/gulpfile.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -var gulp = require('gulp'); -var webpack = require('webpack-stream'); -var mocha = require('gulp-mocha'); // 用于单元测试 -var babel = require("gulp-babel"); // 用于ES6转化ES5 -// var browserify = require('browserify'); -// var source = require('vinyl-source-stream'); -// var buffer = require('vinyl-buffer'); -var uglify = require('gulp-uglify'); -var rename = require('gulp-rename'); -var sourcemaps = require('gulp-sourcemaps'); -var gutil = require('gulp-util'); - - -// websdk.js -// websdk.min.js -// websdk.min.js.map -gulp.task('sdk', ['sdk:umd', 'sdk:umd:min']); - -// websdk.js -gulp.task('sdk:umd', function () { - return gulp.src('./index.js') - .pipe(webpack({ - output: { - filename: 'websdk.browser.js', - library: 'WebIM', - libraryTarget: 'umd' - } - }) - ) - .pipe(gulp.dest('dist/')); -}); - -// websdk.min.js -// websdk.min.js.map -gulp.task('sdk:umd:min', ['sdk:umd'], function () { - return gulp.src('./dist/websdk.browser.js') - .pipe(sourcemaps.init({loadMaps: true})) - .pipe(uglify()) - .pipe(rename('websdk.browser.min.js')) - .on('error', gutil.log) - .pipe(sourcemaps.write('./')) - .pipe(gulp.dest('dist/')); -}); - -gulp.task('default', ['sdk']); - -// -// gulp.task('watch', function() { -// livereload.listen(); //要在这里调用listen()方法 -// gulp.watch('less/*.less', ['less']); -// }); \ No newline at end of file diff --git a/littleApp_child/utils/sdk/index.js b/littleApp_child/utils/sdk/index.js deleted file mode 100644 index fa8e24c..0000000 --- a/littleApp_child/utils/sdk/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./src/connection'); \ No newline at end of file diff --git a/littleApp_child/utils/sdk/package.json b/littleApp_child/utils/sdk/package.json deleted file mode 100644 index 2bd2ef1..0000000 --- a/littleApp_child/utils/sdk/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "easemob-websdk", - "version": "1.1.4", - "description": "Easemob im websdk", - "keywords": [ - "realtime", - "im", - "easemob", - "xmpp", - "strophe" - ], - "main": "index.js", - "scripts": { - "build": "gulp", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "WytheMe", - "license": "MIT", - "dependencies": { - }, - "repository": { - "type": "git", - "url": "git+https://github.com/easemob/web-im" - }, - "devDependencies": { - "gulp-rename": "^1.2.2", - "browserify": "^13.1.1", - "gulp-sourcemaps": "^2.2.0", - "gulp-uglify": "^2.0.0", - "gulp-util": "^3.0.7", - "vinyl-buffer": "^1.0.0", - "vinyl-source-stream": "^1.1.0", - "webpack-stream": "^3.2.0" - } -} diff --git a/littleApp_child/utils/sdk/src/connection.js b/littleApp_child/utils/sdk/src/connection.js deleted file mode 100644 index 7ed447c..0000000 --- a/littleApp_child/utils/sdk/src/connection.js +++ /dev/null @@ -1,2686 +0,0 @@ -// ; -// (function (window, undefined) { -import StropheAll from '../../strophe.js' - -var Strophe = StropheAll.Strophe - -Strophe.log = function (level, msg) { - //console.log(ts(), level, msg); -}; - -var xmldom = require('../../xmldom/dom-parser'); -// //console.log('xml',xmldom, typeof xmldom.DOMParser); -var DOMParser = xmldom.DOMParser; - - -var window = {} -var _version = '1.1.3'; -var _code = require('./status').code; -var _utils = require('./utils').utils; -var _msg = require('./message'); -var _message = _msg._msg; -var _msgHash = {}; -var Queue = require('./queue').Queue; - -var PAGELIMIT = 2; -var pageLimitKey = new Date().getTime(); - -var location = window.location || {protocol: 'https:'} -window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; - -if (window.XDomainRequest) { - XDomainRequest.prototype.oldsend = XDomainRequest.prototype.send; - XDomainRequest.prototype.send = function () { - XDomainRequest.prototype.oldsend.apply(this, arguments); - this.readyState = 2; - }; -} - -Strophe.Request.prototype._newXHR = function () { - var xhr = _utils.xmlrequest(true); - if (xhr.overrideMimeType) { - xhr.overrideMimeType('text/xml'); - } - // use Function.bind() to prepend ourselves as an argument - xhr.onreadystatechange = this.func.bind(null, this); - return xhr; -}; - -Strophe.Websocket.prototype._closeSocket = function () { - if (this.socket) { - var me = this; - setTimeout(function () { - try { - me.socket.close(); - } catch (e) { - } - }, 0); - } else { - this.socket = null; - } -}; - -/** - * - * Strophe.Websocket has a bug while logout: - * 1.send: is ok; - * 2.send: will cause a problem,log as follows: - * WebSocket connection to 'ws://im-api.easemob.com/ws/' failed: Data frame received after close_connect @ strophe.js:5292connect @ strophe.js:2491_login @ websdk-1.1.2.js:278suc @ websdk-1.1.2.js:636xhr.onreadystatechange @ websdk-1.1.2.js:2582 - * 3 "Websocket error [object Event]" - * _changeConnectStatus - * onError Object {type: 7, msg: "The WebSocket connection could not be established or was disconnected.", reconnect: true} - * - * this will trigger socket.onError, therefore _doDisconnect again. - * Fix it by overide _onMessage - */ -Strophe.Websocket.prototype._onMessage = function (message) { - // WebIM && WebIM.config.isDebug && //console.log(WebIM.utils.ts() + 'recv:', message.data); - try { - if (WebIM && WebIM.config.isDebug) { - console.group('%crecv # ', 'color: green; font-size: large') - console.log('%c' + message.data, 'color: green'); - console.groupEnd(); - } - } catch (e) { - //console.log('%crecv' + message.data, 'color: green'); - } - - var elem, data; - // check for closing stream - // var close = ''; - // if (message.data === close) { - // this._conn.rawInput(close); - // this._conn.xmlInput(message); - // if (!this._conn.disconnecting) { - // this._conn._doDisconnect(); - // } - // return; - // - // send and receive close xml: - // so we can't judge whether message.data equals close by === simply. - //console.log('DOMParser connection') - if (message.data.indexOf(" from server"); - // } - } - return; - } else if (message.data.search(" tag before we close the connection - return; - } - this._conn._dataRecv(elem, message.data); -}; - - -var _listenNetwork = function (onlineCallback, offlineCallback) { - - if (window.addEventListener) { - window.addEventListener('online', onlineCallback); - window.addEventListener('offline', offlineCallback); - - } else if (window.attachEvent) { - if (document.body) { - document.body.attachEvent('ononline', onlineCallback); - document.body.attachEvent('onoffline', offlineCallback); - } else { - window.attachEvent('load', function () { - document.body.attachEvent('ononline', onlineCallback); - document.body.attachEvent('onoffline', offlineCallback); - }); - } - } else { - /*var onlineTmp = window.ononline; - var offlineTmp = window.onoffline; - - window.attachEvent('ononline', function () { - try { - typeof onlineTmp === 'function' && onlineTmp(); - } catch ( e ) {} - onlineCallback(); - }); - window.attachEvent('onoffline', function () { - try { - typeof offlineTmp === 'function' && offlineTmp(); - } catch ( e ) {} - offlineCallback(); - });*/ - } -}; - -var _parseRoom = function (result) { - var rooms = []; - var items = result.getElementsByTagName('item'); - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var roomJid = item.getAttribute('jid'); - var tmp = roomJid.split('@')[0]; - var room = { - jid: roomJid, - name: item.getAttribute('name'), - roomId: tmp.split('_')[1] - }; - rooms.push(room); - } - } - return rooms; -}; - -var _parseRoomOccupants = function (result) { - var occupants = []; - var items = result.getElementsByTagName('item'); - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var room = { - jid: item.getAttribute('jid'), - name: item.getAttribute('name') - }; - occupants.push(room); - } - } - return occupants; -}; - -var _parseResponseMessage = function (msginfo) { - var parseMsgData = {errorMsg: true, data: []}; - - ////console.log('msginfo', msginfo) - var msgBodies = msginfo.getElementsByTagName('body'); - ////console.log('msginfo', msgBodies) - if (msgBodies) { - for (var i = 0; i < msgBodies.length; i++) { - var msgBody = msgBodies[i]; - var childNodes = msgBody.childNodes; - if (childNodes && childNodes.length > 0) { - var childNode = msgBody.childNodes[0]; - if (childNode.nodeType == Strophe.ElementType.TEXT) { - var jsondata = childNode.wholeText || childNode.nodeValue; - jsondata = jsondata.replace('\n', '
'); - //console.log('jsondata', jsondata) - - try { - var data = JSON.parse(jsondata); - parseMsgData.errorMsg = false; - parseMsgData.data = [data]; - } catch (e) { - //console.log('eval error', e) - } - } - } - } - - var delayTags = msginfo.getElementsByTagName('delay'); - if (delayTags && delayTags.length > 0) { - var delayTag = delayTags[0]; - var delayMsgTime = delayTag.getAttribute('stamp'); - if (delayMsgTime) { - parseMsgData.delayTimeStamp = delayMsgTime; - } - } - } else { - var childrens = msginfo.childNodes; - if (childrens && childrens.length > 0) { - var child = msginfo.childNodes[0]; - if (child.nodeType == Strophe.ElementType.TEXT) { - try { - var data = eval('(' + child.nodeValue + ')'); - parseMsgData.errorMsg = false; - parseMsgData.data = [data]; - } catch (e) { - } - } - } - } - return parseMsgData; -}; - -var _parseNameFromJidFn = function (jid, domain) { - domain = domain || ''; - var tempstr = jid; - var findex = tempstr.indexOf('_'); - - if (findex !== -1) { - tempstr = tempstr.substring(findex + 1); - } - var atindex = tempstr.indexOf('@' + domain); - if (atindex !== -1) { - tempstr = tempstr.substring(0, atindex); - } - return tempstr; -}; - -var _parseFriend = function (queryTag, conn, from) { - var rouster = []; - var items = queryTag.getElementsByTagName('item'); - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var jid = item.getAttribute('jid'); - if (!jid) { - continue; - } - var subscription = item.getAttribute('subscription'); - var friend = { - subscription: subscription, - jid: jid - }; - var ask = item.getAttribute('ask'); - if (ask) { - friend.ask = ask; - } - var name = item.getAttribute('name'); - if (name) { - friend.name = name; - } else { - var n = _parseNameFromJidFn(jid); - friend.name = n; - } - var groups = []; - Strophe.forEachChild(item, 'group', function (group) { - groups.push(Strophe.getText(group)); - }); - friend.groups = groups; - rouster.push(friend); - // B同意之后 -> B订阅A - if (conn && (subscription == 'from')) { - conn.subscribe({ - toJid: jid - }); - } - - if (conn && (subscription == 'to')) { - conn.subscribed({ - toJid: jid - }); - } - } - } - return rouster; -}; - -var _login = function (options, conn) { - ////console.log(options, conn, '_login') - var accessToken = options.access_token || ''; - if (accessToken == '') { - var loginfo = _utils.stringify(options); - conn.onError({ - type: _code.WEBIM_CONNCTION_OPEN_USERGRID_ERROR, - data: options - }); - return; - } - conn.context.accessToken = options.access_token; - conn.context.accessTokenExpires = options.expires_in; - var stropheConn = null; - if (conn.isOpening() && conn.context.stropheConn) { - stropheConn = conn.context.stropheConn; - } else if (conn.isOpened() && conn.context.stropheConn) { - // return; - stropheConn = new Strophe.Connection(conn.url, { - inactivity: conn.inactivity, - maxRetries: conn.maxRetries, - pollingTime: conn.pollingTime - }); - } else { - stropheConn = new Strophe.Connection(conn.url, { - inactivity: conn.inactivity, - maxRetries: conn.maxRetries, - pollingTime: conn.pollingTime - }); - } - var callback = function (status, msg) { - _loginCallback(status, msg, conn); - }; - - conn.context.stropheConn = stropheConn; - if (conn.route) { - stropheConn.connect(conn.context.jid, '$t$' + accessToken, callback, conn.wait, conn.hold, conn.route); - } else { - stropheConn.connect(conn.context.jid, '$t$' + accessToken, callback, conn.wait, conn.hold); - } -}; - -var _parseMessageType = function (msginfo) { - var msgtype = 'normal'; - var receiveinfo = msginfo.getElementsByTagName('received'); - if (receiveinfo && receiveinfo.length > 0 && receiveinfo[0].namespaceURI === 'urn:xmpp:receipts') { - msgtype = 'received'; - } else { - var inviteinfo = msginfo.getElementsByTagName('invite'); - if (inviteinfo && inviteinfo.length > 0) { - msgtype = 'invite'; - } - } - return msgtype; -}; - -var _handleMessageQueue = function (conn) { - for (var i in _msgHash) { - if (_msgHash.hasOwnProperty(i)) { - _msgHash[i].send(conn); - } - } -}; - -var _loginCallback = function (status, msg, conn) { - var conflict, error; - // console.log('_loginCallback 1', Strophe.Status, status, msg) - if (msg === 'conflict') { - conflict = true; - } - - if (status == Strophe.Status.CONNFAIL) { - //client offline, ping/pong timeout, server quit, server offline - error = { - type: _code.WEBIM_CONNCTION_SERVER_CLOSE_ERROR, //客户端网络离线 - msg: msg, - reconnect: true - }; - - conflict && (error.conflict = true); - conn.onError(error); - } else if (status == Strophe.Status.ATTACHED || status == Strophe.Status.CONNECTED) { - conn.autoReconnectNumTotal = 0 - - // client should limit the speed of sending ack messages up to 5/s - //console.log('_loginCallback 2') - conn.intervalId = setInterval(function () { - conn.handelSendQueue(); - }, 200); - var handleMessage = function (msginfo) { - var type = _parseMessageType(msginfo); - if ('received' === type) { - conn.handleReceivedMessage(msginfo); - return true; - } else if ('invite' === type) { - conn.handleInviteMessage(msginfo); - return true; - } else { - conn.handleMessage(msginfo); - return true; - } - }; - var handlePresence = function (msginfo) { - conn.handlePresence(msginfo); - return true; - }; - var handlePing = function (msginfo) { - conn.handlePing(msginfo); - return true; - }; - var handleIqRoster = function (msginfo) { - conn.handleIqRoster(msginfo); - return true; - }; - var handleIqPrivacy = function (msginfo) { - conn.handleIqPrivacy(msginfo); - return true; - }; - var handleIq = function (msginfo) { - conn.handleIq(msginfo); - return true; - }; - conn.addHandler(handleMessage, null, 'message', null, null, null); - conn.addHandler(handlePresence, null, 'presence', null, null, null); - conn.addHandler(handlePing, 'urn:xmpp:ping', 'iq', 'get', null, null); - conn.addHandler(handleIqRoster, 'jabber:iq:roster', 'iq', 'set', null, null); - conn.addHandler(handleIqPrivacy, 'jabber:iq:privacy', 'iq', 'set', null, null); - conn.addHandler(handleIq, null, 'iq', null, null, null); - - conn.context.status = _code.STATUS_OPENED; - - var supportRecMessage = [ - _code.WEBIM_MESSAGE_REC_TEXT, - _code.WEBIM_MESSAGE_REC_EMOJI]; - - if (_utils.isCanDownLoadFile) { - supportRecMessage.push(_code.WEBIM_MESSAGE_REC_PHOTO); - supportRecMessage.push(_code.WEBIM_MESSAGE_REC_AUDIO_FILE); - } - var supportSedMessage = [_code.WEBIM_MESSAGE_SED_TEXT]; - if (_utils.isCanUploadFile) { - supportSedMessage.push(_code.WEBIM_MESSAGE_REC_PHOTO); - supportSedMessage.push(_code.WEBIM_MESSAGE_REC_AUDIO_FILE); - } - //console.log('_loginCallback 3') - conn.notifyVersion(); - conn.retry && _handleMessageQueue(conn); - conn.heartBeat(); - conn.isAutoLogin && conn.setPresence(); - conn.onOpened({ - canReceive: supportRecMessage, - canSend: supportSedMessage, - accessToken: conn.context.accessToken - }); - } else if (status == Strophe.Status.DISCONNECTING) { - if (conn.isOpened()) { - if (conn.autoReconnectNumTotal < conn.autoReconnectNumMax) { - conn.reconnect() - return - } - - conn.stopHeartBeat() - conn.context.status = _code.STATUS_CLOSING - - error = { - type: _code.WEBIM_CONNCTION_SERVER_CLOSE_ERROR, - msg: msg, - reconnect: true - }; - - conflict && (error.conflict = true); - conn.onError(error); - } - } else if (status == Strophe.Status.DISCONNECTED) { - if (conn.isOpened()) { - if (conn.autoReconnectNumTotal < conn.autoReconnectNumMax) { - conn.reconnect(); - return; - } else { - error = { - type: _code.WEBIM_CONNCTION_DISCONNECTED - }; - conn.onError(error); - } - } - conn.context.status = _code.STATUS_CLOSED; - conn.clear(); - conn.onClosed(); - } else if (status == Strophe.Status.AUTHFAIL) { - error = { - type: _code.WEBIM_CONNCTION_AUTH_ERROR - }; - - conflict && (error.conflict = true); - conn.onError(error); - conn.clear(); - } else if (status == Strophe.Status.ERROR) { - conn.context.status = _code.STATUS_ERROR; - error = { - type: _code.WEBIM_CONNCTION_SERVER_ERROR - }; - - conflict && (error.conflict = true); - conn.onError(error); - } - conn.context.status_now = status; -}; - -var _getJid = function (options, conn) { - var jid = options.toJid || ''; - - if (jid === '') { - var appKey = conn.context.appKey || ''; - var toJid = appKey + '_' + options.to + '@' + conn.domain; - - if (options.resource) { - toJid = toJid + '/' + options.resource; - } - jid = toJid; - } - return jid; -}; - -var _getJidByName = function (name, conn) { - var options = { - to: name - }; - return _getJid(options, conn); -}; - -var _validCheck = function (options, conn) { - options = options || {}; - - if (options.user == '') { - conn.onError({ - type: _code.WEBIM_CONNCTION_USER_NOT_ASSIGN_ERROR - }); - return false; - } - - var user = (options.user + '') || ''; - var appKey = options.appKey || ''; - var devInfos = appKey.split('#'); - - if (devInfos.length !== 2) { - conn.onError({ - type: _code.WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR - }); - return false; - } - var orgName = devInfos[0]; - var appName = devInfos[1]; - - if (!orgName) { - conn.onError({ - type: _code.WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR - }); - return false; - } - if (!appName) { - conn.onError({ - type: _code.WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR - }); - return false; - } - - var jid = appKey + '_' + user.toLowerCase() + '@' + conn.domain, - resource = options.resource || 'webim'; - - if (conn.isMultiLoginSessions) { - resource += user + new Date().getTime() + Math.floor(Math.random().toFixed(6) * 1000000); - } - conn.context.jid = jid + '/' + resource; - /*jid: {appkey}_{username}@domain/resource*/ - conn.context.userId = user; - conn.context.appKey = appKey; - conn.context.appName = appName; - conn.context.orgName = orgName; - - return true; -}; - -var _getXmppUrl = function (baseUrl, https) { - if (/^(ws|http)s?:\/\/?/.test(baseUrl)) { - return baseUrl; - } - - var url = { - prefix: 'http', - base: '://' + baseUrl, - suffix: '/http-bind/' - }; - - if (https && _utils.isSupportWss) { - url.prefix = 'wss'; - url.suffix = '/ws/'; - } else { - if (https) { - url.prefix = 'https'; - } else if (window.WebSocket) { - url.prefix = 'ws'; - url.suffix = '/ws/'; - } - } - - return url.prefix + url.base + url.suffix; -}; - - -//class -var connection = function (options) { - if (!this instanceof connection) { - return new connection(options); - } - - var options = options || {}; - - this.isMultiLoginSessions = options.isMultiLoginSessions || false; - this.wait = options.wait || 30; - this.retry = options.retry || false; - this.https = options.https || location.protocol === 'https:'; - this.url = _getXmppUrl(options.url, this.https); - this.hold = options.hold || 1; - this.route = options.route || null; - this.domain = options.domain || 'easemob.com'; - this.inactivity = options.inactivity || 30; - this.heartBeatWait = options.heartBeatWait || 4500; - this.maxRetries = options.maxRetries || 5; - this.isAutoLogin = options.isAutoLogin === false ? false : true; - this.pollingTime = options.pollingTime || 800; - this.stropheConn = false; - this.autoReconnectNumMax = options.autoReconnectNumMax || 0; - this.autoReconnectNumTotal = 0; - this.autoReconnectInterval = options.autoReconnectInterval || 0; - this.context = {status: _code.STATUS_INIT}; - //todo 接收的事件,放到数组里的时候,加上g.isInBackground字段。每帧执行一个事件的时候,如果g.isInBackground=true,就pass - this.sendQueue = new Queue(); //接收到的事件队列 - this.intervalId = null; -}; - -connection.prototype.handelSendQueue = function () { - var options = this.sendQueue.pop(); - if (options !== null) { - this.sendReceiptsMessage(options); - } -}; -connection.prototype.listen = function (options) { - options.url && (this.url = _getXmppUrl(options.url, this.https)); - this.onOpened = options.onOpened || _utils.emptyfn; - this.onClosed = options.onClosed || _utils.emptyfn; - this.onTextMessage = options.onTextMessage || _utils.emptyfn; - this.onEmojiMessage = options.onEmojiMessage || _utils.emptyfn; - this.onPictureMessage = options.onPictureMessage || _utils.emptyfn; - this.onAudioMessage = options.onAudioMessage || _utils.emptyfn; - this.onVideoMessage = options.onVideoMessage || _utils.emptyfn; - this.onFileMessage = options.onFileMessage || _utils.emptyfn; - this.onLocationMessage = options.onLocationMessage || _utils.emptyfn; - this.onCmdMessage = options.onCmdMessage || _utils.emptyfn; - this.onPresence = options.onPresence || _utils.emptyfn; - this.onRoster = options.onRoster || _utils.emptyfn; - this.onError = options.onError || _utils.emptyfn; - this.onReceivedMessage = options.onReceivedMessage || _utils.emptyfn; - this.onInviteMessage = options.onInviteMessage || _utils.emptyfn; - this.onOffline = options.onOffline || _utils.emptyfn; - this.onOnline = options.onOnline || _utils.emptyfn; - this.onConfirmPop = options.onConfirmPop || _utils.emptyfn; - //for WindowSDK - this.onUpdateMyGroupList = options.onUpdateMyGroupList || _utils.emptyfn; - this.onUpdateMyRoster = options.onUpdateMyRoster || _utils.emptyfn; - // - this.onBlacklistUpdate = options.onBlacklistUpdate || _utils.emptyfn; - - _listenNetwork(this.onOnline, this.onOffline); -}; - -connection.prototype.heartBeat = function () { - var me = this; - //IE8: strophe auto switch from ws to BOSH, need heartbeat - var isNeed = !/^ws|wss/.test(me.url); - // || /mobile/.test(navigator.userAgent) - if (this.heartBeatID || !isNeed) { - return; - } - - var options = { - toJid: this.domain, - type: 'normal' - }; - this.heartBeatID = setInterval(function () { - me.ping(options); - }, this.heartBeatWait); -}; - -connection.prototype.stopHeartBeat = function () { - if (typeof this.heartBeatID == "number") { - this.heartBeatID = clearInterval(this.heartBeatID); - } -}; - -connection.prototype.sendReceiptsMessage = function (options) { - var dom = StropheAll.$msg({ - from: this.context.jid || '', - to: this.domain, - id: options.id || '' - }).c('received', { - xmlns: 'urn:xmpp:receipts', - id: options.id || '' - }); - this.sendCommand(dom.tree()); -}; - -connection.prototype.cacheReceiptsMessage = function (options) { - this.sendQueue.push(options); -}; - -connection.prototype.open = function (options) { - - - var pass = _validCheck(options, this); - - if (!pass) { - return; - } - var conn = this; - - if (conn.isOpening() || conn.isOpened()) { - return; - } - - if (options.accessToken) { - options.access_token = options.accessToken; - _login(options, conn); - } else { - var apiUrl = options.apiUrl; - var userId = options.user; - var pwd = options.pwd || ''; - var appkey = options.appKey; - var str = appkey.split('#'); - var orgName = str[0]; - var appName = str[1]; - var successMethod = options.success; - - var suc = function (data, xhr, myName) { - // console.log('success',data, xhr, myName) - conn.context.status = _code.STATUS_DOLOGIN_IM; - conn.context.restTokenData = data; - //console.log(options) - if (data.statusCode != '404' && data.statusCode != '400') { - wx.showToast({ - title: '登录成功', - icon: 'success', - duration: 1000 - }); - - setTimeout(function () { - successMethod(data); - - // wx.redirectTo({ - // url: '../main/main?myName=' + userId - // }) - }, 1000); - } - - _login(data.data, conn); - }; - var error = function (res, xhr, msg) { - console.log('error', res, xhr, msg) - conn.clear(); - wx.showModal({ - title: '用户名或密码错误!', - showCancel: false, - confirmText: 'OK' - }); - if (res.error && res.error_description) { - conn.onError({ - type: _code.WEBIM_CONNCTION_OPEN_USERGRID_ERROR, - data: res, - xhr: xhr - }); - } else { - conn.onError({ - type: _code.WEBIM_CONNCTION_OPEN_ERROR, - data: res, - xhr: xhr - }); - } - }; - - this.context.status = _code.STATUS_DOLOGIN_USERGRID; - - var loginJson = { - grant_type: 'password', - username: userId, - password: pwd, - timestamp: +new Date() - }; - var loginfo = _utils.stringify(loginJson); - console.log(loginfo) - var options = { - url: apiUrl + '/' + orgName + '/' + appName + '/token', - data: loginfo, - success: suc || _utils.emptyfn, - error: error || _utils.emptyfn - }; - console.log("options", options.success) - _utils.ajax(options); - } - - -}; - -// attach to xmpp server for BOSH -connection.prototype.attach = function (options) { - var pass = _validCheck(options, this); - - if (!pass) { - return; - } - - options = options || {}; - - var accessToken = options.accessToken || ''; - if (accessToken == '') { - this.onError({ - type: _code.WEBIM_CONNCTION_TOKEN_NOT_ASSIGN_ERROR - }); - return; - } - - var sid = options.sid || ''; - if (sid === '') { - this.onError({ - type: _code.WEBIM_CONNCTION_SESSIONID_NOT_ASSIGN_ERROR - }); - return; - } - - var rid = options.rid || ''; - if (rid === '') { - this.onError({ - type: _code.WEBIM_CONNCTION_RID_NOT_ASSIGN_ERROR - }); - return; - } - - var stropheConn = new Strophe.Connection(this.url, { - inactivity: this.inactivity, - maxRetries: this.maxRetries, - pollingTime: this.pollingTime, - heartBeatWait: this.heartBeatWait - }); - - this.context.accessToken = accessToken; - this.context.stropheConn = stropheConn; - this.context.status = _code.STATUS_DOLOGIN_IM; - - var conn = this; - var callback = function (status, msg) { - _loginCallback(status, msg, conn); - }; - - var jid = this.context.jid; - var wait = this.wait; - var hold = this.hold; - var wind = this.wind || 5; - stropheConn.attach(jid, sid, rid, callback, wait, hold, wind); -}; - -connection.prototype.close = function (reason) { - this.stopHeartBeat(); - - var status = this.context.status; - if (status == _code.STATUS_INIT) { - return; - } - - if (this.isClosed() || this.isClosing()) { - return; - } - - this.context.status = _code.STATUS_CLOSING; - this.context.stropheConn.disconnect(reason); -}; - -connection.prototype.addHandler = function (handler, ns, name, type, id, from, options) { - this.context.stropheConn.addHandler(handler, ns, name, type, id, from, options); -}; - -connection.prototype.notifyVersion = function (suc, fail) { - var jid = _getJid({}, this); - var dom = StropheAll.$iq({ - from: this.context.jid || '' - , to: this.domain - , type: 'result' - }) - .c('query', {xmlns: 'jabber:iq:version'}) - .c('name') - .t('easemob') - .up() - .c('version') - .t(_version) - .up() - .c('os') - .t('webim'); - - var suc = suc || _utils.emptyfn; - var error = fail || this.onError; - var failFn = function (ele) { - error({ - type: _code.WEBIM_CONNCTION_NOTIFYVERSION_ERROR - , data: ele - }); - }; - this.context.stropheConn.sendIQ(dom.tree(), suc, failFn); - return; -}; - -// handle all types of presence message -connection.prototype.handlePresence = function (msginfo) { - if (this.isClosed()) { - return; - } - var from = msginfo.getAttribute('from') || ''; - var to = msginfo.getAttribute('to') || ''; - var type = msginfo.getAttribute('type') || ''; - var presence_type = msginfo.getAttribute('presence_type') || ''; - var fromUser = _parseNameFromJidFn(from); - var toUser = _parseNameFromJidFn(to); - var info = { - from: fromUser, - to: toUser, - fromJid: from, - toJid: to, - type: type, - chatroom: msginfo.getElementsByTagName('roomtype').length ? true : false - }; - - var showTags = msginfo.getElementsByTagName('show'); - if (showTags && showTags.length > 0) { - var showTag = showTags[0]; - info.show = Strophe.getText(showTag); - } - var statusTags = msginfo.getElementsByTagName('status'); - if (statusTags && statusTags.length > 0) { - var statusTag = statusTags[0]; - info.status = Strophe.getText(statusTag); - info.code = statusTag.getAttribute('code'); - } - - var priorityTags = msginfo.getElementsByTagName('priority'); - if (priorityTags && priorityTags.length > 0) { - var priorityTag = priorityTags[0]; - info.priority = Strophe.getText(priorityTag); - } - - var error = msginfo.getElementsByTagName('error'); - if (error && error.length > 0) { - var error = error[0]; - info.error = { - code: error.getAttribute('code') - }; - } - - var destroy = msginfo.getElementsByTagName('destroy'); - if (destroy && destroy.length > 0) { - var destroy = destroy[0]; - info.destroy = true; - - var reason = destroy.getElementsByTagName('reason'); - if (reason && reason.length > 0) { - info.reason = Strophe.getText(reason[0]); - } - } - - // - // - // one record once a time - // kick info: actor / member - var members = msginfo.getElementsByTagName('item'); - if (members && members.length > 0) { - var member = members[0]; - var role = member.getAttribute('role'); - var jid = member.getAttribute('jid'); - // dismissed by group - if (role == 'none' && jid) { - var kickedMember = _parseNameFromJidFn(jid); - var actor = member.getElementsByTagName('actor')[0]; - var actorNick = actor.getAttribute('nick'); - info.actor = actorNick; - info.kicked = kickedMember; - } - // Service Acknowledges Room Creation `createGroupACK` - if (role == 'moderator' && info.code == '201') { - // info.type = 'createGroupACK'; - info.type = 'joinPublicGroupSuccess'; - } - } - - // from message : apply to join group - var apply = msginfo.getElementsByTagName('apply'); - if (apply && apply.length > 0) { - apply = apply[0]; - var toNick = apply.getAttribute('toNick'); - var groupJid = apply.getAttribute('to'); - var userJid = apply.getAttribute('from'); - var groupName = _parseNameFromJidFn(groupJid); - var userName = _parseNameFromJidFn(userJid); - info.toNick = toNick; - info.groupName = groupName; - info.type = 'joinGroupNotifications'; - var reason = apply.getElementsByTagName('reason'); - if (reason && reason.length > 0) { - info.reason = Strophe.getText(reason[0]); - } - } - - - if (info.chatroom) { - // diff the - info.presence_type = presence_type; - info.original_type = info.type; - var reflectUser = from.slice(from.lastIndexOf('/') + 1); - - if (reflectUser === this.context.userId) { - if (info.type === '' && !info.code) { - info.type = 'joinChatRoomSuccess'; - } else if (presence_type === 'unavailable' || info.type === 'unavailable') { - if (!info.status) {// logout successfully. - info.type = 'leaveChatRoom'; - } else if (info.code == 110) {// logout or dismissied by admin. - info.type = 'leaveChatRoom'; - } else if (info.error && info.error.code == 406) {// The chat room is full. - info.type = 'reachChatRoomCapacity'; - } - } - } - } else { - info.presence_type = presence_type; - info.original_type = type; - - if (info.type) { - - } else if (type == "" && !info.status && !info.error) { - info.type = 'joinPublicGroupSuccess'; - } else if (presence_type === 'unavailable' || type === 'unavailable') {// There is no roomtype when a chat room is deleted. - if (info.destroy) {// Group or Chat room Deleted. - info.type = 'deleteGroupChat'; - } else if (info.code == 307 || info.code == 321) {// Dismissed by group. - info.type = 'leaveGroup'; - } - } - } - this.onPresence(info, msginfo); -}; - -connection.prototype.handlePing = function (e) { - if (this.isClosed()) { - return; - } - var id = e.getAttribute('id'); - var from = e.getAttribute('from'); - var to = e.getAttribute('to'); - var dom = $iq({ - from: to - , to: from - , id: id - , type: 'result' - }); - this.sendCommand(dom.tree()); -}; - -connection.prototype.handleIq = function (iq) { - return true; -}; - -connection.prototype.handleIqPrivacy = function (msginfo) { - var list = msginfo.getElementsByTagName('list'); - if (list.length == 0) { - return; - } - this.getBlacklist(); -}; - -connection.prototype.handleIqRoster = function (e) { - var id = e.getAttribute('id'); - var from = e.getAttribute('from') || ''; - var name = _parseNameFromJidFn(from); - var curJid = this.context.jid; - var curUser = this.context.userId; - - var iqresult = StropheAll.$iq({type: 'result', id: id, from: curJid}); - this.sendCommand(iqresult.tree()); - - var msgBodies = e.getElementsByTagName('query'); - if (msgBodies && msgBodies.length > 0) { - var queryTag = msgBodies[0]; - var rouster = _parseFriend(queryTag, this, from); - this.onRoster(rouster); - } - return true; -}; - -connection.prototype.handleMessage = function (msginfo) { - if (this.isClosed()) { - return; - } - - var id = msginfo.getAttribute('id') || ''; - - // cache ack into sendQueue first , handelSendQueue will do the send thing with the speed of 5/s - this.cacheReceiptsMessage({ - id: id - }); - ////console.log('handlePresence', msginfo) - var parseMsgData = _parseResponseMessage(msginfo); - ////console.log('parseMsgData', parseMsgData) - if (parseMsgData.errorMsg) { - this.handlePresence(msginfo); - return; - } - // send error - var error = msginfo.getElementsByTagName('error'); - var errorCode = ''; - var errorText = ''; - var errorBool = false; - if (error.length > 0) { - errorBool = true; - errorCode = error[0].getAttribute('code'); - var textDOM = error[0].getElementsByTagName('text'); - errorText = textDOM[0].textContent || textDOM[0].text; - log('handle error', errorCode, errorText); - } - - var msgDatas = parseMsgData.data; - for (var i in msgDatas) { - if (!msgDatas.hasOwnProperty(i)) { - continue; - } - var msg = msgDatas[i]; - if (!msg.from || !msg.to) { - continue; - } - - var from = (msg.from + '').toLowerCase(); - var too = (msg.to + '').toLowerCase(); - var extmsg = msg.ext || {}; - var chattype = ''; - var typeEl = msginfo.getElementsByTagName('roomtype'); - if (typeEl.length) { - chattype = typeEl[0].getAttribute('type') || 'chat'; - } else { - chattype = msginfo.getAttribute('type') || 'chat'; - } - - var msgBodies = msg.bodies; - if (!msgBodies || msgBodies.length == 0) { - continue; - } - var msgBody = msg.bodies[0]; - var type = msgBody.type; - - //console.log('onmessage1', type, msgBody) - - try { - switch (type) { - case 'txt': - //console.log("666666666666") - var receiveMsg = msgBody.msg; - //console.log('receiveMsg', receiveMsg) - //console.log('WebIM.Emoji', WebIM.Emoji) - var emojibody = _utils.parseTextMessage(receiveMsg, WebIM.Emoji); - //console.log('emojibody', emojibody) - if (emojibody.isemoji) { - var msg = { - id: id - , type: chattype - , from: from - , to: too - , delay: parseMsgData.delayTimeStamp - , data: emojibody.body - , ext: extmsg - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - //console.log('onmessage', type, msg) - - this.onEmojiMessage(msg); - } else { - //console.log('ttxtxtxtxtxtxttxtxtxtxtxtxt') - var msg = { - id: id - , type: chattype - , from: from - , to: too - , delay: parseMsgData.delayTimeStamp - , data: receiveMsg - , ext: extmsg - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - //console.log('onmessage', type, msg) - - this.onTextMessage(msg); - } - break; - case 'img': - var rwidth = 0; - var rheight = 0; - if (msgBody.size) { - rwidth = msgBody.size.width; - rheight = msgBody.size.height; - } - var msg = { - id: id - , type: chattype - , from: from - , to: too - , url: msgBody.url - , secret: msgBody.secret - , filename: msgBody.filename - , thumb: msgBody.thumb - , thumb_secret: msgBody.thumb_secret - , file_length: msgBody.file_length || '' - , width: rwidth - , height: rheight - , filetype: msgBody.filetype || '' - , accessToken: this.context.accessToken || '' - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onPictureMessage(msg); - break; - case 'audio': - var msg = { - id: id - , type: chattype - , from: from - , to: too - , url: msgBody.url - , secret: msgBody.secret - , filename: msgBody.filename - , length: msgBody.length || '' - , file_length: msgBody.file_length || '' - , filetype: msgBody.filetype || '' - , accessToken: this.context.accessToken || '' - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onAudioMessage(msg); - break; - case 'file': - var msg = { - id: id - , type: chattype - , from: from - , to: too - , url: msgBody.url - , secret: msgBody.secret - , filename: msgBody.filename - , file_length: msgBody.file_length - , accessToken: this.context.accessToken || '' - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onFileMessage(msg); - break; - case 'loc': - var msg = { - id: id - , type: chattype - , from: from - , to: too - , addr: msgBody.addr - , lat: msgBody.lat - , lng: msgBody.lng - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onLocationMessage(msg); - break; - case 'video': - var msg = { - id: id - , type: chattype - , from: from - , to: too - , url: msgBody.url - , secret: msgBody.secret - , filename: msgBody.filename - , file_length: msgBody.file_length - , accessToken: this.context.accessToken || '' - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onVideoMessage(msg); - break; - case 'cmd': - var msg = { - id: id - , from: from - , to: too - , action: msgBody.action - , ext: extmsg - , delay: parseMsgData.delayTimeStamp - }; - !msg.delay && delete msg.delay; - msg.error = errorBool; - msg.errorText = errorText; - msg.errorCode = errorCode; - this.onCmdMessage(msg); - break; - } - ; - } catch (e) { - this.onError({ - type: _code.WEBIM_CONNCTION_CALLBACK_INNER_ERROR - , data: e - }); - } - } -}; - -connection.prototype.handleReceivedMessage = function (message) { - try { - this.onReceivedMessage(message); - } catch (e) { - this.onError({ - type: _code.WEBIM_CONNCTION_CALLBACK_INNER_ERROR - , data: e - }); - } - - var rcv = message.getElementsByTagName('received'), - id, - mid; - - if (rcv.length > 0) { - if (rcv[0].childNodes && rcv[0].childNodes.length > 0) { - id = rcv[0].childNodes[0].nodeValue; - } else { - id = rcv[0].innerHTML || rcv[0].innerText; - } - mid = rcv[0].getAttribute('mid'); - } - - if (_msgHash[id]) { - try { - _msgHash[id].msg.success instanceof Function && _msgHash[id].msg.success(id, mid); - } catch (e) { - this.onError({ - type: _code.WEBIM_CONNCTION_CALLBACK_INNER_ERROR - , data: e - }); - } - delete _msgHash[id]; - } -}; - -connection.prototype.handleInviteMessage = function (message) { - var form = null; - var invitemsg = message.getElementsByTagName('invite'); - var reasonDom = message.getElementsByTagName('reason')[0]; - var reasonMsg = reasonDom.textContent; - var id = message.getAttribute('id') || ''; - this.sendReceiptsMessage({ - id: id - }); - - if (invitemsg && invitemsg.length > 0) { - var fromJid = invitemsg[0].getAttribute('from'); - form = _parseNameFromJidFn(fromJid); - } - var xmsg = message.getElementsByTagName('x'); - var roomid = null; - if (xmsg && xmsg.length > 0) { - for (var i = 0; i < xmsg.length; i++) { - if ('jabber:x:conference' === xmsg[i].namespaceURI) { - var roomjid = xmsg[i].getAttribute('jid'); - roomid = _parseNameFromJidFn(roomjid); - } - } - } - this.onInviteMessage({ - type: 'invite', - from: form, - roomid: roomid, - reason: reasonMsg - }); -}; - -connection.prototype.sendCommand = function (dom, id) { - if (this.isOpened()) { - //console.log("wadawdwdwadwa", dom) - this.context.stropheConn.send(dom); - } else { - this.onError({ - type: _code.WEBIM_CONNCTION_DISCONNECTED, - reconnect: true - }); - } -}; - -connection.prototype.getUniqueId = function (prefix) { - var cdate = new Date(); - var offdate = new Date(2010, 1, 1); - var offset = cdate.getTime() - offdate.getTime(); - var hexd = parseInt(offset).toString(16); - - if (typeof prefix === 'string' || typeof prefix === 'number') { - return prefix + '_' + hexd; - } else { - return 'WEBIM_' + hexd; - } -}; - -connection.prototype.send = function (message) { - //console.log(message) - if (WebIM.config.isWindowSDK) { - WebIM.doQuery('{"type":"sendMessage","to":"' + message.to + '","message_type":"' + message.type + '","msg":"' + encodeURI(message.msg) + '","chatType":"' + message.chatType + '"}', - function (response) { - }, - function (code, msg) { - - }); - } else { - if (Object.prototype.toString.call(message) === '[object Object]') { - var appKey = this.context.appKey || ''; - var toJid = appKey + '_' + message.to + '@' + this.domain; - - if (message.group) { - toJid = appKey + '_' + message.to + '@conference.' + this.domain; - } - if (message.resource) { - toJid = toJid + '/' + message.resource; - } - //console.log(toJid); - //console.log("adwadwdawdaw", message) - message.toJid = toJid; - message.id = message.id || this.getUniqueId(); - _msgHash[message.id] = new _message(message); - // //console.log(new _message(message)) - _msgHash[message.id].send(this); - } else if (typeof message === 'string') { - _msgHash[message] && _msgHash[message].send(this); - } - } -}; - -connection.prototype.addRoster = function (options) { - var jid = _getJid(options, this); - var name = options.name || ''; - var groups = options.groups || ''; - - var iq = StropheAll.$iq({type: 'set'}); - iq.c('query', {xmlns: 'jabber:iq:roster'}); - iq.c('item', {jid: jid, name: name}); - - if (groups) { - for (var i = 0; i < groups.length; i++) { - iq.c('group').t(groups[i]).up(); - } - } - var suc = options.success || _utils.emptyfn; - var error = options.error || _utils.emptyfn; - this.context.stropheConn.sendIQ(iq.tree(), suc, error); -}; - -connection.prototype.removeRoster = function (options) { - var jid = _getJid(options, this); - var iq = StropheAll.$iq({type: 'set'}).c('query', {xmlns: 'jabber:iq:roster'}).c('item', { - jid: jid, - subscription: 'remove' - }); - - var suc = options.success || _utils.emptyfn; - var error = options.error || _utils.emptyfn; - this.context.stropheConn.sendIQ(iq, suc, error); -}; - -connection.prototype.getRoster = function (options) { - var conn = this; - var dom = StropheAll.$iq({ - type: 'get' - }).c('query', {xmlns: 'jabber:iq:roster'}); - var options = options || {}; - var suc = options.success || this.onRoster; - var completeFn = function (ele) { - var rouster = []; - var msgBodies = ele.getElementsByTagName('query'); - if (msgBodies && msgBodies.length > 0) { - var queryTag = msgBodies[0]; - rouster = _parseFriend(queryTag); - } - suc(rouster, ele); - }; - var error = options.error || this.onError; - var failFn = function (ele) { - error({ - type: _code.WEBIM_CONNCTION_GETROSTER_ERROR - , data: ele - }); - }; - if (this.isOpened()) { - this.context.stropheConn.sendIQ(dom.tree(), completeFn, failFn); - } else { - error({ - type: _code.WEBIM_CONNCTION_DISCONNECTED - }); - } -}; - -connection.prototype.subscribe = function (options) { - var jid = _getJid(options, this); - var pres = StropheAll.$pres({to: jid, type: 'subscribe'}); - if (options.message) { - console.log('ggggggggg', pres, options.message) - pres.c('status').t(options.message).up(); - } - if (options.nick) { - pres.c('nick', {'xmlns': 'http://jabber.org/protocol/nick'}).t(options.nick); - } - this.sendCommand(pres.tree()); -}; - -connection.prototype.subscribed = function (options) { - var jid = _getJid(options, this); - var pres = StropheAll.$pres({to: jid, type: 'subscribed'}); - //console.log("options.message", options.message) - if (options.message) { - pres.c('status').t(options.message).up(); - } - this.sendCommand(pres.tree()); -}; - -connection.prototype.unsubscribe = function (options) { - var jid = _getJid(options, this); - var pres = StropheAll.$pres({to: jid, type: 'unsubscribe'}); - - if (options.message) { - pres.c('status').t(options.message); - } - this.sendCommand(pres.tree()); -}; - -connection.prototype.unsubscribed = function (options) { - var jid = _getJid(options, this); - var pres = StropheAll.$pres({to: jid, type: 'unsubscribed'}); - - if (options.message) { - pres.c('status').t(options.message).up(); - } - this.sendCommand(pres.tree()); -}; - -connection.prototype.createRoom = function (options) { - var suc = options.success || _utils.emptyfn; - var err = options.error || _utils.emptyfn; - var roomiq; - - roomiq = StropheAll.$iq({ - to: options.roomName, - type: 'set' - }) - .c('query', {xmlns: Strophe.NS.MUC_OWNER}) - .c('x', {xmlns: 'jabber:x:data', type: 'submit'}); - - return this.context.stropheConn.sendIQ(roomiq.tree(), suc, err); -}; - -connection.prototype.joinPublicGroup = function (options) { - var roomJid = this.context.appKey + '_' + options.roomId + '@conference.' + this.domain; - var room_nick = roomJid + '/' + this.context.userId; - var suc = options.success || _utils.emptyfn; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_JOINROOM_ERROR, - data: ele - }); - }; - var iq = $pres({ - from: this.context.jid, - to: room_nick - }) - .c('x', {xmlns: Strophe.NS.MUC}); - - this.context.stropheConn.sendIQ(iq.tree(), suc, errorFn); -}; - -connection.prototype.listRooms = function (options) { - var iq = StropheAll.$iq({ - to: options.server || 'conference.' + this.domain, - from: this.context.jid, - type: 'get' - }) - .c('query', {xmlns: Strophe.NS.DISCO_ITEMS}); - - var suc = options.success || _utils.emptyfn; - var error = options.error || this.onError; - var completeFn = function (result) { - var rooms = []; - rooms = _parseRoom(result); - try { - suc(rooms); - } catch (e) { - error({ - type: _code.WEBIM_CONNCTION_GETROOM_ERROR, - data: e - }); - } - }; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_GETROOM_ERROR - , data: ele - }); - }; - this.context.stropheConn.sendIQ(iq.tree(), completeFn, errorFn); -}; - -connection.prototype.queryRoomMember = function (options) { - var domain = this.domain; - var members = []; - var iq = StropheAll.$iq({ - to: this.context.appKey + '_' + options.roomId + '@conference.' + this.domain - , type: 'get' - }) - .c('query', {xmlns: Strophe.NS.MUC + '#admin'}) - .c('item', {affiliation: 'member'}); - - var suc = options.success || _utils.emptyfn; - var completeFn = function (result) { - var items = result.getElementsByTagName('item'); - - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var mem = { - jid: item.getAttribute('jid') - , affiliation: 'member' - }; - members.push(mem); - } - } - suc(members); - }; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_GETROOMMEMBER_ERROR - , data: ele - }); - }; - this.context.stropheConn.sendIQ(iq.tree(), completeFn, errorFn); -}; - -connection.prototype.queryRoomInfo = function (options) { - var domain = this.domain; - var iq = StropheAll.$iq({ - to: this.context.appKey + '_' + options.roomId + '@conference.' + domain, - type: 'get' - }).c('query', {xmlns: Strophe.NS.DISCO_INFO}); - - var suc = options.success || _utils.emptyfn; - var members = []; - - var completeFn = function (result) { - var settings = ''; - var features = result.getElementsByTagName('feature'); - if (features) { - settings = features[1].getAttribute('var') + '|' + features[3].getAttribute('var') + '|' + features[4].getAttribute('var'); - } - switch (settings) { - case 'muc_public|muc_membersonly|muc_notallowinvites': - settings = 'PUBLIC_JOIN_APPROVAL'; - break; - case 'muc_public|muc_open|muc_notallowinvites': - settings = 'PUBLIC_JOIN_OPEN'; - break; - case 'muc_hidden|muc_membersonly|muc_allowinvites': - settings = 'PRIVATE_MEMBER_INVITE'; - break; - case 'muc_hidden|muc_membersonly|muc_notallowinvites': - settings = 'PRIVATE_OWNER_INVITE'; - break; - } - var owner = ''; - var fields = result.getElementsByTagName('field'); - var fieldValues = {}; - if (fields) { - for (var i = 0; i < fields.length; i++) { - var field = fields[i]; - var fieldVar = field.getAttribute('var'); - var fieldSimplify = fieldVar.split('_')[1]; - switch (fieldVar) { - case 'muc#roominfo_occupants': - case 'muc#roominfo_maxusers': - case 'muc#roominfo_affiliations': - case 'muc#roominfo_description': - fieldValues[fieldSimplify] = (field.textContent || field.text || ''); - break; - case 'muc#roominfo_owner': - var mem = { - jid: (field.textContent || field.text) + '@' + domain - , affiliation: 'owner' - }; - members.push(mem); - fieldValues[fieldSimplify] = (field.textContent || field.text); - break; - } - - // if (field.getAttribute('label') === 'owner') { - // var mem = { - // jid: (field.textContent || field.text) + '@' + domain - // , affiliation: 'owner' - // }; - // members.push(mem); - // break; - // } - } - fieldValues['name'] = (result.getElementsByTagName('identity')[0]).getAttribute('name'); - } - log(settings, members, fieldValues); - suc(settings, members, fieldValues); - }; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_GETROOMINFO_ERROR - , data: ele - }); - }; - this.context.stropheConn.sendIQ(iq.tree(), completeFn, errorFn); -}; - -connection.prototype.queryRoomOccupants = function (options) { - var suc = options.success || _utils.emptyfn; - var completeFn = function (result) { - var occupants = []; - occupants = _parseRoomOccupants(result); - suc(occupants); - } - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_GETROOMOCCUPANTS_ERROR - , data: ele - }); - }; - var attrs = { - xmlns: Strophe.NS.DISCO_ITEMS - }; - var info = StropheAll.$iq({ - from: this.context.jid - , to: this.context.appKey + '_' + options.roomId + '@conference.' + this.domain - , type: 'get' - }).c('query', attrs); - this.context.stropheConn.sendIQ(info.tree(), completeFn, errorFn); -}; - -connection.prototype.setUserSig = function (desc) { - var dom = StropheAll.$pres({xmlns: 'jabber:client'}); - desc = desc || ''; - dom.c('status').t(desc); - this.sendCommand(dom.tree()); -}; - -connection.prototype.setPresence = function (type, status) { - var dom = StropheAll.$pres({xmlns: 'jabber:client'}); - if (type) { - if (status) { - dom.c('show').t(type); - dom.up().c('status').t(status); - } else { - dom.c('show').t(type); - } - } - this.sendCommand(dom.tree()); -}; - -connection.prototype.getPresence = function () { - var dom = StropheAll.$pres({xmlns: 'jabber:client'}); - var conn = this; - this.sendCommand(dom.tree()); -}; - -connection.prototype.ping = function (options) { - var options = options || {}; - var jid = _getJid(options, this); - - var dom = StropheAll.$iq({ - from: this.context.jid || '' - , to: jid - , type: 'get' - }).c('ping', {xmlns: 'urn:xmpp:ping'}); - - var suc = options.success || _utils.emptyfn; - var error = options.error || this.onError; - var failFn = function (ele) { - error({ - type: _code.WEBIM_CONNCTION_PING_ERROR - , data: ele - }); - }; - if (this.isOpened()) { - this.context.stropheConn.sendIQ(dom.tree(), suc, failFn); - } else { - error({ - type: _code.WEBIM_CONNCTION_DISCONNECTED - }); - } - return; -}; - -connection.prototype.isOpened = function () { - return this.context.status == _code.STATUS_OPENED; -}; - -connection.prototype.isOpening = function () { - var status = this.context.status; - return status == _code.STATUS_DOLOGIN_USERGRID || status == _code.STATUS_DOLOGIN_IM; -}; - -connection.prototype.isClosing = function () { - return this.context.status == _code.STATUS_CLOSING; -}; - -connection.prototype.isClosed = function () { - return this.context.status == _code.STATUS_CLOSED; -}; - -connection.prototype.clear = function () { - var key = this.context.appKey; - if (this.errorType != WebIM.statusCode.WEBIM_CONNCTION_DISCONNECTED) { - this.context = { - status: _code.STATUS_INIT, - appKey: key - }; - } - if (this.intervalId) { - clearInterval(this.intervalId); - } - if (this.errorType == WebIM.statusCode.WEBIM_CONNCTION_CLIENT_LOGOUT || this.errorType == -1) { - - } -}; - -connection.prototype.getChatRooms = function (options) { - - if (!_utils.isCanSetRequestHeader) { - conn.onError({ - type: _code.WEBIM_CONNCTION_NOT_SUPPORT_CHATROOM_ERROR - }); - return; - } - - var conn = this, - token = options.accessToken || this.context.accessToken; - - if (token) { - var apiUrl = options.apiUrl; - var appName = this.context.appName; - var orgName = this.context.orgName; - - if (!appName || !orgName) { - conn.onError({ - type: _code.WEBIM_CONNCTION_AUTH_ERROR - }); - return; - } - - var suc = function (data, xhr) { - typeof options.success === 'function' && options.success(data); - }; - - var error = function (res, xhr, msg) { - if (res.error && res.error_description) { - conn.onError({ - type: _code.WEBIM_CONNCTION_LOAD_CHATROOM_ERROR, - msg: res.error_description, - data: res, - xhr: xhr - }); - } - }; - - var pageInfo = { - pagenum: parseInt(options.pagenum) || 1, - pagesize: parseInt(options.pagesize) || 20 - }; - - var opts = { - url: apiUrl + '/' + orgName + '/' + appName + '/chatrooms', - dataType: 'json', - type: 'GET', - headers: {'Authorization': 'Bearer ' + token}, - data: pageInfo, - success: suc || _utils.emptyfn, - error: error || _utils.emptyfn - }; - _utils.ajax(opts); - } else { - conn.onError({ - type: _code.WEBIM_CONNCTION_TOKEN_NOT_ASSIGN_ERROR - }); - } - -}; - -connection.prototype.joinChatRoom = function (options) { - var roomJid = this.context.appKey + '_' + options.roomId + '@conference.' + this.domain; - var room_nick = roomJid + '/' + this.context.userId; - var suc = options.success || _utils.emptyfn; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_JOINCHATROOM_ERROR - , data: ele - }); - }; - - var iq = $pres({ - from: this.context.jid, - to: room_nick - }) - .c('x', {xmlns: Strophe.NS.MUC + '#user'}) - .c('item', {affiliation: 'member', role: 'participant'}) - .up().up() - .c('roomtype', {xmlns: 'easemob:x:roomtype', type: 'chatroom'}); - - this.context.stropheConn.sendIQ(iq.tree(), suc, errorFn); -}; - -connection.prototype.quitChatRoom = function (options) { - var roomJid = this.context.appKey + '_' + options.roomId + '@conference.' + this.domain; - var room_nick = roomJid + '/' + this.context.userId; - var suc = options.success || _utils.emptyfn; - var err = options.error || _utils.emptyfn; - var errorFn = function (ele) { - err({ - type: _code.WEBIM_CONNCTION_QUITCHATROOM_ERROR - , data: ele - }); - }; - var iq = $pres({ - from: this.context.jid, - to: room_nick, - type: 'unavailable' - }) - .c('x', {xmlns: Strophe.NS.MUC + '#user'}) - .c('item', {affiliation: 'none', role: 'none'}) - .up().up() - .c('roomtype', {xmlns: 'easemob:x:roomtype', type: 'chatroom'}); - - this.context.stropheConn.sendIQ(iq.tree(), suc, errorFn); -}; - -connection.prototype._onReceiveInviteFromGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group invitation", - msg: info.user + " invites you to join into group:" + info.group_id, - agree: function agree() { - WebIM.doQuery('{"type":"acceptInvitationFromGroup","id":"' + info.group_id + '","user":"' + info.user + '"}', function (response) { - }, function (code, msg) { - IM.api.NotifyError("acceptInvitationFromGroup error:" + msg); - }); - - }, - reject: function reject() { - WebIM.doQuery('{"type":"declineInvitationFromGroup","id":"' + info.group_id + '","user":"' + info.user + '"}', function (response) { - }, function (code, msg) { - IM.api.NotifyError("declineInvitationFromGroup error:" + msg); - }); - } - }; - - this.onConfirmPop(options); -}; -connection.prototype._onReceiveInviteAcceptionFromGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group invitation response", - msg: info.user + " agreed to join into group:" + info.group_id, - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onReceiveInviteDeclineFromGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group invitation response", - msg: info.user + " rejected to join into group:" + info.group_id, - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onAutoAcceptInvitationFromGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group invitation", - msg: "You had joined into the group:" + info.group_name + " automatically.Inviter:" + info.user, - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onLeaveGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group notification", - msg: "You have been out of the group:" + info.group_id + ".Reason:" + info.msg, - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onReceiveJoinGroupApplication = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group join application", - msg: info.user + " applys to join into group:" + info.group_id, - agree: function agree() { - WebIM.doQuery('{"type":"acceptJoinGroupApplication","id":"' + info.group_id + '","user":"' + info.user + '"}', function (response) { - }, function (code, msg) { - IM.api.NotifyError("acceptJoinGroupApplication error:" + msg); - }); - }, - reject: function reject() { - WebIM.doQuery('{"type":"declineJoinGroupApplication","id":"' + info.group_id + '","user":"' + info.user + '"}', function (response) { - }, function (code, msg) { - IM.api.NotifyError("declineJoinGroupApplication error:" + msg); - }); - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onReceiveAcceptionFromGroup = function (info) { - info = eval('(' + info + ')'); - var options = { - title: "Group notification", - msg: "You had joined into the group:" + info.group_name + ".", - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onReceiveRejectionFromGroup = function () { - info = eval('(' + info + ')'); - var options = { - title: "Group notification", - msg: "You have been rejected to join into the group:" + info.group_name + ".", - agree: function agree() { - } - }; - this.onConfirmPop(options); -}; -connection.prototype._onUpdateMyGroupList = function (options) { - this.onUpdateMyGroupList(options); -}; -connection.prototype._onUpdateMyRoster = function (options) { - this.onUpdateMyRoster(options); -}; -connection.prototype.reconnect = function () { - var that = this; - setTimeout(function () { - _login(that.context.restTokenData, that); - }, (this.autoReconnectNumTotal == 0 ? 0 : this.autoReconnectInterval) * 1000); - this.autoReconnectNumTotal++; -}; -connection.prototype.closed = function () { - IM.api.init(); -}; - -// used for blacklist -function _parsePrivacy(iq) { - var list = []; - var items = iq.getElementsByTagName('item'); - - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var jid = item.getAttribute('value'); - var order = item.getAttribute('order'); - var type = item.getAttribute('type'); - if (!jid) { - continue; - } - var n = _parseNameFromJidFn(jid); - list[n] = { - type: type, - order: order, - jid: jid, - name: n - }; - } - } - return list; -}; - -// used for blacklist -connection.prototype.getBlacklist = function (options) { - options = (options || {}); - var iq = StropheAll.$iq({type: 'get'}); - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var me = this; - - iq.c('query', {xmlns: 'jabber:iq:privacy'}) - .c('list', {name: 'special'}); - - this.context.stropheConn.sendIQ(iq.tree(), function (iq) { - me.onBlacklistUpdate(_parsePrivacy(iq)); - sucFn(); - }, function () { - me.onBlacklistUpdate([]); - errFn(); - }); -}; - -// used for blacklist -connection.prototype.addToBlackList = function (options) { - var iq = StropheAll.$iq({type: 'set'}); - var blacklist = options.list || {}; - var type = options.type || 'jid'; - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var piece = iq.c('query', {xmlns: 'jabber:iq:privacy'}) - .c('list', {name: 'special'}); - - var keys = Object.keys(blacklist); - var len = keys.length; - var order = 2; - - for (var i = 0; i < len; i++) { - var item = blacklist[keys[i]]; - var type = item.type || 'jid'; - var jid = item.jid; - - piece = piece.c('item', {action: 'deny', order: order++, type: type, value: jid}) - .c('message'); - if (i !== len - 1) { - piece = piece.up().up(); - } - } - - // log('addToBlackList', blacklist, piece.tree()); - this.context.stropheConn.sendIQ(piece.tree(), sucFn, errFn); -}; - -// used for blacklist -connection.prototype.removeFromBlackList = function (options) { - - var iq = StropheAll.$iq({type: 'set'}); - var blacklist = options.list || {}; - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var piece = iq.c('query', {xmlns: 'jabber:iq:privacy'}) - .c('list', {name: 'special'}); - - var keys = Object.keys(blacklist); - var len = keys.length; - - for (var i = 0; i < len; i++) { - var item = blacklist[keys[i]]; - var type = item.type || 'jid'; - var jid = item.jid; - var order = item.order; - - piece = piece.c('item', {action: 'deny', order: order, type: type, value: jid}) - .c('message'); - if (i !== len - 1) { - piece = piece.up().up(); - } - } - - // log('removeFromBlackList', blacklist, piece.tree()); - this.context.stropheConn.sendIQ(piece.tree(), sucFn, errFn); -}; - -connection.prototype._getGroupJid = function (to) { - var appKey = this.context.appKey || ''; - return appKey + '_' + to + '@conference.' + this.domain; -} -; - -// used for blacklist -connection.prototype.addToGroupBlackList = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var jid = _getJid(options, this); - var affiliation = 'admin';//options.affiliation || 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = StropheAll.$iq({type: 'set', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('item', { - affiliation: 'outcast', - jid: jid - }); - - this.context.stropheConn.sendIQ(iq.tree(), sucFn, errFn); -}; - -function _parseGroupBlacklist(iq) { - var list = {}; - var items = iq.getElementsByTagName('item'); - - if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; - var jid = item.getAttribute('jid'); - var affiliation = item.getAttribute('affiliation'); - var nick = item.getAttribute('nick'); - if (!jid) { - continue; - } - var n = _parseNameFromJidFn(jid); - list[n] = { - jid: jid, - affiliation: affiliation, - nick: nick, - name: n - }; - } - } - return list; -} - -// used for blacklist -connection.prototype.getGroupBlacklist = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - - // var jid = _getJid(options, this); - var affiliation = 'admin';//options.affiliation || 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = StropheAll.$iq({type: 'get', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('item', { - affiliation: 'outcast', - }); - - this.context.stropheConn.sendIQ(iq.tree(), function (msginfo) { - log('getGroupBlackList'); - sucFn(_parseGroupBlacklist(msginfo)); - }, function () { - errFn(); - }); -}; - -// used for blacklist -connection.prototype.removeGroupMemberFromBlacklist = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - - var jid = _getJid(options, this); - var affiliation = 'admin';//options.affiliation || 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = StropheAll.$iq({type: 'set', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('item', { - affiliation: 'member', - jid: jid - }); - - this.context.stropheConn.sendIQ(iq.tree(), function (msginfo) { - sucFn(); - }, function () { - errFn(); - }); -}; - -/** - * changeGroupSubject 修改群名称 - * - * @param options - */ - -connection.prototype.changeGroupSubject = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - - // must be `owner` - var affiliation = 'owner'; - var to = this._getGroupJid(options.roomId); - var iq = StropheAll.$iq({type: 'set', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('x', {type: 'submit', xmlns: 'jabber:x:data'}) - .c('field', {var: 'FORM_TYPE'}) - .c('value') - .t('http://jabber.org/protocol/muc#roomconfig') - .up().up() - .c('field', {var: 'muc#roomconfig_roomname'}) - .c('value') - .t(options.subject) - .up().up() - .c('field', {var: 'muc#roomconfig_roomdesc'}) - .c('value') - .t(options.description); - - - this.context.stropheConn.sendIQ(iq.tree(), function (msginfo) { - sucFn(); - }, function () { - errFn(); - }); -}; - -/** - * destroyGroup 删除群组 - * - * @param options - */ - -connection.prototype.destroyGroup = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - - // must be `owner` - var affiliation = 'owner'; - var to = this._getGroupJid(options.roomId); - var iq = StropheAll.$iq({type: 'set', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('destroy'); - - this.context.stropheConn.sendIQ(iq.tree(), function (msginfo) { - sucFn(); - }, function () { - errFn(); - }); -}; - -/** - * leaveGroupBySelf 主动离开群组 - * - * @param options - */ - -connection.prototype.leaveGroupBySelf = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - - // must be `owner` - var jid = _getJid(options, this); - var affiliation = 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = $iq({type: 'set', to: to}); - - iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - .c('item', { - affiliation: 'none', - jid: jid - }); - - this.context.stropheConn.sendIQ(iq.tree(), function (msgInfo) { - sucFn(msgInfo); - }, function (errInfo) { - errFn(errInfo); - }); -}; - -/** - * leaveGroup 被踢出群组 - * - * @param options - */ - -connection.prototype.leaveGroup = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var list = options.list || []; - var affiliation = 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = $iq({type: 'set', to: to}); - var piece = iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - var keys = Object.keys(list); - var len = keys.length; - - for (var i = 0; i < len; i++) { - var name = list[keys[i]]; - var jid = _getJidByName(name, this); - - piece = piece.c('item', { - affiliation: 'none', - jid: jid - }).up().c('item', { - role: 'none', - jid: jid, - }).up(); - } - - this.context.stropheConn.sendIQ(iq.tree(), function (msgInfo) { - sucFn(msgInfo); - }, function (errInfo) { - errFn(errInfo); - }); -}; - -/** - * addGroupMembers 添加群组成员 - * - * @param options - */ - -connection.prototype.addGroupMembers = function (options) { - var sucFn = options.success || _utils.emptyfn; - var errFn = options.error || _utils.emptyfn; - var list = options.list || []; - var affiliation = 'admin'; - var to = this._getGroupJid(options.roomId); - var iq = $iq({type: 'set', to: to}); - var piece = iq.c('query', {xmlns: 'http://jabber.org/protocol/muc#' + affiliation}) - var keys = Object.keys(list); - var len = keys.length; - - for (var i = 0; i < len; i++) { - var name = list[keys[i]]; - var jid = _getJidByName(name, this); - - piece = piece.c('item', { - affiliation: 'member', - jid: jid - }).up(); - } - - this.context.stropheConn.sendIQ(iq.tree(), function (msgInfo) { - sucFn(msgInfo); - }, function (errInfo) { - errFn(errInfo); - }); -}; - -/** - * acceptInviteFromGroup 接受加入申请 - * - * @param options - */ -connection.prototype.acceptInviteFromGroup = function (options) { - options.success = function () { - // then send sendAcceptInviteMessage - // connection.prototype.sendAcceptInviteMessage(optoins); - }; - this.addGroupMembers(options); -}; - -/** - * rejectInviteFromGroup 拒绝加入申请 - * - * throw request for now 暂时不处理,直接丢弃 - * - * @param options - */ -connection.prototype.rejectInviteFromGroup = function (options) { -}; - -/** - * createGroup 创建群组 - * - * 1. 创建申请 -> 得到房主身份 - * 2. 获取房主信息 -> 得到房间form - * 3. 完善房间form -> 创建成功 - * 4. 添加房间成员 - * 5. 消息通知成员 - * @param options - */ -connection.prototype.createGroup = function (options) { - var roomId = +new Date(); - var toRoom = this._getGroupJid(roomId); - var to = toRoom + '/' + this.context.userId; - - var pres = StropheAll.$pres({to: to}) - .c('x', {xmlns: 'http://jabber.org/protocol/muc'}).up() - .c('create', {xmlns: 'http://jabber.org/protocol/muc'}).up(); - // .c('c', { - // hash: 'sha-1', - // node: 'https://github.com/robbiehanson/XMPPFramework', - // ver: 'k6gP4Ua5m4uu9YorAG0LRXM+kZY=', - // xmlns: 'http://jabber.org/protocol/caps' - // }).up(); - - // createGroupACK - this.sendCommand(pres.tree()); - - var me = this; - // timeout hack for create group async - setTimeout(function () { - // Creating a Reserved Room - var iq = $iq({type: 'get', to: toRoom}) - .c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'}); - - // Strophe.info('step 1 ----------'); - // Strophe.info(options); - me.context.stropheConn.sendIQ(iq.tree(), function (msgInfo) { - // log(msgInfo); - - // for ie hack - if ('setAttribute' in msgInfo) { - // Strophe.info('step 3 ----------'); - var x = msgInfo.getElementsByTagName('x')[0]; - x.setAttribute('type', 'submit'); - } else { - // Strophe.info('step 4 ----------'); - Strophe.forEachChild(msgInfo, 'x', function (field) { - field.setAttribute('type', 'submit'); - }); - } - - // var rcv = msgInfo.getElementsByTagName('x'); - // var v; - // if (rcv.length > 0) { - // if (rcv[0].childNodes && rcv[0].childNodes.length > 0) { - // v = rcv[0].childNodes[0].nodeValue; - // } else { - // v = rcv[0].innerHTML || rcv[0].innerText - // } - // mid = rcv[0].getAttribute('mid'); - // } - Strophe.info('step 5 ----------'); - Strophe.forEachChild(x, 'field', function (field) { - var fieldVar = field.getAttribute('var'); - var valueDom = field.getElementsByTagName('value')[0]; - Strophe.info(fieldVar); - switch (fieldVar) { - case 'muc#roomconfig_roomname': - _setText(valueDom, options.subject || ''); - break; - case 'muc#roomconfig_roomdesc': - _setText(valueDom, options.description || ''); - break; - case 'muc#roomconfig_publicroom': // public 1 - _setText(valueDom, +options.optionsPublic); - break; - case 'muc#roomconfig_membersonly': - _setText(valueDom, +options.optionsMembersOnly); - break; - case 'muc#roomconfig_moderatedroom': - _setText(valueDom, +options.optionsModerate); - break; - case 'muc#roomconfig_persistentroom': - _setText(valueDom, 1); - break; - case 'muc#roomconfig_allowinvites': - _setText(valueDom, +options.optionsAllowInvites); - break; - case 'muc#roomconfig_allowvisitornickchange': - _setText(valueDom, 0); - break; - case 'muc#roomconfig_allowvisitorstatus': - _setText(valueDom, 0); - break; - case 'allow_private_messages': - _setText(valueDom, 0); - break; - case 'allow_private_messages_from_visitors': - _setText(valueDom, 'nobody'); - break; - default: - break; - } - // log(valueDom); - }); - - var iq = $iq({to: toRoom, type: 'set'}) - .c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'}) - .cnode(x); - - // log(iq.tree()); - - me.context.stropheConn.sendIQ(iq.tree(), function (msgInfo) { - // sucFn(msgInfo); - - me.addGroupMembers({ - list: options.members, - roomId: roomId - }); - }, function (errInfo) { - // errFn(errInfo); - }); - // sucFn(msgInfo); - }, function (errInfo) { - // errFn(errInfo); - }); - }, 1000); -}; - -function _setText(valueDom, v) { - if ('textContent' in valueDom) { - valueDom.textContent = v; - } else if ('text' in valueDom) { - valueDom.text = v; - } else { - // Strophe.info('_setText 4 ----------'); - // valueDom.innerHTML = v; - } -} -// connection.prototype.onError = function () { -// return false; -// }; -// window.WebIM = typeof WebIM !== 'undefined' ? WebIM : {}; -var WebIM = window.WebIM || {}; -WebIM.connection = connection; -WebIM.utils = _utils; -WebIM.statusCode = _code; -WebIM.message = _msg.message; -WebIM.doQuery = function (str, suc, fail) { - if (typeof window.cefQuery === 'undefined') { - return; - } - window.cefQuery({ - request: str, - persistent: false, - onSuccess: suc, - onFailure: fail - } - ); -}; - -module.exports = WebIM; - -if (module.hot) { - module.hot.accept(); -} diff --git a/littleApp_child/utils/sdk/src/message.js b/littleApp_child/utils/sdk/src/message.js deleted file mode 100644 index bcf80b3..0000000 --- a/littleApp_child/utils/sdk/src/message.js +++ /dev/null @@ -1,310 +0,0 @@ -import StropheAll from '../../strophe.js' - ; -(function () { - 'use strict'; - - var _utils = require('./utils').utils; - var Message = function (type, id) { - if (!this instanceof Message) { - return new Message(type); - } - - this._msg = {}; - - if (typeof Message[type] === 'function') { - Message[type].prototype.setGroup = this.setGroup; - this._msg = new Message[type](id); - } - return this._msg; - } - Message.prototype.setGroup = function (group) { - this.body.group = group; - } - - - /* - * text message - */ - Message.txt = function (id) { - this.id = id; - this.type = 'txt'; - this.body = {}; - }; - Message.txt.prototype.set = function (opt) { - this.value = opt.msg; - this.body = { - id: this.id - , to: opt.to - , msg: this.value - , type: this.type - , roomType: opt.roomType - , ext: opt.ext || {} - , success: opt.success - , fail: opt.fail - }; - - !opt.roomType && delete this.body.roomType; - - }; - - /* - * cmd message - */ - Message.cmd = function (id) { - this.id = id; - this.type = 'cmd'; - this.body = {}; - }; - Message.cmd.prototype.set = function (opt) { - this.value = ''; - - this.body = { - to: opt.to - , action: opt.action - , msg: this.value - , type: this.type - , roomType: opt.roomType - , ext: opt.ext || {} - }; - !opt.roomType && delete this.body.roomType; - }; - - /* - * loc message - */ - Message.location = function (id) { - this.id = id; - this.type = 'loc'; - this.body = {}; - }; - Message.location.prototype.set = function (opt) { - this.body = { - to: opt.to - , type: this.type - , roomType: opt.roomType - , addr: opt.addr - , lat: opt.lat - , lng: opt.lng - , ext: opt.ext || {} - }; - }; - - /* - * img message - */ - Message.img = function (id) { - this.id = id; - this.type = 'img'; - this.body = {}; - }; - Message.img.prototype.set = function (opt) { - // opt.file = opt.file || _utils.getFileUrl(opt.fileInputId); - ////console.log(opt) - this.value = opt.file; - this.body = { - id: this.id, - file: this.value, - apiUrl: opt.apiUrl, - to: opt.to, - type: this.type, - ext: opt.ext || {}, - roomType: opt.roomType, - onFileUploadError: opt.onFileUploadError, - onFileUploadComplete: opt.onFileUploadComplete, - success: opt.success, - fail: opt.fail, - flashUpload: opt.flashUpload, - width: opt.width, - height: opt.height, - body: opt.body - }; - !opt.roomType && delete this.body.roomType; - }; - - /* - * audio message - */ - Message.audio = function (id) { - this.id = id; - this.type = 'audio'; - this.body = {}; - }; - Message.audio.prototype.set = function (opt) { - opt.file = opt.file || _utils.getFileUrl(opt.fileInputId); - - this.value = opt.file; - this.filename = opt.filename || this.value.filename; - - this.body = { - id: this.id - , file: this.value - , filename: this.filename - , apiUrl: opt.apiUrl - , to: opt.to - , type: this.type - , ext: opt.ext || {} - , length: opt.length || 0 - , roomType: opt.roomType - , file_length: opt.file_length - , onFileUploadError: opt.onFileUploadError - , onFileUploadComplete: opt.onFileUploadComplete - , success: opt.success - , fail: opt.fail - , flashUpload: opt.flashUpload - , body: opt.body - }; - !opt.roomType && delete this.body.roomType; - }; - - /* - * file message - */ - Message.file = function (id) { - this.id = id; - this.type = 'file'; - this.body = {}; - }; - Message.file.prototype.set = function (opt) { - opt.file = opt.file || _utils.getFileUrl(opt.fileInputId); - - this.value = opt.file; - this.filename = opt.filename || this.value.filename; - - this.body = { - id: this.id - , file: this.value - , filename: this.filename - , apiUrl: opt.apiUrl - , to: opt.to - , type: this.type - , ext: opt.ext || {} - , roomType: opt.roomType - , onFileUploadError: opt.onFileUploadError - , onFileUploadComplete: opt.onFileUploadComplete - , success: opt.success - , fail: opt.fail - , flashUpload: opt.flashUpload - , body: opt.body - }; - !opt.roomType && delete this.body.roomType; - }; - - /* - * video message - */ - Message.video = function (id) { - - }; - Message.video.prototype.set = function (opt) { - - }; - - var _Message = function (message) { - - if (!this instanceof _Message) { - return new _Message(message, conn); - } - - this.msg = message; - } - - _Message.prototype.send = function (conn) { - var me = this; - ////console.log(this) // 消息对象 - var _send = function (message) { - - message.ext = message.ext || {}; - message.ext.weichat = message.ext.weichat || {}; - message.ext.weichat.originType = message.ext.weichat.originType || 'webim'; - // //console.log('message',message) msg对象 - var json = { - from: conn.context.userId || '' - , to: message.to - , bodies: [message.body] - , ext: message.ext || {} - }; - - var jsonstr = _utils.stringify(json); - var dom = StropheAll.$msg({ - type: message.group || 'chat' - , to: message.toJid - , id: message.id - , xmlns: 'jabber:client' - }).c('body').t(jsonstr); - //console.log("dommmmmmmm",dom) - if (message.roomType) { - dom.up().c('roomtype', {xmlns: 'easemob:x:roomtype', type: 'chatroom'}); - } - - setTimeout(function () { - if (typeof _msgHash !== 'undefined' && _msgHash[message.id]) { - _msgHash[message.id].msg.fail instanceof Function - && _msgHash[message.id].msg.fail(message.id); - } - }, 60000); - conn.sendCommand(dom.tree(), message.id); - } - - - if (me.msg.file) { - if (me.msg.body && me.msg.body.url) {// Only send msg - _send(me.msg); - return; - } - var _tmpComplete = me.msg.onFileUploadComplete; - var _complete = function (data) { - - if (data.entities[0]['file-metadata']) { - var file_len = data.entities[0]['file-metadata']['content-length']; - me.msg.file_length = file_len; - me.msg.filetype = data.entities[0]['file-metadata']['content-type']; - if (file_len > 204800) { - me.msg.thumbnail = true; - } - } - - me.msg.body = { - type: me.msg.type || 'file' - , url: data.uri + '/' + data.entities[0]['uuid'] - , secret: data.entities[0]['share-secret'] - , filename: me.msg.file.filename || me.msg.filename - , size: { - width: me.msg.width || 0 - , height: me.msg.height || 0 - } - , length: me.msg.length || 0 - , file_length: me.msg.file_length || 0 - , filetype: me.msg.filetype - } - - _send(me.msg); - _tmpComplete instanceof Function && _tmpComplete(data, me.msg.id); - }; - - me.msg.onFileUploadComplete = _complete; - _utils.uploadFile.call(conn, me.msg); - } else { - if (me.msg.type === 'img') { // 添加img判断规则 wjy - _send(me.msg); - } else { - me.msg.body = { - type: me.msg.type === 'chat' ? 'txt' : me.msg.type - , msg: me.msg.msg - }; - if (me.msg.type === 'cmd') { - me.msg.body.action = me.msg.action; - } else if (me.msg.type === 'loc') { - me.msg.body.addr = me.msg.addr; - me.msg.body.lat = me.msg.lat; - me.msg.body.lng = me.msg.lng; - } - _send(me.msg); - //console.log('ooooooooooooooooooo') - } - - } - }; - - exports._msg = _Message; - exports.message = Message; -}()); diff --git a/littleApp_child/utils/sdk/src/queue.js b/littleApp_child/utils/sdk/src/queue.js deleted file mode 100644 index 54302ad..0000000 --- a/littleApp_child/utils/sdk/src/queue.js +++ /dev/null @@ -1,151 +0,0 @@ -;(function () { - function Array_h(length) { - this.array = length === undefined ? [] : new Array(length); - } - - Array_h.prototype = { - /** - * 返回数组长度 - * - * @return {Number} length [数组长度] - */ - length: function () { - return this.array.length; - }, - - at: function (index) { - return this.array[index]; - }, - - set: function (index, obj) { - this.array[index] = obj; - }, - - /** - * 向数组的末尾添加一个或多个元素,并返回新的长度。 - * - * @param {*} obj [description] - * @return {Number} length [新数组的长度] - */ - push: function (obj) { - return this.array.push(obj); - }, - - /** - * 返回数组中选定的元素 - * - * @param {Number} start [开始索引值] - * @param {Number} end [结束索引值] - * @return {Array} newArray [新的数组] - */ - slice: function (start, end) { - return this.array = this.array.slice(start, end); - }, - - concat: function (array) { - this.array = this.array.concat(array); - }, - - remove: function (index, count) { - count = count === undefined ? 1 : count; - this.array.splice(index, count); - }, - - join: function (separator) { - return this.array.join(separator); - }, - - clear: function () { - this.array.length = 0; - } - }; - - /** - * 先进先出队列 (First Input First Output) - * - * 一种先进先出的数据缓存器 - */ - var Queue = function () { - this._array_h = new Array_h(); - }; - - Queue.prototype = { - _index: 0, - - /** - * 排队 - * - * @param {Object} obj [description] - * @return {[type]} [description] - */ - push: function (obj) { - this._array_h.push(obj); - }, - - /** - * 出队 - * - * @return {Object} [description] - */ - pop: function () { - var ret = null; - if (this._array_h.length()) { - ret = this._array_h.at(this._index); - if (++this._index * 2 >= this._array_h.length()) { - this._array_h.slice(this._index); - this._index = 0; - } - } - return ret; - }, - - /** - * 返回队列中头部(即最新添加的)的动态对象 - * - * @return {Object} [description] - */ - head: function () { - var ret = null, len = this._array_h.length(); - if (len) { - ret = this._array_h.at(len - 1); - } - return ret; - }, - - /** - * 返回队列中尾部(即最早添加的)的动态对象 - * - * @return {Object} [description] - */ - tail: function () { - var ret = null, len = this._array_h.length(); - if (len) { - ret = this._array_h.at(this._index); - } - return ret; - }, - - /** - * 返回数据队列长度 - * - * @return {Number} [description] - */ - length: function () { - return this._array_h.length() - this._index; - }, - - /** - * 队列是否为空 - * - * @return {Boolean} [description] - */ - empty: function () { - return (this._array_h.length() === 0); - }, - - clear: function () { - this._array_h.clear(); - } - }; - exports.Queue = Queue; -}()); diff --git a/littleApp_child/utils/sdk/src/status.js b/littleApp_child/utils/sdk/src/status.js deleted file mode 100644 index 6d4c4dc..0000000 --- a/littleApp_child/utils/sdk/src/status.js +++ /dev/null @@ -1,87 +0,0 @@ -; -(function () { - var connIndex = 0, - uploadIndex = 100, - downloadIndex = 200, - msgIndex = 300, - statusIndex = 400; - - exports.code = { - WEBIM_CONNCTION_USER_NOT_ASSIGN_ERROR: connIndex++, - WEBIM_CONNCTION_OPEN_ERROR: connIndex++, - WEBIM_CONNCTION_AUTH_ERROR: connIndex++, - WEBIM_CONNCTION_OPEN_USERGRID_ERROR: connIndex++, - WEBIM_CONNCTION_ATTACH_ERROR: connIndex++, - WEBIM_CONNCTION_ATTACH_USERGRID_ERROR: connIndex++, - WEBIM_CONNCTION_REOPEN_ERROR: connIndex++, - WEBIM_CONNCTION_SERVER_CLOSE_ERROR: connIndex++, //7: client-side network offline (net::ERR_INTERNET_DISCONNECTED) - WEBIM_CONNCTION_SERVER_ERROR: connIndex++, //8: offline by multi login - WEBIM_CONNCTION_IQ_ERROR: connIndex++, - - WEBIM_CONNCTION_PING_ERROR: connIndex++, - WEBIM_CONNCTION_NOTIFYVERSION_ERROR: connIndex++, - WEBIM_CONNCTION_GETROSTER_ERROR: connIndex++, - WEBIM_CONNCTION_CROSSDOMAIN_ERROR: connIndex++, - WEBIM_CONNCTION_LISTENING_OUTOF_MAXRETRIES: connIndex++, - WEBIM_CONNCTION_RECEIVEMSG_CONTENTERROR: connIndex++, - WEBIM_CONNCTION_DISCONNECTED: connIndex++, //16: server-side close the websocket connection - WEBIM_CONNCTION_AJAX_ERROR: connIndex++, - WEBIM_CONNCTION_JOINROOM_ERROR: connIndex++, - WEBIM_CONNCTION_GETROOM_ERROR: connIndex++, - - WEBIM_CONNCTION_GETROOMINFO_ERROR: connIndex++, - WEBIM_CONNCTION_GETROOMMEMBER_ERROR: connIndex++, - WEBIM_CONNCTION_GETROOMOCCUPANTS_ERROR: connIndex++, - WEBIM_CONNCTION_LOAD_CHATROOM_ERROR: connIndex++, - WEBIM_CONNCTION_NOT_SUPPORT_CHATROOM_ERROR: connIndex++, - WEBIM_CONNCTION_JOINCHATROOM_ERROR: connIndex++, - WEBIM_CONNCTION_QUITCHATROOM_ERROR: connIndex++, - WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR: connIndex++, - WEBIM_CONNCTION_TOKEN_NOT_ASSIGN_ERROR: connIndex++, - WEBIM_CONNCTION_SESSIONID_NOT_ASSIGN_ERROR: connIndex++, - - WEBIM_CONNCTION_RID_NOT_ASSIGN_ERROR: connIndex++, - WEBIM_CONNCTION_CALLBACK_INNER_ERROR: connIndex++, - WEBIM_CONNCTION_CLIENT_OFFLINE: connIndex++, //32: client offline - WEBIM_CONNCTION_CLIENT_LOGOUT: connIndex++, //33: client logout - - - WEBIM_UPLOADFILE_BROWSER_ERROR: uploadIndex++, - WEBIM_UPLOADFILE_ERROR: uploadIndex++, - WEBIM_UPLOADFILE_NO_LOGIN: uploadIndex++, - WEBIM_UPLOADFILE_NO_FILE: uploadIndex++, - - - WEBIM_DOWNLOADFILE_ERROR: downloadIndex++, - WEBIM_DOWNLOADFILE_NO_LOGIN: downloadIndex++, - WEBIM_DOWNLOADFILE_BROWSER_ERROR: downloadIndex++, - - - WEBIM_MESSAGE_REC_TEXT: msgIndex++, - WEBIM_MESSAGE_REC_TEXT_ERROR: msgIndex++, - WEBIM_MESSAGE_REC_EMOTION: msgIndex++, - WEBIM_MESSAGE_REC_PHOTO: msgIndex++, - WEBIM_MESSAGE_REC_AUDIO: msgIndex++, - WEBIM_MESSAGE_REC_AUDIO_FILE: msgIndex++, - WEBIM_MESSAGE_REC_VEDIO: msgIndex++, - WEBIM_MESSAGE_REC_VEDIO_FILE: msgIndex++, - WEBIM_MESSAGE_REC_FILE: msgIndex++, - WEBIM_MESSAGE_SED_TEXT: msgIndex++, - WEBIM_MESSAGE_SED_EMOTION: msgIndex++, - WEBIM_MESSAGE_SED_PHOTO: msgIndex++, - WEBIM_MESSAGE_SED_AUDIO: msgIndex++, - WEBIM_MESSAGE_SED_AUDIO_FILE: msgIndex++, - WEBIM_MESSAGE_SED_VEDIO: msgIndex++, - WEBIM_MESSAGE_SED_VEDIO_FILE: msgIndex++, - WEBIM_MESSAGE_SED_FILE: msgIndex++, - - - STATUS_INIT: statusIndex++, - STATUS_DOLOGIN_USERGRID: statusIndex++, - STATUS_DOLOGIN_IM: statusIndex++, - STATUS_OPENED: statusIndex++, - STATUS_CLOSING: statusIndex++, - STATUS_CLOSED: statusIndex++, - STATUS_ERROR: statusIndex++ - }; -}()); diff --git a/littleApp_child/utils/sdk/src/utils.js b/littleApp_child/utils/sdk/src/utils.js deleted file mode 100644 index 24150fc..0000000 --- a/littleApp_child/utils/sdk/src/utils.js +++ /dev/null @@ -1,832 +0,0 @@ -; -(function () { - - var EMPTYFN = function () { - }; - var _code = require('./status').code; - var WEBIM_FILESIZE_LIMIT = 10485760; - - var _createStandardXHR = function () { - try { - return new window.XMLHttpRequest(); - } catch (e) { - return false; - } - }; - - var _createActiveXHR = function () { - try { - return new window.ActiveXObject('Microsoft.XMLHTTP'); - } catch (e) { - return false; - } - }; - - var _xmlrequest = function (crossDomain) { - return false; - crossDomain = crossDomain || true; - var temp = _createStandardXHR() || _createActiveXHR(); - - if ('withCredentials' in temp) { - return temp; - } - if (!crossDomain) { - return temp; - } - if (typeof window.XDomainRequest === 'undefined') { - return temp; - } - var xhr = new XDomainRequest(); - xhr.readyState = 0; - xhr.status = 100; - xhr.onreadystatechange = EMPTYFN; - xhr.onload = function () { - xhr.readyState = 4; - xhr.status = 200; - - var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); - xmlDoc.async = 'false'; - xmlDoc.loadXML(xhr.responseText); - xhr.responseXML = xmlDoc; - xhr.response = xhr.responseText; - xhr.onreadystatechange(); - }; - xhr.ontimeout = xhr.onerror = function () { - xhr.readyState = 4; - xhr.status = 500; - xhr.onreadystatechange(); - }; - return xhr; - }; - - var _hasFlash = (function () { - return false; - - if ('ActiveXObject' in window) { - try { - return new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); - } catch (ex) { - return 0; - } - } else { - if (navigator.plugins && navigator.plugins.length > 0) { - return navigator.plugins['Shockwave Flash']; - } - } - return 0; - }()); - - var _tmpUtilXHR = _xmlrequest(), - _hasFormData = typeof FormData !== 'undefined', - _hasBlob = typeof Blob !== 'undefined', - _isCanSetRequestHeader = _tmpUtilXHR.setRequestHeader || false, - _hasOverrideMimeType = _tmpUtilXHR.overrideMimeType || false, - _isCanUploadFileAsync = _isCanSetRequestHeader && _hasFormData, - _isCanUploadFile = _isCanUploadFileAsync || _hasFlash, - _isCanDownLoadFile = _isCanSetRequestHeader && (_hasBlob || _hasOverrideMimeType); - - if (!Object.keys) { - Object.keys = (function () { - 'use strict'; - var hasOwnProperty = Object.prototype.hasOwnProperty, - hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), - dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ], - dontEnumsLength = dontEnums.length; - - return function (obj) { - if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { - throw new TypeError('Object.keys called on non-object'); - } - - var result = [], prop, i; - - for (prop in obj) { - if (hasOwnProperty.call(obj, prop)) { - result.push(prop); - } - } - - if (hasDontEnumBug) { - for (i = 0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) { - result.push(dontEnums[i]); - } - } - } - return result; - }; - }()); - } - - var utils = { - hasFormData: _hasFormData, - - hasBlob: _hasBlob, - - emptyfn: EMPTYFN, - - isCanSetRequestHeader: _isCanSetRequestHeader, - - hasOverrideMimeType: _hasOverrideMimeType, - - isCanUploadFileAsync: _isCanUploadFileAsync, - - isCanUploadFile: _isCanUploadFile, - - isCanDownLoadFile: _isCanDownLoadFile, - - isSupportWss: (function () { - return true; - var notSupportList = [ - //1: QQ browser X5 core - /MQQBrowser[\/]5([.]\d+)?\sTBS/ - - //2: etc. - //... - ]; - - if (!window.WebSocket) { - return false; - } - - var ua = window.navigator.userAgent; - for (var i = 0, l = notSupportList.length; i < l; i++) { - if (notSupportList[i].test(ua)) { - return false; - } - } - return true; - }()), - - getIEVersion: (function () { - return null; - var ua = navigator.userAgent, matches, tridentMap = {'4': 8, '5': 9, '6': 10, '7': 11}; - - matches = ua.match(/MSIE (\d+)/i); - - if (matches && matches[1]) { - return +matches[1]; - } - matches = ua.match(/Trident\/(\d+)/i); - if (matches && matches[1]) { - return tridentMap[matches[1]] || null; - } - return null; - }()), - - - stringify: function (json) { - if (typeof JSON !== 'undefined' && JSON.stringify) { - return JSON.stringify(json); - } else { - var s = '', - arr = []; - - var iterate = function (json) { - var isArr = false; - - if (Object.prototype.toString.call(json) === '[object Array]') { - arr.push(']', '['); - isArr = true; - } else if (Object.prototype.toString.call(json) === '[object Object]') { - arr.push('}', '{'); - } - - for (var o in json) { - if (Object.prototype.toString.call(json[o]) === '[object Null]') { - json[o] = 'null'; - } else if (Object.prototype.toString.call(json[o]) === '[object Undefined]') { - json[o] = 'undefined'; - } - - if (json[o] && typeof json[o] === 'object') { - s += ',' + (isArr ? '' : '"' + o + '":' + (isArr ? '"' : '')) + iterate(json[o]) + ''; - } else { - s += ',"' + (isArr ? '' : o + '":"') + json[o] + '"'; - } - } - - if (s != '') { - s = s.slice(1); - } - - return arr.pop() + s + arr.pop(); - }; - return iterate(json); - } - }, - registerUser: function (options) { - var orgName = options.orgName || ''; - var appName = options.appName || ''; - var appKey = options.appKey || ''; - var suc = options.success || EMPTYFN; - var err = options.error || EMPTYFN; - - if (!orgName && !appName && appKey) { - var devInfos = appKey.split('#'); - if (devInfos.length === 2) { - orgName = devInfos[0]; - appName = devInfos[1]; - } - } - if (!orgName && !appName) { - err({ - type: _code.WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR - }); - return; - } - - - var https = options.https || https; - var apiUrl = options.apiUrl; - var restUrl = apiUrl + '/' + orgName + '/' + appName + '/users'; - - var userjson = { - username: options.username, - password: options.password, - nickname: options.nickname || '' - }; - var userinfo = utils.stringify(userjson); - var options = { - url: restUrl, - data: userinfo, - success: suc, - error: err - }; - return utils.ajax(options); - }, - login: function (options) { - var options = options || {}; - var suc = options.success || EMPTYFN; - var err = options.error || EMPTYFN; - - var appKey = options.appKey || ''; - var devInfos = appKey.split('#'); - if (devInfos.length !== 2) { - err({ - type: _code.WEBIM_CONNCTION_APPKEY_NOT_ASSIGN_ERROR - }); - return false; - } - - var orgName = devInfos[0]; - var appName = devInfos[1]; - var https = https || options.https; - var user = options.user || ''; - var pwd = options.pwd || ''; - - var apiUrl = options.apiUrl; - - var loginJson = { - grant_type: 'password', - username: user, - password: pwd, - timestamp: +new Date() - }; - var loginfo = utils.stringify(loginJson); - - var options = { - url: apiUrl + '/' + orgName + '/' + appName + '/token', - data: loginfo, - success: suc, - error: err - }; - return utils.ajax(options); - }, - - getFileUrl: function (fileInputId) { - - var uri = { - url: '', - filename: '', - filetype: '', - data: '' - }; - - var fileObj = typeof fileInputId === 'string' ? document.getElementById(fileInputId) : fileInputId; - - if (!utils.isCanUploadFileAsync || !fileObj) { - return uri; - } - try { - if (window.URL.createObjectURL) { - var fileItems = fileObj.files; //一个对象,文件列表 - if (fileItems.length > 0) { - var u = fileItems.item(0); // 有关选取文件的信息 - uri.data = u; - uri.url = window.URL.createObjectURL(u); //指向该文件的URL - uri.filename = u.name || ''; - } - } else { // IE - var u = document.getElementById(fileInputId).value; - uri.url = u; - var pos1 = u.lastIndexOf('/'); - var pos2 = u.lastIndexOf('\\'); - var pos = Math.max(pos1, pos2); - if (pos < 0) - uri.filename = u; - else - uri.filename = u.substring(pos + 1); - } - var index = uri.filename.lastIndexOf('.'); - if (index != -1) { - uri.filetype = uri.filename.substring(index + 1).toLowerCase(); - } - return uri; - - } catch (e) { - throw e; - } - }, - - getFileSize: function (fileInputId) { - var file = document.getElementById(fileInputId); - var fileSize = 0; - if (file) { - if (file.files) { - if (file.files.length > 0) { - fileSize = file.files[0].size; - } - } else if (file.select && 'ActiveXObject' in window) { - file.select(); - var fileobject = new ActiveXObject('Scripting.FileSystemObject'); - var file = fileobject.GetFile(file.value); - fileSize = file.Size; - } - } - return fileSize; - }, - - hasFlash: _hasFlash, - - trim: function (str) { - - str = typeof str === 'string' ? str : ''; - - return str.trim - ? str.trim() - : str.replace(/^\s|\s$/g, ''); - }, - - parseEmoji: function (msg) { - if (typeof WebIM.Emoji === 'undefined' || typeof WebIM.Emoji.map === 'undefined') { - return msg; - } else { - var emoji = WebIM.Emoji, - reg = null; - - for (var face in emoji.map) { - if (emoji.map.hasOwnProperty(face)) { - while (msg.indexOf(face) > -1) { - msg = msg.replace(face, ''); - } - } - } - return msg; - } - }, - - parseLink: function (msg) { - - var reg = /(https?\:\/\/|www\.)([a-zA-Z0-9-]+(\.[a-zA-Z0-9]+)+)(\:[0-9]{2,4})?\/?((\.[:_0-9a-zA-Z-]+)|[:_0-9a-zA-Z-]*\/?)*\??[:_#@*&%0-9a-zA-Z-/=]*/gm; - - msg = msg.replace(reg, function (v) { - - var prefix = /^https?/gm.test(v); - - return "" - + v - + ""; - - }); - - return msg; - - }, - - parseJSON: function (data) { - - if (window.JSON && window.JSON.parse) { - return window.JSON.parse(data + ''); - } - - var requireNonComma, - depth = null, - str = utils.trim(data + ''); - - return str && !utils.trim( - str.replace(/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g - , function (token, comma, open, close) { - - if (requireNonComma && comma) { - depth = 0; - } - - if (depth === 0) { - return token; - } - - requireNonComma = open || comma; - depth += !close - !open; - return ''; - }) - ) - ? (Function('return ' + str))() - : (Function('Invalid JSON: ' + data))(); - }, - - parseUploadResponse: function (response) { - return response.indexOf('callback') > -1 ? //lte ie9 - response.slice(9, -1) : response; - }, - - parseDownloadResponse: function (response) { - return ((response && response.type && response.type === 'application/json') - || 0 > Object.prototype.toString.call(response).indexOf('Blob')) - ? this.url + '?token=' : window.URL.createObjectURL(response); - }, - - uploadFile: function (options) { - var options = options || {}; - options.onFileUploadProgress = options.onFileUploadProgress || EMPTYFN; - options.onFileUploadComplete = options.onFileUploadComplete || EMPTYFN; - options.onFileUploadError = options.onFileUploadError || EMPTYFN; - options.onFileUploadCanceled = options.onFileUploadCanceled || EMPTYFN; - - var acc = options.accessToken || this.context.accessToken; - if (!acc) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_NO_LOGIN - , id: options.id - }); - return; - } - - var orgName, appName, devInfos; - var appKey = options.appKey || this.context.appKey || ''; - - if (appKey) { - devInfos = appKey.split('#'); - orgName = devInfos[0]; - appName = devInfos[1]; - } - - if (!orgName && !appName) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR - , id: options.id - }); - return; - } - - var apiUrl = options.apiUrl; - var uploadUrl = apiUrl + '/' + orgName + '/' + appName + '/chatfiles'; - - if (!utils.isCanUploadFileAsync) { - if (utils.hasFlash && typeof options.flashUpload === 'function') { - options.flashUpload && options.flashUpload(uploadUrl, options); - } else { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_BROWSER_ERROR - , id: options.id - }); - } - return; - } - - var fileSize = options.file.data ? options.file.data.size : undefined; - if (fileSize > WEBIM_FILESIZE_LIMIT) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR - , id: options.id - }); - return; - } else if (fileSize <= 0) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR - , id: options.id - }); - return; - } - - var xhr = utils.xmlrequest(); - var onError = function (e) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR, - id: options.id, - xhr: xhr - }); - }; - if (xhr.upload) { - xhr.upload.addEventListener('progress', options.onFileUploadProgress, false); - } - if (xhr.addEventListener) { - xhr.addEventListener('abort', options.onFileUploadCanceled, false); - xhr.addEventListener('load', function (e) { - try { - var json = utils.parseJSON(xhr.responseText); - try { - options.onFileUploadComplete(json); - } catch (e) { - options.onFileUploadError({ - type: _code.WEBIM_CONNCTION_CALLBACK_INNER_ERROR - , data: e - }); - } - } catch (e) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR, - data: xhr.responseText, - id: options.id, - xhr: xhr - }); - } - }, false); - xhr.addEventListener('error', onError, false); - } else if (xhr.onreadystatechange) { - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (ajax.status === 200) { - try { - var json = utils.parseJSON(xhr.responseText); - options.onFileUploadComplete(json); - } catch (e) { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR, - data: xhr.responseText, - id: options.id, - xhr: xhr - }); - } - } else { - options.onFileUploadError({ - type: _code.WEBIM_UPLOADFILE_ERROR, - data: xhr.responseText, - id: options.id, - xhr: xhr - }); - } - } else { - xhr.abort(); - options.onFileUploadCanceled(); - } - } - } - - xhr.open('POST', uploadUrl); - - xhr.setRequestHeader('restrict-access', 'true'); - xhr.setRequestHeader('Accept', '*/*');// Android QQ browser has some problem with this attribute. - xhr.setRequestHeader('Authorization', 'Bearer ' + acc); - - var formData = new FormData(); - formData.append('file', options.file.data); - xhr.send(formData); - }, - - - download: function (options) { - options.onFileDownloadComplete = options.onFileDownloadComplete || EMPTYFN; - options.onFileDownloadError = options.onFileDownloadError || EMPTYFN; - - var accessToken = options.accessToken || this.context.accessToken; - if (!accessToken) { - options.onFileDownloadError({ - type: _code.WEBIM_DOWNLOADFILE_NO_LOGIN, - id: options.id - }); - return; - } - - var onError = function (e) { - options.onFileDownloadError({ - type: _code.WEBIM_DOWNLOADFILE_ERROR, - id: options.id, - xhr: xhr - }); - }; - - if (!utils.isCanDownLoadFile) { - options.onFileDownloadComplete(); - return; - } - var xhr = utils.xmlrequest(); - if ('addEventListener' in xhr) { - xhr.addEventListener('load', function (e) { - options.onFileDownloadComplete(xhr.response, xhr); - }, false); - xhr.addEventListener('error', onError, false); - } else if ('onreadystatechange' in xhr) { - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (ajax.status === 200) { - options.onFileDownloadComplete(xhr.response, xhr); - } else { - options.onFileDownloadError({ - type: _code.WEBIM_DOWNLOADFILE_ERROR, - id: options.id, - xhr: xhr - }); - } - } else { - xhr.abort(); - options.onFileDownloadError({ - type: _code.WEBIM_DOWNLOADFILE_ERROR, - id: options.id, - xhr: xhr - }); - } - } - } - - var method = options.method || 'GET'; - var resType = options.responseType || 'blob'; - var mimeType = options.mimeType || 'text/plain; charset=x-user-defined'; - xhr.open(method, options.url); - if (typeof Blob !== 'undefined') { - xhr.responseType = resType; - } else { - xhr.overrideMimeType(mimeType); - } - - var innerHeaer = { - 'X-Requested-With': 'XMLHttpRequest', - 'Accept': 'application/octet-stream', - 'share-secret': options.secret, - 'Authorization': 'Bearer ' + accessToken - }; - var headers = options.headers || {}; - for (var key in headers) { - innerHeaer[key] = headers[key]; - } - for (var key in innerHeaer) { - if (innerHeaer[key]) { - xhr.setRequestHeader(key, innerHeaer[key]); - } - } - xhr.send(null); - }, - - parseTextMessage: function (message, faces) { - if (typeof message !== 'string') { - return; - } - - if (Object.prototype.toString.call(faces) !== '[object Object]') { - return { - isemoji: false, - body: [ - { - type: 'txt', - data: message - } - ] - }; - } - var receiveMsg = message; - var emessage = []; - var expr = /\[[^[\]]{2,3}\]/mg; - var emoji = receiveMsg.match(expr); - //console.log(emoji) - if (!emoji || emoji.length < 1) { - return { - isemoji: false, - body: [ - { - type: 'txt', - data: message - } - ] - }; - } - - var isemoji = false; - for (var i = 0; i < emoji.length; i++) { - var tmsg = receiveMsg.substring(0, receiveMsg.indexOf(emoji[i])); - var existEmoji = faces.map[emoji[i]]; - if (tmsg) { - emessage.push({ - type: 'txt', - data: tmsg - }); - } - if (!existEmoji) { - emessage.push({ - type: 'txt', - data: emoji[i] - }); - continue; - } - var emojiStr = faces.map ? existEmoji : null; - - if (emojiStr) { - isemoji = true; - emessage.push({ - type: 'emoji', - data: emojiStr - }); - } else { - emessage.push({ - type: 'txt', - data: emoji[i] - }); - } - var restMsgIndex = receiveMsg.indexOf(emoji[i]) + emoji[i].length; - receiveMsg = receiveMsg.substring(restMsgIndex); - } - if (receiveMsg) { - emessage.push({ - type: 'txt', - data: receiveMsg - }); - } - if (isemoji) { - return { - isemoji: isemoji, - body: emessage - }; - } - return { - isemoji: false, - body: [ - { - type: 'txt', - data: message - } - ] - }; - }, - - xmlrequest: _xmlrequest, - - - ajax: function (options) { - var suc = options.success || EMPTYFN; - var error = options.error || EMPTYFN; - - var type = options.type || 'POST', - data = options.data || null, - tempData = ''; - - if (type.toLowerCase() === 'get' && data) { - for (var o in data) { - if (data.hasOwnProperty(o)) { - tempData += o + '=' + data[o] + '&'; - } - } - tempData = tempData ? tempData.slice(0, -1) : tempData; - options.url += (options.url.indexOf('?') > 0 ? '&' : '?') + (tempData ? tempData + '&' : tempData) + '_v=' + new Date().getTime(); - data = null; - tempData = null; - } - wx.request({ - url: options.url, - data: options.data, - header: { - 'content-type': 'application/json' - }, - method: type, - success: function(res){ - //console.log(res) - if(res.statusCode == '200') { - suc(res) - }else { - error(res) - } - } - }) - }, - - ts: function () { - var d = new Date(); - var Hours = d.getHours(); //获取当前小时数(0-23) - var Minutes = d.getMinutes(); //获取当前分钟数(0-59) - var Seconds = d.getSeconds(); //获取当前秒数(0-59) - var Milliseconds = d.getMilliseconds(); //获取当前毫秒 - return (Hours < 10 ? "0" + Hours : Hours) + ':' + (Minutes < 10 ? "0" + Minutes : Minutes) + ':' + (Seconds < 10 ? "0" + Seconds : Seconds) + ':' + Milliseconds + ' '; - }, - - getObjectKey: function (obj, val) { - for (var key in obj) { - if (obj[key] == val) { - return key; - } - } - return ''; - } - - }; - - - exports.utils = utils; -}()); diff --git a/littleApp_child/utils/strophe.js b/littleApp_child/utils/strophe.js deleted file mode 100644 index b9561fd..0000000 --- a/littleApp_child/utils/strophe.js +++ /dev/null @@ -1,6027 +0,0 @@ -/** File: strophe.js - * A JavaScript library for writing XMPP clients. - * - * This library uses either Bidirectional-streams Over Synchronous HTTP (BOSH) - * to emulate a persistent, stateful, two-way connection to an XMPP server or - * alternatively WebSockets. - * - * More information on BOSH can be found in XEP 124. - * For more information on XMPP-over WebSocket see this RFC: - * http://tools.ietf.org/html/rfc7395 - */ - -/* All of the Strophe globals are defined in this special function below so - * that references to the globals become closures. This will ensure that - * on page reload, these references will still be available to callbacks - * that are still executing. - */ -// //console.log(window,document) - -var isSocketConnnected = false; -var xmldom = require('./xmldom/dom-parser'); -// //console.log('xml', xmldom, typeof xmldom.DOMParser); -var DOMParser = xmldom.DOMParser; -//console.log('DOMParser inited'); -let document = new DOMParser().parseFromString("\n", 'text/xml'); -//console.log('document inited'); -var window = window || {}; -window.DOMParser = DOMParser; - -//console.log('strophe ...') -var Strophe = null; -var $build = null; -var $msg = null; -var $iq = null; -var $pres = null; -/* jshint ignore:start */ -(function (callback) { - /* jshint ignore:end */ - -// This code was written by Tyler Akins and has been placed in the -// public domain. It would be nice if you left this header intact. -// Base64 code from Tyler Akins -- http://rumkin.com -//module.exports = callback(); - - (function (root, factory) { - //console.log(typeof define, define.amd, root) - if (typeof define === 'function' && define.amd) { - define('strophe-base64', function () { - return factory(); - }); - } - else { - // Browser globals - root.Base64 = factory(); - } - }(this, function () { - var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - - var obj = { - /** - * Encodes a string in base64 - * @param {String} input The string to encode in base64. - */ - encode: function (input) { - var output = ""; - var chr1, chr2, chr3; - var enc1, enc2, enc3, enc4; - var i = 0; - - do { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc2 = ((chr1 & 3) << 4); - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - - output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + - keyStr.charAt(enc3) + keyStr.charAt(enc4); - } while (i < input.length); - - return output; - }, - - /** - * Decodes a base64 string. - * @param {String} input The string to decode. - */ - decode: function (input) { - var output = ""; - var chr1, chr2, chr3; - var enc1, enc2, enc3, enc4; - var i = 0; - - // remove all characters that are not A-Z, a-z, 0-9, +, /, or = - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - - do { - enc1 = keyStr.indexOf(input.charAt(i++)); - enc2 = keyStr.indexOf(input.charAt(i++)); - enc3 = keyStr.indexOf(input.charAt(i++)); - enc4 = keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 != 64) { - output = output + String.fromCharCode(chr2); - } - if (enc4 != 64) { - output = output + String.fromCharCode(chr3); - } - } while (i < input.length); - - return output; - } - }; - return obj; - })); - /* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Version 2.1a Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */ - - /* jshint undef: true, unused: true:, noarg: true, latedef: false */ - /* global define */ - - /* Some functions and variables have been stripped for use with Strophe */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-sha1', function () { - return factory(); - }); - } else { - // Browser globals - root.SHA1 = factory(); - } - }(this, function () { - - /* - * Calculate the SHA-1 of an array of big-endian words, and a bit length - */ - function core_sha1(x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = new Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - var i, j, t, olda, oldb, oldc, oldd, olde; - for (i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - olde = e; - - for (j = 0; j < 80; j++) { - if (j < 16) { - w[j] = x[i + j]; - } - else { - w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); - } - t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return [a, b, c, d, e]; - } - - /* - * Perform the appropriate triplet combination function for the current - * iteration - */ - function sha1_ft(t, b, c, d) { - if (t < 20) { - return (b & c) | ((~b) & d); - } - if (t < 40) { - return b ^ c ^ d; - } - if (t < 60) { - return (b & c) | (b & d) | (c & d); - } - return b ^ c ^ d; - } - - /* - * Determine the appropriate additive constant for the current iteration - */ - function sha1_kt(t) { - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; - } - - /* - * Calculate the HMAC-SHA1 of a key and some data - */ - function core_hmac_sha1(key, data) { - var bkey = str2binb(key); - if (bkey.length > 16) { - bkey = core_sha1(bkey, key.length * 8); - } - - var ipad = new Array(16), opad = new Array(16); - for (var i = 0; i < 16; i++) { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * 8); - return core_sha1(opad.concat(hash), 512 + 160); - } - - /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - function safe_add(x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); - } - - /* - * Bitwise rotate a 32-bit number to the left. - */ - function rol(num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); - } - - /* - * Convert an 8-bit or 16-bit string to an array of big-endian words - * In 8-bit function, characters >255 have their hi-byte silently ignored. - */ - function str2binb(str) { - var bin = []; - var mask = 255; - for (var i = 0; i < str.length * 8; i += 8) { - bin[i >> 5] |= (str.charCodeAt(i / 8) & mask) << (24 - i % 32); - } - return bin; - } - - /* - * Convert an array of big-endian words to a string - */ - function binb2str(bin) { - var str = ""; - var mask = 255; - for (var i = 0; i < bin.length * 32; i += 8) { - str += String.fromCharCode((bin[i >> 5] >>> (24 - i % 32)) & mask); - } - return str; - } - - /* - * Convert an array of big-endian words to a base-64 string - */ - function binb2b64(binarray) { - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - var triplet, j; - for (var i = 0; i < binarray.length * 4; i += 3) { - triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) | - (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8 ) | - ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF); - for (j = 0; j < 4; j++) { - if (i * 8 + j * 6 > binarray.length * 32) { - str += "="; - } - else { - str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F); - } - } - } - return str; - } - - /* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ - return { - b64_hmac_sha1: function (key, data) { - return binb2b64(core_hmac_sha1(key, data)); - }, - b64_sha1: function (s) { - return binb2b64(core_sha1(str2binb(s), s.length * 8)); - }, - binb2str: binb2str, - core_hmac_sha1: core_hmac_sha1, - str_hmac_sha1: function (key, data) { - return binb2str(core_hmac_sha1(key, data)); - }, - str_sha1: function (s) { - return binb2str(core_sha1(str2binb(s), s.length * 8)); - }, - }; - })); - - /* - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - - /* - * Everything that isn't used by Strophe has been stripped here! - */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-md5', function () { - return factory(); - }); - } else { - // Browser globals - root.MD5 = factory(); - } - }(this, function (b) { - /* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ - var safe_add = function (x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); - }; - - /* - * Bitwise rotate a 32-bit number to the left. - */ - var bit_rol = function (num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); - }; - - /* - * Convert a string to an array of little-endian words - */ - var str2binl = function (str) { - var bin = []; - for (var i = 0; i < str.length * 8; i += 8) { - bin[i >> 5] |= (str.charCodeAt(i / 8) & 255) << (i % 32); - } - return bin; - }; - - /* - * Convert an array of little-endian words to a string - */ - var binl2str = function (bin) { - var str = ""; - for (var i = 0; i < bin.length * 32; i += 8) { - str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & 255); - } - return str; - }; - - /* - * Convert an array of little-endian words to a hex string. - */ - var binl2hex = function (binarray) { - var hex_tab = "0123456789abcdef"; - var str = ""; - for (var i = 0; i < binarray.length * 4; i++) { - str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) + - hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 )) & 0xF); - } - return str; - }; - - /* - * These functions implement the four basic operations the algorithm uses. - */ - var md5_cmn = function (q, a, b, x, s, t) { - return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); - }; - - var md5_ff = function (a, b, c, d, x, s, t) { - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); - }; - - var md5_gg = function (a, b, c, d, x, s, t) { - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); - }; - - var md5_hh = function (a, b, c, d, x, s, t) { - return md5_cmn(b ^ c ^ d, a, b, x, s, t); - }; - - var md5_ii = function (a, b, c, d, x, s, t) { - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); - }; - - /* - * Calculate the MD5 of an array of little-endian words, and a bit length - */ - var core_md5 = function (x, len) { - /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - - var olda, oldb, oldc, oldd; - for (var i = 0; i < x.length; i += 16) { - olda = a; - oldb = b; - oldc = c; - oldd = d; - - a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); - d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); - d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); - d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); - b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); - d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); - d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); - c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); - d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); - c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); - d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); - c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); - d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); - c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); - d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); - d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); - d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); - d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); - d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); - d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); - d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); - d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - } - return [a, b, c, d]; - }; - - var obj = { - /* - * These are the functions you'll usually want to call. - * They take string arguments and return either hex or base-64 encoded - * strings. - */ - hexdigest: function (s) { - return binl2hex(core_md5(str2binl(s), s.length * 8)); - }, - - hash: function (s) { - return binl2str(core_md5(str2binl(s), s.length * 8)); - } - }; - return obj; - })); - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-utils', function () { - return factory(); - }); - } else { - // Browser globals - root.stropheUtils = factory(); - } - }(this, function () { - - var utils = { - - utf16to8: function (str) { - var i, c; - var out = ""; - var len = str.length; - for (i = 0; i < len; i++) { - c = str.charCodeAt(i); - if ((c >= 0x0000) && (c <= 0x007F)) { - out += str.charAt(i); - } else if (c > 0x07FF) { - out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); - out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); - out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); - } else { - out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); - out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); - } - } - return out; - }, - - addCookies: function (cookies) { - /* Parameters: - * (Object) cookies - either a map of cookie names - * to string values or to maps of cookie values. - * - * For example: - * { "myCookie": "1234" } - * - * or: - * { "myCookie": { - * "value": "1234", - * "domain": ".example.org", - * "path": "/", - * "expires": expirationDate - * } - * } - * - * These values get passed to Strophe.Connection via - * options.cookies - */ - var cookieName, cookieObj, isObj, cookieValue, expires, domain, path; - for (cookieName in (cookies || {})) { - expires = ''; - domain = ''; - path = ''; - cookieObj = cookies[cookieName]; - isObj = typeof cookieObj == "object"; - cookieValue = escape(unescape(isObj ? cookieObj.value : cookieObj)); - if (isObj) { - expires = cookieObj.expires ? ";expires=" + cookieObj.expires : ''; - domain = cookieObj.domain ? ";domain=" + cookieObj.domain : ''; - path = cookieObj.path ? ";path=" + cookieObj.path : ''; - } - document.cookie = - cookieName + '=' + cookieValue + expires + domain + path; - } - } - }; - return utils; - })); - - /* - This program is distributed under the terms of the MIT license. - Please see the LICENSE file for details. - - Copyright 2006-2008, OGG, LLC - */ - - /* jshint undef: true, unused: true:, noarg: true, latedef: true */ - /* global define */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-polyfill', [], function () { - return factory(); - }); - } else { - // Browser globals - return factory(); - } - }(this, function () { - - /** Function: Function.prototype.bind - * Bind a function to an instance. - * - * This Function object extension method creates a bound method similar - * to those in Python. This means that the 'this' object will point - * to the instance you want. See - * MDC's bind() documentation and - * Bound Functions and Function Imports in JavaScript - * for a complete explanation. - * - * This extension already exists in some browsers (namely, Firefox 3), but - * we provide it to support those that don't. - * - * Parameters: - * (Object) obj - The object that will become 'this' in the bound function. - * (Object) argN - An option argument that will be prepended to the - * arguments given for the function call - * - * Returns: - * The bound function. - */ - if (!Function.prototype.bind) { - Function.prototype.bind = function (obj /*, arg1, arg2, ... */) { - var func = this; - var _slice = Array.prototype.slice; - var _concat = Array.prototype.concat; - var _args = _slice.call(arguments, 1); - return function () { - return func.apply(obj ? obj : this, _concat.call(_args, _slice.call(arguments, 0))); - }; - }; - } - - /** Function: Array.isArray - * This is a polyfill for the ES5 Array.isArray method. - */ - if (!Array.isArray) { - Array.isArray = function (arg) { - return Object.prototype.toString.call(arg) === '[object Array]'; - }; - } - - /** Function: Array.prototype.indexOf - * Return the index of an object in an array. - * - * This function is not supplied by some JavaScript implementations, so - * we provide it if it is missing. This code is from: - * http://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Objects:Array:indexOf - * - * Parameters: - * (Object) elt - The object to look for. - * (Integer) from - The index from which to start looking. (optional). - * - * Returns: - * The index of elt in the array or -1 if not found. - */ - if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (elt /*, from*/) { - var len = this.length; - var from = Number(arguments[1]) || 0; - from = (from < 0) ? Math.ceil(from) : Math.floor(from); - if (from < 0) { - from += len; - } - - for (; from < len; from++) { - if (from in this && this[from] === elt) { - return from; - } - } - return -1; - }; - } - })); - - - /** Function: Array.prototype.forEach - * - * This function is not available in IE < 9 - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach - */ - if (!Array.prototype.forEach) { - Array.prototype.forEach = function (callback, thisArg) { - var T, k; - if (this === null) { - throw new TypeError(' this is null or not defined'); - } - - // 1. Let O be the result of calling toObject() passing the - // |this| value as the argument. - var O = Object(this); - // 2. Let lenValue be the result of calling the Get() internal - // method of O with the argument "length". - // 3. Let len be toUint32(lenValue). - var len = O.length >>> 0; - // 4. If isCallable(callback) is false, throw a TypeError exception. - // See: http://es5.github.com/#x9.11 - if (typeof callback !== "function") { - throw new TypeError(callback + ' is not a function'); - } - // 5. If thisArg was supplied, let T be thisArg; else let - // T be undefined. - if (arguments.length > 1) { - T = thisArg; - } - // 6. Let k be 0 - k = 0; - // 7. Repeat, while k < len - while (k < len) { - var kValue; - // a. Let Pk be ToString(k). - // This is implicit for LHS operands of the in operator - // b. Let kPresent be the result of calling the HasProperty - // internal method of O with argument Pk. - // This step can be combined with c - // c. If kPresent is true, then - if (k in O) { - // i. Let kValue be the result of calling the Get internal - // method of O with argument Pk. - kValue = O[k]; - // ii. Call the Call internal method of callback with T as - // the this value and argument list containing kValue, k, and O. - callback.call(T, kValue, k, O); - } - // d. Increase k by 1. - k++; - } - // 8. return undefined - }; - } - - /* - This program is distributed under the terms of the MIT license. - Please see the LICENSE file for details. - - Copyright 2006-2008, OGG, LLC - */ - - /* jshint undef: true, unused: true:, noarg: true, latedef: true */ - /*global define, document, window, setTimeout, clearTimeout, ActiveXObject, DOMParser */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-core', [ - 'strophe-sha1', - 'strophe-base64', - 'strophe-md5', - 'strophe-utils', - "strophe-polyfill" - ], function () { - return factory.apply(this, arguments); - }); - } else { - // Browser globals - - var o = factory(root.SHA1, root.Base64, root.MD5, root.stropheUtils, root.Strophe); - root.Strophe = o.Strophe; - root.$build = o.$build; - root.$iq = o.$iq; - root.$msg = o.$msg; - root.$pres = o.$pres; - root.SHA1 = o.SHA1; - root.Base64 = o.Base64; - root.MD5 = o.MD5; - root.b64_hmac_sha1 = o.SHA1.b64_hmac_sha1; - root.b64_sha1 = o.SHA1.b64_sha1; - root.str_hmac_sha1 = o.SHA1.str_hmac_sha1; - root.str_sha1 = o.SHA1.str_sha1; - //console.log(root); - module.exports = root; - } - }(this, function (SHA1, Base64, MD5, utils, Strophe) { - - var Strophe; - - /** Function: $build - * Create a Strophe.Builder. - * This is an alias for 'new Strophe.Builder(name, attrs)'. - * - * Parameters: - * (String) name - The root element name. - * (Object) attrs - The attributes for the root element in object notation. - * - * Returns: - * A new Strophe.Builder object. - */ - function $build(name, attrs) { - return new Strophe.Builder(name, attrs); - } - - /** Function: $msg - * Create a Strophe.Builder with a element as the root. - * - * Parameters: - * (Object) attrs - The element attributes in object notation. - * - * Returns: - * A new Strophe.Builder object. - */ - function $msg(attrs) { - return new Strophe.Builder("message", attrs); - } - - /** Function: $iq - * Create a Strophe.Builder with an element as the root. - * - * Parameters: - * (Object) attrs - The element attributes in object notation. - * - * Returns: - * A new Strophe.Builder object. - */ - function $iq(attrs) { - return new Strophe.Builder("iq", attrs); - } - - /** Function: $pres - * Create a Strophe.Builder with a element as the root. - * - * Parameters: - * (Object) attrs - The element attributes in object notation. - * - * Returns: - * A new Strophe.Builder object. - */ - function $pres(attrs) { - return new Strophe.Builder("presence", attrs); - } - - /** Class: Strophe - * An object container for all Strophe library functions. - * - * This class is just a container for all the objects and constants - * used in the library. It is not meant to be instantiated, but to - * provide a namespace for library objects, constants, and functions. - */ - Strophe = { - /** Constant: VERSION - * The version of the Strophe library. Unreleased builds will have - * a version of head-HASH where HASH is a partial revision. - */ - VERSION: "1.2.9", - - /** Constants: XMPP Namespace Constants - * Common namespace constants from the XMPP RFCs and XEPs. - * - * NS.HTTPBIND - HTTP BIND namespace from XEP 124. - * NS.BOSH - BOSH namespace from XEP 206. - * NS.CLIENT - Main XMPP client namespace. - * NS.AUTH - Legacy authentication namespace. - * NS.ROSTER - Roster operations namespace. - * NS.PROFILE - Profile namespace. - * NS.DISCO_INFO - Service discovery info namespace from XEP 30. - * NS.DISCO_ITEMS - Service discovery items namespace from XEP 30. - * NS.MUC - Multi-User Chat namespace from XEP 45. - * NS.SASL - XMPP SASL namespace from RFC 3920. - * NS.STREAM - XMPP Streams namespace from RFC 3920. - * NS.BIND - XMPP Binding namespace from RFC 3920. - * NS.SESSION - XMPP Session namespace from RFC 3920. - * NS.XHTML_IM - XHTML-IM namespace from XEP 71. - * NS.XHTML - XHTML body namespace from XEP 71. - */ - NS: { - HTTPBIND: "http://jabber.org/protocol/httpbind", - BOSH: "urn:xmpp:xbosh", - CLIENT: "jabber:client", - AUTH: "jabber:iq:auth", - ROSTER: "jabber:iq:roster", - PROFILE: "jabber:iq:profile", - DISCO_INFO: "http://jabber.org/protocol/disco#info", - DISCO_ITEMS: "http://jabber.org/protocol/disco#items", - MUC: "http://jabber.org/protocol/muc", - SASL: "urn:ietf:params:xml:ns:xmpp-sasl", - STREAM: "http://etherx.jabber.org/streams", - FRAMING: "urn:ietf:params:xml:ns:xmpp-framing", - BIND: "urn:ietf:params:xml:ns:xmpp-bind", - SESSION: "urn:ietf:params:xml:ns:xmpp-session", - VERSION: "jabber:iq:version", - STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas", - XHTML_IM: "http://jabber.org/protocol/xhtml-im", - XHTML: "http://www.w3.org/1999/xhtml" - }, - - /** Constants: XHTML_IM Namespace - * contains allowed tags, tag attributes, and css properties. - * Used in the createHtml function to filter incoming html into the allowed XHTML-IM subset. - * See http://xmpp.org/extensions/xep-0071.html#profile-summary for the list of recommended - * allowed tags and their attributes. - */ - XHTML: { - tags: ['a', 'blockquote', 'br', 'cite', 'em', 'img', 'li', 'ol', 'p', 'span', 'strong', 'ul', 'body'], - attributes: { - 'a': ['href'], - 'blockquote': ['style'], - 'br': [], - 'cite': ['style'], - 'em': [], - 'img': ['src', 'alt', 'style', 'height', 'width'], - 'li': ['style'], - 'ol': ['style'], - 'p': ['style'], - 'span': ['style'], - 'strong': [], - 'ul': ['style'], - 'body': [] - }, - css: ['background-color', 'color', 'font-family', 'font-size', 'font-style', 'font-weight', 'margin-left', 'margin-right', 'text-align', 'text-decoration'], - /** Function: XHTML.validTag - * - * Utility method to determine whether a tag is allowed - * in the XHTML_IM namespace. - * - * XHTML tag names are case sensitive and must be lower case. - */ - validTag: function (tag) { - for (var i = 0; i < Strophe.XHTML.tags.length; i++) { - if (tag == Strophe.XHTML.tags[i]) { - return true; - } - } - return false; - }, - /** Function: XHTML.validAttribute - * - * Utility method to determine whether an attribute is allowed - * as recommended per XEP-0071 - * - * XHTML attribute names are case sensitive and must be lower case. - */ - validAttribute: function (tag, attribute) { - if (typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) { - for (var i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - if (attribute == Strophe.XHTML.attributes[tag][i]) { - return true; - } - } - } - return false; - }, - validCSS: function (style) { - for (var i = 0; i < Strophe.XHTML.css.length; i++) { - if (style == Strophe.XHTML.css[i]) { - return true; - } - } - return false; - } - }, - - /** Constants: Connection Status Constants - * Connection status constants for use by the connection handler - * callback. - * - * Status.ERROR - An error has occurred - * Status.CONNECTING - The connection is currently being made - * Status.CONNFAIL - The connection attempt failed - * Status.AUTHENTICATING - The connection is authenticating - * Status.AUTHFAIL - The authentication attempt failed - * Status.CONNECTED - The connection has succeeded - * Status.DISCONNECTED - The connection has been terminated - * Status.DISCONNECTING - The connection is currently being terminated - * Status.ATTACHED - The connection has been attached - * Status.CONNTIMEOUT - The connection has timed out - */ - Status: { - ERROR: 0, - CONNECTING: 1, - CONNFAIL: 2, - AUTHENTICATING: 3, - AUTHFAIL: 4, - CONNECTED: 5, - DISCONNECTED: 6, - DISCONNECTING: 7, - ATTACHED: 8, - REDIRECT: 9, - CONNTIMEOUT: 10 - }, - - /** Constants: Log Level Constants - * Logging level indicators. - * - * LogLevel.DEBUG - Debug output - * LogLevel.INFO - Informational output - * LogLevel.WARN - Warnings - * LogLevel.ERROR - Errors - * LogLevel.FATAL - Fatal errors - */ - LogLevel: { - DEBUG: 0, - INFO: 1, - WARN: 2, - ERROR: 3, - FATAL: 4 - }, - - /** PrivateConstants: DOM Element Type Constants - * DOM element types. - * - * ElementType.NORMAL - Normal element. - * ElementType.TEXT - Text data element. - * ElementType.FRAGMENT - XHTML fragment element. - */ - ElementType: { - NORMAL: 1, - TEXT: 3, - CDATA: 4, - FRAGMENT: 11 - }, - - /** PrivateConstants: Timeout Values - * Timeout values for error states. These values are in seconds. - * These should not be changed unless you know exactly what you are - * doing. - * - * TIMEOUT - Timeout multiplier. A waiting request will be considered - * failed after Math.floor(TIMEOUT * wait) seconds have elapsed. - * This defaults to 1.1, and with default wait, 66 seconds. - * SECONDARY_TIMEOUT - Secondary timeout multiplier. In cases where - * Strophe can detect early failure, it will consider the request - * failed if it doesn't return after - * Math.floor(SECONDARY_TIMEOUT * wait) seconds have elapsed. - * This defaults to 0.1, and with default wait, 6 seconds. - */ - TIMEOUT: 1.1, - SECONDARY_TIMEOUT: 0.1, - - /** Function: addNamespace - * This function is used to extend the current namespaces in - * Strophe.NS. It takes a key and a value with the key being the - * name of the new namespace, with its actual value. - * For example: - * Strophe.addNamespace('PUBSUB', "http://jabber.org/protocol/pubsub"); - * - * Parameters: - * (String) name - The name under which the namespace will be - * referenced under Strophe.NS - * (String) value - The actual namespace. - */ - addNamespace: function (name, value) { - Strophe.NS[name] = value; - }, - - /** Function: forEachChild - * Map a function over some or all child elements of a given element. - * - * This is a small convenience function for mapping a function over - * some or all of the children of an element. If elemName is null, all - * children will be passed to the function, otherwise only children - * whose tag names match elemName will be passed. - * - * Parameters: - * (XMLElement) elem - The element to operate on. - * (String) elemName - The child element tag name filter. - * (Function) func - The function to apply to each child. This - * function should take a single argument, a DOM element. - */ - forEachChild: function (elem, elemName, func) { - var i, childNode; - for (i = 0; i < elem.childNodes.length; i++) { - childNode = elem.childNodes[i]; - if (childNode.nodeType == Strophe.ElementType.NORMAL && - (!elemName || this.isTagEqual(childNode, elemName))) { - func(childNode); - } - } - }, - - /** Function: isTagEqual - * Compare an element's tag name with a string. - * - * This function is case sensitive. - * - * Parameters: - * (XMLElement) el - A DOM element. - * (String) name - The element name. - * - * Returns: - * true if the element's tag name matches _el_, and false - * otherwise. - */ - isTagEqual: function (el, name) { - return el.tagName == name; - }, - - /** PrivateVariable: _xmlGenerator - * _Private_ variable that caches a DOM document to - * generate elements. - */ - _xmlGenerator: null, - - /** PrivateFunction: _makeGenerator - * _Private_ function that creates a dummy XML DOM document to serve as - * an element and text node generator. - */ - _makeGenerator: function () { - var doc; - // IE9 does implement createDocument(); however, using it will cause the browser to leak memory on page unload. - // Here, we test for presence of createDocument() plus IE's proprietary documentMode attribute, which would be - // less than 10 in the case of IE9 and below. - if (document.implementation.createDocument === undefined || - document.implementation.createDocument && document.documentMode && document.documentMode < 10) { - doc = this._getIEXmlDom(); - doc.appendChild(doc.createElement('strophe')); - } else { - doc = document.implementation - .createDocument('jabber:client', 'strophe', null); - } - return doc; - }, - - /** Function: xmlGenerator - * Get the DOM document to generate elements. - * - * Returns: - * The currently used DOM document. - */ - xmlGenerator: function () { - if (!Strophe._xmlGenerator) { - Strophe._xmlGenerator = Strophe._makeGenerator(); - } - return Strophe._xmlGenerator; - }, - - /** PrivateFunction: _getIEXmlDom - * Gets IE xml doc object - * - * Returns: - * A Microsoft XML DOM Object - * See Also: - * http://msdn.microsoft.com/en-us/library/ms757837%28VS.85%29.aspx - */ - _getIEXmlDom: function () { - var doc = null; - var docStrings = [ - "Msxml2.DOMDocument.6.0", - "Msxml2.DOMDocument.5.0", - "Msxml2.DOMDocument.4.0", - "MSXML2.DOMDocument.3.0", - "MSXML2.DOMDocument", - "MSXML.DOMDocument", - "Microsoft.XMLDOM" - ]; - - for (var d = 0; d < docStrings.length; d++) { - if (doc === null) { - try { - doc = new ActiveXObject(docStrings[d]); - } catch (e) { - doc = null; - } - } else { - break; - } - } - return doc; - }, - - /** Function: xmlElement - * Create an XML DOM element. - * - * This function creates an XML DOM element correctly across all - * implementations. Note that these are not HTML DOM elements, which - * aren't appropriate for XMPP stanzas. - * - * Parameters: - * (String) name - The name for the element. - * (Array|Object) attrs - An optional array or object containing - * key/value pairs to use as element attributes. The object should - * be in the format {'key': 'value'} or {key: 'value'}. The array - * should have the format [['key1', 'value1'], ['key2', 'value2']]. - * (String) text - The text child data for the element. - * - * Returns: - * A new XML DOM element. - */ - xmlElement: function (name) { - if (!name) { - return null; - } - - var node = Strophe.xmlGenerator().createElement(name); - // FIXME: this should throw errors if args are the wrong type or - // there are more than two optional args - var a, i, k; - for (a = 1; a < arguments.length; a++) { - var arg = arguments[a]; - if (!arg) { - continue; - } - if (typeof(arg) == "string" || - typeof(arg) == "number") { - node.appendChild(Strophe.xmlTextNode(arg)); - } else if (typeof(arg) == "object" && - typeof(arg.sort) == "function") { - for (i = 0; i < arg.length; i++) { - var attr = arg[i]; - if (typeof(attr) == "object" && - typeof(attr.sort) == "function" && - attr[1] !== undefined && - attr[1] !== null) { - node.setAttribute(attr[0], attr[1]); - } - } - } else if (typeof(arg) == "object") { - for (k in arg) { - if (arg.hasOwnProperty(k)) { - if (arg[k] !== undefined && - arg[k] !== null) { - node.setAttribute(k, arg[k]); - } - } - } - } - } - - return node; - }, - - /* Function: xmlescape - * Excapes invalid xml characters. - * - * Parameters: - * (String) text - text to escape. - * - * Returns: - * Escaped text. - */ - xmlescape: function (text) { - text = text.replace(/\&/g, "&"); - text = text.replace(//g, ">"); - text = text.replace(/'/g, "'"); - text = text.replace(/"/g, """); - return text; - }, - - /* Function: xmlunescape - * Unexcapes invalid xml characters. - * - * Parameters: - * (String) text - text to unescape. - * - * Returns: - * Unescaped text. - */ - xmlunescape: function (text) { - text = text.replace(/\&/g, "&"); - text = text.replace(/</g, "<"); - text = text.replace(/>/g, ">"); - text = text.replace(/'/g, "'"); - text = text.replace(/"/g, "\""); - return text; - }, - - /** Function: xmlTextNode - * Creates an XML DOM text node. - * - * Provides a cross implementation version of document.createTextNode. - * - * Parameters: - * (String) text - The content of the text node. - * - * Returns: - * A new XML DOM text node. - */ - xmlTextNode: function (text) { - return Strophe.xmlGenerator().createTextNode(text); - }, - - /** Function: xmlHtmlNode - * Creates an XML DOM html node. - * - * Parameters: - * (String) html - The content of the html node. - * - * Returns: - * A new XML DOM text node. - */ - xmlHtmlNode: function (html) { - var node; - //ensure text is escaped - //console.log('xmlhtmlnode init', window.DOMParser, typeof window.DOMParser) - if (window.DOMParser) { - var parser = new DOMParser(); - node = parser.parseFromString(html, "text/xml"); - } else { - node = new ActiveXObject("Microsoft.XMLDOM"); - node.async = "false"; - node.loadXML(html); - } - return node; - }, - - /** Function: getText - * Get the concatenation of all text children of an element. - * - * Parameters: - * (XMLElement) elem - A DOM element. - * - * Returns: - * A String with the concatenated text of all text element children. - */ - getText: function (elem) { - if (!elem) { - return null; - } - - var str = ""; - if (elem.childNodes.length === 0 && elem.nodeType == - Strophe.ElementType.TEXT) { - str += elem.nodeValue; - } - - for (var i = 0; i < elem.childNodes.length; i++) { - if (elem.childNodes[i].nodeType == Strophe.ElementType.TEXT) { - str += elem.childNodes[i].nodeValue; - } - } - - return Strophe.xmlescape(str); - }, - - /** Function: copyElement - * Copy an XML DOM element. - * - * This function copies a DOM element and all its descendants and returns - * the new copy. - * - * Parameters: - * (XMLElement) elem - A DOM element. - * - * Returns: - * A new, copied DOM element tree. - */ - copyElement: function (elem) { - var i, el; - if (elem.nodeType == Strophe.ElementType.NORMAL) { - el = Strophe.xmlElement(elem.tagName); - - for (i = 0; i < elem.attributes.length; i++) { - el.setAttribute(elem.attributes[i].nodeName, - elem.attributes[i].value); - } - - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.copyElement(elem.childNodes[i])); - } - } else if (elem.nodeType == Strophe.ElementType.TEXT) { - el = Strophe.xmlGenerator().createTextNode(elem.nodeValue); - } - return el; - }, - - - /** Function: createHtml - * Copy an HTML DOM element into an XML DOM. - * - * This function copies a DOM element and all its descendants and returns - * the new copy. - * - * Parameters: - * (HTMLElement) elem - A DOM element. - * - * Returns: - * A new, copied DOM element tree. - */ - createHtml: function (elem) { - var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue; - if (elem.nodeType == Strophe.ElementType.NORMAL) { - tag = elem.nodeName.toLowerCase(); // XHTML tags must be lower case. - if (Strophe.XHTML.validTag(tag)) { - try { - el = Strophe.xmlElement(tag); - for (i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - attribute = Strophe.XHTML.attributes[tag][i]; - value = elem.getAttribute(attribute); - if (typeof value == 'undefined' || value === null || value === '' || value === false || value === 0) { - continue; - } - if (attribute == 'style' && typeof value == 'object') { - if (typeof value.cssText != 'undefined') { - value = value.cssText; // we're dealing with IE, need to get CSS out - } - } - // filter out invalid css styles - if (attribute == 'style') { - css = []; - cssAttrs = value.split(';'); - for (j = 0; j < cssAttrs.length; j++) { - attr = cssAttrs[j].split(':'); - cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase(); - if (Strophe.XHTML.validCSS(cssName)) { - cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, ""); - css.push(cssName + ': ' + cssValue); - } - } - if (css.length > 0) { - value = css.join('; '); - el.setAttribute(attribute, value); - } - } else { - el.setAttribute(attribute, value); - } - } - - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } catch (e) { // invalid elements - el = Strophe.xmlTextNode(''); - } - } else { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } - } else if (elem.nodeType == Strophe.ElementType.FRAGMENT) { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } else if (elem.nodeType == Strophe.ElementType.TEXT) { - el = Strophe.xmlTextNode(elem.nodeValue); - } - return el; - }, - - /** Function: escapeNode - * Escape the node part (also called local part) of a JID. - * - * Parameters: - * (String) node - A node (or local part). - * - * Returns: - * An escaped node (or local part). - */ - escapeNode: function (node) { - if (typeof node !== "string") { - return node; - } - return node.replace(/^\s+|\s+$/g, '') - .replace(/\\/g, "\\5c") - .replace(/ /g, "\\20") - .replace(/\"/g, "\\22") - .replace(/\&/g, "\\26") - .replace(/\'/g, "\\27") - .replace(/\//g, "\\2f") - .replace(/:/g, "\\3a") - .replace(//g, "\\3e") - .replace(/@/g, "\\40"); - }, - - /** Function: unescapeNode - * Unescape a node part (also called local part) of a JID. - * - * Parameters: - * (String) node - A node (or local part). - * - * Returns: - * An unescaped node (or local part). - */ - unescapeNode: function (node) { - if (typeof node !== "string") { - return node; - } - return node.replace(/\\20/g, " ") - .replace(/\\22/g, '"') - .replace(/\\26/g, "&") - .replace(/\\27/g, "'") - .replace(/\\2f/g, "/") - .replace(/\\3a/g, ":") - .replace(/\\3c/g, "<") - .replace(/\\3e/g, ">") - .replace(/\\40/g, "@") - .replace(/\\5c/g, "\\"); - }, - - /** Function: getNodeFromJid - * Get the node portion of a JID String. - * - * Parameters: - * (String) jid - A JID. - * - * Returns: - * A String containing the node. - */ - getNodeFromJid: function (jid) { - if (jid.indexOf("@") < 0) { - return null; - } - return jid.split("@")[0]; - }, - - /** Function: getDomainFromJid - * Get the domain portion of a JID String. - * - * Parameters: - * (String) jid - A JID. - * - * Returns: - * A String containing the domain. - */ - getDomainFromJid: function (jid) { - var bare = Strophe.getBareJidFromJid(jid); - if (bare.indexOf("@") < 0) { - return bare; - } else { - var parts = bare.split("@"); - parts.splice(0, 1); - return parts.join('@'); - } - }, - - /** Function: getResourceFromJid - * Get the resource portion of a JID String. - * - * Parameters: - * (String) jid - A JID. - * - * Returns: - * A String containing the resource. - */ - getResourceFromJid: function (jid) { - var s = jid.split("/"); - if (s.length < 2) { - return null; - } - s.splice(0, 1); - return s.join('/'); - }, - - /** Function: getBareJidFromJid - * Get the bare JID from a JID String. - * - * Parameters: - * (String) jid - A JID. - * - * Returns: - * A String containing the bare JID. - */ - getBareJidFromJid: function (jid) { - return jid ? jid.split("/")[0] : null; - }, - - /** PrivateFunction: _handleError - * _Private_ function that properly logs an error to the console - */ - _handleError: function (e) { - if (typeof e.stack !== "undefined") { - Strophe.fatal(e.stack); - } - if (e.sourceURL) { - Strophe.fatal("error: " + this.handler + " " + e.sourceURL + ":" + - e.line + " - " + e.name + ": " + e.message); - } else if (e.fileName) { - Strophe.fatal("error: " + this.handler + " " + - e.fileName + ":" + e.lineNumber + " - " + - e.name + ": " + e.message); - } else { - Strophe.fatal("error: " + e.message); - } - }, - - /** Function: log - * User overrideable logging function. - * - * This function is called whenever the Strophe library calls any - * of the logging functions. The default implementation of this - * function does nothing. If client code wishes to handle the logging - * messages, it should override this with - * > Strophe.log = function (level, msg) { - * > (user code here) - * > }; - * - * Please note that data sent and received over the wire is logged - * via Strophe.Connection.rawInput() and Strophe.Connection.rawOutput(). - * - * The different levels and their meanings are - * - * DEBUG - Messages useful for debugging purposes. - * INFO - Informational messages. This is mostly information like - * 'disconnect was called' or 'SASL auth succeeded'. - * WARN - Warnings about potential problems. This is mostly used - * to report transient connection errors like request timeouts. - * ERROR - Some error occurred. - * FATAL - A non-recoverable fatal error occurred. - * - * Parameters: - * (Integer) level - The log level of the log message. This will - * be one of the values in Strophe.LogLevel. - * (String) msg - The log message. - */ - /* jshint ignore:start */ - log: function (level, msg) { - //console.log('log', level, msg); - - return; - }, - /* jshint ignore:end */ - - /** Function: debug - * Log a message at the Strophe.LogLevel.DEBUG level. - * - * Parameters: - * (String) msg - The log message. - */ - debug: function (msg) { - this.log(this.LogLevel.DEBUG, msg); - }, - - /** Function: info - * Log a message at the Strophe.LogLevel.INFO level. - * - * Parameters: - * (String) msg - The log message. - */ - info: function (msg) { - this.log(this.LogLevel.INFO, msg); - }, - - /** Function: warn - * Log a message at the Strophe.LogLevel.WARN level. - * - * Parameters: - * (String) msg - The log message. - */ - warn: function (msg) { - this.log(this.LogLevel.WARN, msg); - }, - - /** Function: error - * Log a message at the Strophe.LogLevel.ERROR level. - * - * Parameters: - * (String) msg - The log message. - */ - error: function (msg) { - this.log(this.LogLevel.ERROR, msg); - }, - - /** Function: fatal - * Log a message at the Strophe.LogLevel.FATAL level. - * - * Parameters: - * (String) msg - The log message. - */ - fatal: function (msg) { - this.log(this.LogLevel.FATAL, msg); - }, - - /** Function: serialize - * Render a DOM element and all descendants to a String. - * - * Parameters: - * (XMLElement) elem - A DOM element. - * - * Returns: - * The serialized element tree as a String. - */ - serialize: function (elem) { - var result; - - if (!elem) { - return null; - } - - if (typeof(elem.tree) === "function") { - elem = elem.tree(); - } - - var nodeName = elem.nodeName; - var i, child; - - if (elem.getAttribute("_realname")) { - nodeName = elem.getAttribute("_realname"); - } - - result = "<" + nodeName; - for (i = 0; i < elem.attributes.length; i++) { - if (elem.attributes[i].nodeName != "_realname") { - result += " " + elem.attributes[i].nodeName + - "='" + Strophe.xmlescape(elem.attributes[i].value) + "'"; - } - } - - if (elem.childNodes.length > 0) { - result += ">"; - for (i = 0; i < elem.childNodes.length; i++) { - child = elem.childNodes[i]; - switch (child.nodeType) { - case Strophe.ElementType.NORMAL: - // normal element, so recurse - result += Strophe.serialize(child); - break; - case Strophe.ElementType.TEXT: - // text element to escape values - result += Strophe.xmlescape(child.nodeValue); - break; - case Strophe.ElementType.CDATA: - // cdata section so don't escape values - result += ""; - } - } - result += ""; - } else { - result += "/>"; - } - - return result; - }, - - /** PrivateVariable: _requestId - * _Private_ variable that keeps track of the request ids for - * connections. - */ - _requestId: 0, - - /** PrivateVariable: Strophe.connectionPlugins - * _Private_ variable Used to store plugin names that need - * initialization on Strophe.Connection construction. - */ - _connectionPlugins: {}, - - /** Function: addConnectionPlugin - * Extends the Strophe.Connection object with the given plugin. - * - * Parameters: - * (String) name - The name of the extension. - * (Object) ptype - The plugin's prototype. - */ - addConnectionPlugin: function (name, ptype) { - Strophe._connectionPlugins[name] = ptype; - } - }; - - /** Class: Strophe.Builder - * XML DOM builder. - * - * This object provides an interface similar to JQuery but for building - * DOM elements easily and rapidly. All the functions except for toString() - * and tree() return the object, so calls can be chained. Here's an - * example using the $iq() builder helper. - * > $iq({to: 'you', from: 'me', type: 'get', id: '1'}) - * > .c('query', {xmlns: 'strophe:example'}) - * > .c('example') - * > .toString() - * - * The above generates this XML fragment - * > - * > - * > - * > - * > - * The corresponding DOM manipulations to get a similar fragment would be - * a lot more tedious and probably involve several helper variables. - * - * Since adding children makes new operations operate on the child, up() - * is provided to traverse up the tree. To add two children, do - * > builder.c('child1', ...).up().c('child2', ...) - * The next operation on the Builder will be relative to the second child. - */ - - /** Constructor: Strophe.Builder - * Create a Strophe.Builder object. - * - * The attributes should be passed in object notation. For example - * > var b = new Builder('message', {to: 'you', from: 'me'}); - * or - * > var b = new Builder('messsage', {'xml:lang': 'en'}); - * - * Parameters: - * (String) name - The name of the root element. - * (Object) attrs - The attributes for the root element in object notation. - * - * Returns: - * A new Strophe.Builder. - */ - Strophe.Builder = function (name, attrs) { - // Set correct namespace for jabber:client elements - if (name == "presence" || name == "message" || name == "iq") { - if (attrs && !attrs.xmlns) { - attrs.xmlns = Strophe.NS.CLIENT; - } else if (!attrs) { - attrs = {xmlns: Strophe.NS.CLIENT}; - } - } - - // Holds the tree being built. - this.nodeTree = Strophe.xmlElement(name, attrs); - - // Points to the current operation node. - this.node = this.nodeTree; - }; - - Strophe.Builder.prototype = { - /** Function: tree - * Return the DOM tree. - * - * This function returns the current DOM tree as an element object. This - * is suitable for passing to functions like Strophe.Connection.send(). - * - * Returns: - * The DOM tree as a element object. - */ - tree: function () { - return this.nodeTree; - }, - - /** Function: toString - * Serialize the DOM tree to a String. - * - * This function returns a string serialization of the current DOM - * tree. It is often used internally to pass data to a - * Strophe.Request object. - * - * Returns: - * The serialized DOM tree in a String. - */ - toString: function () { - return Strophe.serialize(this.nodeTree); - }, - - /** Function: up - * Make the current parent element the new current element. - * - * This function is often used after c() to traverse back up the tree. - * For example, to add two children to the same element - * > builder.c('child1', {}).up().c('child2', {}); - * - * Returns: - * The Stophe.Builder object. - */ - up: function () { - this.node = this.node.parentNode; - return this; - }, - - /** Function: root - * Make the root element the new current element. - * - * When at a deeply nested element in the tree, this function can be used - * to jump back to the root of the tree, instead of having to repeatedly - * call up(). - * - * Returns: - * The Stophe.Builder object. - */ - root: function () { - this.node = this.nodeTree; - return this; - }, - - /** Function: attrs - * Add or modify attributes of the current element. - * - * The attributes should be passed in object notation. This function - * does not move the current element pointer. - * - * Parameters: - * (Object) moreattrs - The attributes to add/modify in object notation. - * - * Returns: - * The Strophe.Builder object. - */ - attrs: function (moreattrs) { - for (var k in moreattrs) { - if (moreattrs.hasOwnProperty(k)) { - if (moreattrs[k] === undefined) { - this.node.removeAttribute(k); - } else { - this.node.setAttribute(k, moreattrs[k]); - } - } - } - return this; - }, - - /** Function: c - * Add a child to the current element and make it the new current - * element. - * - * This function moves the current element pointer to the child, - * unless text is provided. If you need to add another child, it - * is necessary to use up() to go back to the parent in the tree. - * - * Parameters: - * (String) name - The name of the child. - * (Object) attrs - The attributes of the child in object notation. - * (String) text - The text to add to the child. - * - * Returns: - * The Strophe.Builder object. - */ - c: function (name, attrs, text) { - var child = Strophe.xmlElement(name, attrs, text); - this.node.appendChild(child); - if (typeof text !== "string" && typeof text !== "number") { - this.node = child; - } - return this; - }, - - /** Function: cnode - * Add a child to the current element and make it the new current - * element. - * - * This function is the same as c() except that instead of using a - * name and an attributes object to create the child it uses an - * existing DOM element object. - * - * Parameters: - * (XMLElement) elem - A DOM element. - * - * Returns: - * The Strophe.Builder object. - */ - cnode: function (elem) { - var impNode; - var xmlGen = Strophe.xmlGenerator(); - try { - impNode = (xmlGen.importNode !== undefined); - } catch (e) { - impNode = false; - } - var newElem = impNode ? - xmlGen.importNode(elem, true) : - Strophe.copyElement(elem); - this.node.appendChild(newElem); - this.node = newElem; - return this; - }, - - /** Function: t - * Add a child text element. - * - * This *does not* make the child the new current element since there - * are no children of text elements. - * - * Parameters: - * (String) text - The text data to append to the current element. - * - * Returns: - * The Strophe.Builder object. - */ - t: function (text) { - var child = Strophe.xmlTextNode(text); - this.node.appendChild(child); - return this; - }, - - /** Function: h - * Replace current element contents with the HTML passed in. - * - * This *does not* make the child the new current element - * - * Parameters: - * (String) html - The html to insert as contents of current element. - * - * Returns: - * The Strophe.Builder object. - */ - h: function (html) { - var fragment = document.createElement('body'); - - // force the browser to try and fix any invalid HTML tags - fragment.innerHTML = html; - - // copy cleaned html into an xml dom - var xhtml = Strophe.createHtml(fragment); - - while (xhtml.childNodes.length > 0) { - this.node.appendChild(xhtml.childNodes[0]); - } - return this; - } - }; - - /** PrivateClass: Strophe.Handler - * _Private_ helper class for managing stanza handlers. - * - * A Strophe.Handler encapsulates a user provided callback function to be - * executed when matching stanzas are received by the connection. - * Handlers can be either one-off or persistant depending on their - * return value. Returning true will cause a Handler to remain active, and - * returning false will remove the Handler. - * - * Users will not use Strophe.Handler objects directly, but instead they - * will use Strophe.Connection.addHandler() and - * Strophe.Connection.deleteHandler(). - */ - - /** PrivateConstructor: Strophe.Handler - * Create and initialize a new Strophe.Handler. - * - * Parameters: - * (Function) handler - A function to be executed when the handler is run. - * (String) ns - The namespace to match. - * (String) name - The element name to match. - * (String) type - The element type to match. - * (String) id - The element id attribute to match. - * (String) from - The element from attribute to match. - * (Object) options - Handler options - * - * Returns: - * A new Strophe.Handler object. - */ - Strophe.Handler = function (handler, ns, name, type, id, from, options) { - this.handler = handler; - this.ns = ns; - this.name = name; - this.type = type; - this.id = id; - this.options = options || {'matchBareFromJid': false, 'ignoreNamespaceFragment': false}; - // BBB: Maintain backward compatibility with old `matchBare` option - if (this.options.matchBare) { - Strophe.warn('The "matchBare" option is deprecated, use "matchBareFromJid" instead.'); - this.options.matchBareFromJid = this.options.matchBare; - delete this.options.matchBare; - } - - if (this.options.matchBareFromJid) { - this.from = from ? Strophe.getBareJidFromJid(from) : null; - } else { - this.from = from; - } - // whether the handler is a user handler or a system handler - this.user = true; - }; - - Strophe.Handler.prototype = { - /** PrivateFunction: getNamespace - * Returns the XML namespace attribute on an element. - * If `ignoreNamespaceFragment` was passed in for this handler, then the - * URL fragment will be stripped. - * - * Parameters: - * (XMLElement) elem - The XML element with the namespace. - * - * Returns: - * The namespace, with optionally the fragment stripped. - */ - getNamespace: function (elem) { - var elNamespace = elem.getAttribute("xmlns"); - if (elNamespace && this.options.ignoreNamespaceFragment) { - elNamespace = elNamespace.split('#')[0]; - } - return elNamespace; - }, - - /** PrivateFunction: namespaceMatch - * Tests if a stanza matches the namespace set for this Strophe.Handler. - * - * Parameters: - * (XMLElement) elem - The XML element to test. - * - * Returns: - * true if the stanza matches and false otherwise. - */ - namespaceMatch: function (elem) { - var nsMatch = false; - if (!this.ns) { - return true; - } else { - var that = this; - Strophe.forEachChild(elem, null, function (elem) { - if (that.getNamespace(elem) === that.ns) { - nsMatch = true; - } - }); - nsMatch = nsMatch || this.getNamespace(elem) === this.ns; - } - return nsMatch; - }, - - /** PrivateFunction: isMatch - * Tests if a stanza matches the Strophe.Handler. - * - * Parameters: - * (XMLElement) elem - The XML element to test. - * - * Returns: - * true if the stanza matches and false otherwise. - */ - isMatch: function (elem) { - var from = elem.getAttribute('from'); - if (this.options.matchBareFromJid) { - from = Strophe.getBareJidFromJid(from); - } - var elem_type = elem.getAttribute("type"); - if (this.namespaceMatch(elem) && - (!this.name || Strophe.isTagEqual(elem, this.name)) && - (!this.type || (Array.isArray(this.type) ? this.type.indexOf(elem_type) != -1 : elem_type == this.type)) && - (!this.id || elem.getAttribute("id") == this.id) && - (!this.from || from == this.from)) { - return true; - } - return false; - }, - - /** PrivateFunction: run - * Run the callback on a matching stanza. - * - * Parameters: - * (XMLElement) elem - The DOM element that triggered the - * Strophe.Handler. - * - * Returns: - * A boolean indicating if the handler should remain active. - */ - run: function (elem) { - var result = null; - try { - result = this.handler(elem); - } catch (e) { - Strophe._handleError(e); - throw e; - } - return result; - }, - - /** PrivateFunction: toString - * Get a String representation of the Strophe.Handler object. - * - * Returns: - * A String. - */ - toString: function () { - return "{Handler: " + this.handler + "(" + this.name + "," + - this.id + "," + this.ns + ")}"; - } - }; - - /** PrivateClass: Strophe.TimedHandler - * _Private_ helper class for managing timed handlers. - * - * A Strophe.TimedHandler encapsulates a user provided callback that - * should be called after a certain period of time or at regular - * intervals. The return value of the callback determines whether the - * Strophe.TimedHandler will continue to fire. - * - * Users will not use Strophe.TimedHandler objects directly, but instead - * they will use Strophe.Connection.addTimedHandler() and - * Strophe.Connection.deleteTimedHandler(). - */ - - /** PrivateConstructor: Strophe.TimedHandler - * Create and initialize a new Strophe.TimedHandler object. - * - * Parameters: - * (Integer) period - The number of milliseconds to wait before the - * handler is called. - * (Function) handler - The callback to run when the handler fires. This - * function should take no arguments. - * - * Returns: - * A new Strophe.TimedHandler object. - */ - Strophe.TimedHandler = function (period, handler) { - this.period = period; - this.handler = handler; - this.lastCalled = new Date().getTime(); - this.user = true; - }; - - Strophe.TimedHandler.prototype = { - /** PrivateFunction: run - * Run the callback for the Strophe.TimedHandler. - * - * Returns: - * true if the Strophe.TimedHandler should be called again, and false - * otherwise. - */ - run: function () { - this.lastCalled = new Date().getTime(); - return this.handler(); - }, - - /** PrivateFunction: reset - * Reset the last called time for the Strophe.TimedHandler. - */ - reset: function () { - this.lastCalled = new Date().getTime(); - }, - - /** PrivateFunction: toString - * Get a string representation of the Strophe.TimedHandler object. - * - * Returns: - * The string representation. - */ - toString: function () { - return "{TimedHandler: " + this.handler + "(" + this.period + ")}"; - } - }; - - /** Class: Strophe.Connection - * XMPP Connection manager. - * - * This class is the main part of Strophe. It manages a BOSH or websocket - * connection to an XMPP server and dispatches events to the user callbacks - * as data arrives. It supports SASL PLAIN, SASL DIGEST-MD5, SASL SCRAM-SHA1 - * and legacy authentication. - * - * After creating a Strophe.Connection object, the user will typically - * call connect() with a user supplied callback to handle connection level - * events like authentication failure, disconnection, or connection - * complete. - * - * The user will also have several event handlers defined by using - * addHandler() and addTimedHandler(). These will allow the user code to - * respond to interesting stanzas or do something periodically with the - * connection. These handlers will be active once authentication is - * finished. - * - * To send data to the connection, use send(). - */ - - /** Constructor: Strophe.Connection - * Create and initialize a Strophe.Connection object. - * - * The transport-protocol for this connection will be chosen automatically - * based on the given service parameter. URLs starting with "ws://" or - * "wss://" will use WebSockets, URLs starting with "http://", "https://" - * or without a protocol will use BOSH. - * - * To make Strophe connect to the current host you can leave out the protocol - * and host part and just pass the path, e.g. - * - * > var conn = new Strophe.Connection("/http-bind/"); - * - * Options common to both Websocket and BOSH: - * ------------------------------------------ - * - * cookies - * ~~~~~~~ - * - * The "cookies" option allows you to pass in cookies to be added to the - * document. These cookies will then be included in the BOSH XMLHttpRequest - * or in the websocket connection. - * - * The passed in value must be a map of cookie names and string values: - * - * > { "myCookie": { - * > "value": "1234", - * > "domain": ".example.org", - * > "path": "/", - * > "expires": expirationDate - * > } - * > } - * - * Note that cookies can't be set in this way for other domains (i.e. cross-domain). - * Those cookies need to be set under those domains, for example they can be - * set server-side by making a XHR call to that domain to ask it to set any - * necessary cookies. - * - * mechanisms - * ~~~~~~~~~~ - * - * The "mechanisms" option allows you to specify the SASL mechanisms that this - * instance of Strophe.Connection (and therefore your XMPP client) will - * support. - * - * The value must be an array of objects with Strophe.SASLMechanism - * prototypes. - * - * If nothing is specified, then the following mechanisms (and their - * priorities) are registered: - * - * EXTERNAL - 60 - * OAUTHBEARER - 50 - * SCRAM-SHA1 - 40 - * DIGEST-MD5 - 30 - * PLAIN - 20 - * ANONYMOUS - 10 - * - * WebSocket options: - * ------------------ - * - * If you want to connect to the current host with a WebSocket connection you - * can tell Strophe to use WebSockets through a "protocol" attribute in the - * optional options parameter. Valid values are "ws" for WebSocket and "wss" - * for Secure WebSocket. - * So to connect to "wss://CURRENT_HOSTNAME/xmpp-websocket" you would call - * - * > var conn = new Strophe.Connection("/xmpp-websocket/", {protocol: "wss"}); - * - * Note that relative URLs _NOT_ starting with a "/" will also include the path - * of the current site. - * - * Also because downgrading security is not permitted by browsers, when using - * relative URLs both BOSH and WebSocket connections will use their secure - * variants if the current connection to the site is also secure (https). - * - * BOSH options: - * ------------- - * - * By adding "sync" to the options, you can control if requests will - * be made synchronously or not. The default behaviour is asynchronous. - * If you want to make requests synchronous, make "sync" evaluate to true: - * > var conn = new Strophe.Connection("/http-bind/", {sync: true}); - * - * You can also toggle this on an already established connection: - * > conn.options.sync = true; - * - * The "customHeaders" option can be used to provide custom HTTP headers to be - * included in the XMLHttpRequests made. - * - * The "keepalive" option can be used to instruct Strophe to maintain the - * current BOSH session across interruptions such as webpage reloads. - * - * It will do this by caching the sessions tokens in sessionStorage, and when - * "restore" is called it will check whether there are cached tokens with - * which it can resume an existing session. - * - * The "withCredentials" option should receive a Boolean value and is used to - * indicate wether cookies should be included in ajax requests (by default - * they're not). - * Set this value to true if you are connecting to a BOSH service - * and for some reason need to send cookies to it. - * In order for this to work cross-domain, the server must also enable - * credentials by setting the Access-Control-Allow-Credentials response header - * to "true". For most usecases however this setting should be false (which - * is the default). - * Additionally, when using Access-Control-Allow-Credentials, the - * Access-Control-Allow-Origin header can't be set to the wildcard "*", but - * instead must be restricted to actual domains. - * - * The "contentType" option can be set to change the default Content-Type - * of "text/xml; charset=utf-8", which can be useful to reduce the amount of - * CORS preflight requests that are sent to the server. - * - * Parameters: - * (String) service - The BOSH or WebSocket service URL. - * (Object) options - A hash of configuration options - * - * Returns: - * A new Strophe.Connection object. - */ - Strophe.Connection = function (service, options) { - // The service URL - this.service = service; - // Configuration options - this.options = options || {}; - var proto = this.options.protocol || ""; - - // Select protocal based on service or options - if (service.indexOf("ws:") === 0 || service.indexOf("wss:") === 0 || - proto.indexOf("ws") === 0) { - this._proto = new Strophe.Websocket(this); - } else { - this._proto = new Strophe.Bosh(this); - } - - /* The connected JID. */ - this.jid = ""; - /* the JIDs domain */ - this.domain = null; - /* stream:features */ - this.features = null; - - // SASL - this._sasl_data = {}; - this.do_session = false; - this.do_bind = false; - - // handler lists - this.timedHandlers = []; - this.handlers = []; - this.removeTimeds = []; - this.removeHandlers = []; - this.addTimeds = []; - this.addHandlers = []; - this.protocolErrorHandlers = { - 'HTTP': {}, - 'websocket': {} - }; - - this._idleTimeout = null; - this._disconnectTimeout = null; - - this.authenticated = false; - this.connected = false; - this.disconnecting = false; - this.do_authentication = true; - this.paused = false; - this.restored = false; - - this._data = []; - this._uniqueId = 0; - - this._sasl_success_handler = null; - this._sasl_failure_handler = null; - this._sasl_challenge_handler = null; - - // Max retries before disconnecting - this.maxRetries = 5; - - // Call onIdle callback every 1/10th of a second - // XXX: setTimeout should be called only with function expressions (23974bc1) - this._idleTimeout = setTimeout(function () { - this._onIdle(); - }.bind(this), 100); - - utils.addCookies(this.options.cookies); - this.registerSASLMechanisms(this.options.mechanisms); - - // initialize plugins - for (var k in Strophe._connectionPlugins) { - if (Strophe._connectionPlugins.hasOwnProperty(k)) { - var ptype = Strophe._connectionPlugins[k]; - // jslint complaints about the below line, but this is fine - var F = function () { - }; // jshint ignore:line - F.prototype = ptype; - this[k] = new F(); - this[k].init(this); - } - } - }; - - Strophe.Connection.prototype = { - /** Function: reset - * Reset the connection. - * - * This function should be called after a connection is disconnected - * before that connection is reused. - */ - reset: function () { - this._proto._reset(); - - // SASL - this.do_session = false; - this.do_bind = false; - - // handler lists - this.timedHandlers = []; - this.handlers = []; - this.removeTimeds = []; - this.removeHandlers = []; - this.addTimeds = []; - this.addHandlers = []; - - this.authenticated = false; - this.connected = false; - this.disconnecting = false; - this.restored = false; - - this._data = []; - this._requests = []; - this._uniqueId = 0; - }, - - /** Function: pause - * Pause the request manager. - * - * This will prevent Strophe from sending any more requests to the - * server. This is very useful for temporarily pausing - * BOSH-Connections while a lot of send() calls are happening quickly. - * This causes Strophe to send the data in a single request, saving - * many request trips. - */ - pause: function () { - this.paused = true; - }, - - /** Function: resume - * Resume the request manager. - * - * This resumes after pause() has been called. - */ - resume: function () { - this.paused = false; - }, - - /** Function: getUniqueId - * Generate a unique ID for use in elements. - * - * All stanzas are required to have unique id attributes. This - * function makes creating these easy. Each connection instance has - * a counter which starts from zero, and the value of this counter - * plus a colon followed by the suffix becomes the unique id. If no - * suffix is supplied, the counter is used as the unique id. - * - * Suffixes are used to make debugging easier when reading the stream - * data, and their use is recommended. The counter resets to 0 for - * every new connection for the same reason. For connections to the - * same server that authenticate the same way, all the ids should be - * the same, which makes it easy to see changes. This is useful for - * automated testing as well. - * - * Parameters: - * (String) suffix - A optional suffix to append to the id. - * - * Returns: - * A unique string to be used for the id attribute. - */ - getUniqueId: function (suffix) { - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0, - v = c == 'x' ? r : r & 0x3 | 0x8; - return v.toString(16); - }); - if (typeof(suffix) == "string" || typeof(suffix) == "number") { - return uuid + ":" + suffix; - } else { - return uuid + ""; - } - }, - - /** Function: addProtocolErrorHandler - * Register a handler function for when a protocol (websocker or HTTP) - * error occurs. - * - * NOTE: Currently only HTTP errors for BOSH requests are handled. - * Patches that handle websocket errors would be very welcome. - * - * Parameters: - * (String) protocol - 'HTTP' or 'websocket' - * (Integer) status_code - Error status code (e.g 500, 400 or 404) - * (Function) callback - Function that will fire on Http error - * - * Example: - * function onError(err_code){ - * //do stuff - * } - * - * var conn = Strophe.connect('http://example.com/http-bind'); - * conn.addProtocolErrorHandler('HTTP', 500, onError); - * // Triggers HTTP 500 error and onError handler will be called - * conn.connect('user_jid@incorrect_jabber_host', 'secret', onConnect); - */ - addProtocolErrorHandler: function (protocol, status_code, callback) { - this.protocolErrorHandlers[protocol][status_code] = callback; - }, - - - /** Function: connect - * Starts the connection process. - * - * As the connection process proceeds, the user supplied callback will - * be triggered multiple times with status updates. The callback - * should take two arguments - the status code and the error condition. - * - * The status code will be one of the values in the Strophe.Status - * constants. The error condition will be one of the conditions - * defined in RFC 3920 or the condition 'strophe-parsererror'. - * - * The Parameters _wait_, _hold_ and _route_ are optional and only relevant - * for BOSH connections. Please see XEP 124 for a more detailed explanation - * of the optional parameters. - * - * Parameters: - * (String) jid - The user's JID. This may be a bare JID, - * or a full JID. If a node is not supplied, SASL ANONYMOUS - * authentication will be attempted. - * (String) pass - The user's password. - * (Function) callback - The connect callback function. - * (Integer) wait - The optional HTTPBIND wait value. This is the - * time the server will wait before returning an empty result for - * a request. The default setting of 60 seconds is recommended. - * (Integer) hold - The optional HTTPBIND hold value. This is the - * number of connections the server will hold at one time. This - * should almost always be set to 1 (the default). - * (String) route - The optional route value. - * (String) authcid - The optional alternative authentication identity - * (username) if intending to impersonate another user. - * When using the SASL-EXTERNAL authentication mechanism, for example - * with client certificates, then the authcid value is used to - * determine whether an authorization JID (authzid) should be sent to - * the server. The authzid should not be sent to the server if the - * authzid and authcid are the same. So to prevent it from being sent - * (for example when the JID is already contained in the client - * certificate), set authcid to that same JID. See XEP-178 for more - * details. - */ - connect: function (jid, pass, callback, wait, hold, route, authcid) { - this.jid = jid; - /** Variable: authzid - * Authorization identity. - */ - this.authzid = Strophe.getBareJidFromJid(this.jid); - - /** Variable: authcid - * Authentication identity (User name). - */ - this.authcid = authcid || Strophe.getNodeFromJid(this.jid); - - /** Variable: pass - * Authentication identity (User password). - */ - this.pass = pass; - - /** Variable: servtype - * Digest MD5 compatibility. - */ - this.servtype = "xmpp"; - - this.connect_callback = callback; - this.disconnecting = false; - this.connected = false; - this.authenticated = false; - this.restored = false; - - // parse jid for domain - this.domain = Strophe.getDomainFromJid(this.jid); - - this._changeConnectStatus(Strophe.Status.CONNECTING, null); - - this._proto._connect(wait, hold, route); - }, - - /** Function: attach - * Attach to an already created and authenticated BOSH session. - * - * This function is provided to allow Strophe to attach to BOSH - * sessions which have been created externally, perhaps by a Web - * application. This is often used to support auto-login type features - * without putting user credentials into the page. - * - * Parameters: - * (String) jid - The full JID that is bound by the session. - * (String) sid - The SID of the BOSH session. - * (String) rid - The current RID of the BOSH session. This RID - * will be used by the next request. - * (Function) callback The connect callback function. - * (Integer) wait - The optional HTTPBIND wait value. This is the - * time the server will wait before returning an empty result for - * a request. The default setting of 60 seconds is recommended. - * Other settings will require tweaks to the Strophe.TIMEOUT value. - * (Integer) hold - The optional HTTPBIND hold value. This is the - * number of connections the server will hold at one time. This - * should almost always be set to 1 (the default). - * (Integer) wind - The optional HTTBIND window value. This is the - * allowed range of request ids that are valid. The default is 5. - */ - attach: function (jid, sid, rid, callback, wait, hold, wind) { - if (this._proto instanceof Strophe.Bosh) { - this._proto._attach(jid, sid, rid, callback, wait, hold, wind); - } else { - throw { - name: 'StropheSessionError', - message: 'The "attach" method can only be used with a BOSH connection.' - }; - } - }, - - /** Function: restore - * Attempt to restore a cached BOSH session. - * - * This function is only useful in conjunction with providing the - * "keepalive":true option when instantiating a new Strophe.Connection. - * - * When "keepalive" is set to true, Strophe will cache the BOSH tokens - * RID (Request ID) and SID (Session ID) and then when this function is - * called, it will attempt to restore the session from those cached - * tokens. - * - * This function must therefore be called instead of connect or attach. - * - * For an example on how to use it, please see examples/restore.js - * - * Parameters: - * (String) jid - The user's JID. This may be a bare JID or a full JID. - * (Function) callback - The connect callback function. - * (Integer) wait - The optional HTTPBIND wait value. This is the - * time the server will wait before returning an empty result for - * a request. The default setting of 60 seconds is recommended. - * (Integer) hold - The optional HTTPBIND hold value. This is the - * number of connections the server will hold at one time. This - * should almost always be set to 1 (the default). - * (Integer) wind - The optional HTTBIND window value. This is the - * allowed range of request ids that are valid. The default is 5. - */ - restore: function (jid, callback, wait, hold, wind) { - if (this._sessionCachingSupported()) { - this._proto._restore(jid, callback, wait, hold, wind); - } else { - throw { - name: 'StropheSessionError', - message: 'The "restore" method can only be used with a BOSH connection.' - }; - } - }, - - /** PrivateFunction: _sessionCachingSupported - * Checks whether sessionStorage and JSON are supported and whether we're - * using BOSH. - */ - _sessionCachingSupported: function () { - if (this._proto instanceof Strophe.Bosh) { - if (!JSON) { - return false; - } - try { - window.sessionStorage.setItem('_strophe_', '_strophe_'); - window.sessionStorage.removeItem('_strophe_'); - } catch (e) { - return false; - } - return true; - } - return false; - }, - - /** Function: xmlInput - * User overrideable function that receives XML data coming into the - * connection. - * - * The default function does nothing. User code can override this with - * > Strophe.Connection.xmlInput = function (elem) { - * > (user code) - * > }; - * - * Due to limitations of current Browsers' XML-Parsers the opening and closing - * tag for WebSocket-Connoctions will be passed as selfclosing here. - * - * BOSH-Connections will have all stanzas wrapped in a tag. See - * if you want to strip this tag. - * - * Parameters: - * (XMLElement) elem - The XML data received by the connection. - */ - /* jshint unused:false */ - xmlInput: function (elem) { - return; - }, - /* jshint unused:true */ - - /** Function: xmlOutput - * User overrideable function that receives XML data sent to the - * connection. - * - * The default function does nothing. User code can override this with - * > Strophe.Connection.xmlOutput = function (elem) { - * > (user code) - * > }; - * - * Due to limitations of current Browsers' XML-Parsers the opening and closing - * tag for WebSocket-Connoctions will be passed as selfclosing here. - * - * BOSH-Connections will have all stanzas wrapped in a tag. See - * if you want to strip this tag. - * - * Parameters: - * (XMLElement) elem - The XMLdata sent by the connection. - */ - /* jshint unused:false */ - xmlOutput: function (elem) { - return; - }, - /* jshint unused:true */ - - /** Function: rawInput - * User overrideable function that receives raw data coming into the - * connection. - * - * The default function does nothing. User code can override this with - * > Strophe.Connection.rawInput = function (data) { - * > (user code) - * > }; - * - * Parameters: - * (String) data - The data received by the connection. - */ - /* jshint unused:false */ - rawInput: function (data) { - return; - }, - /* jshint unused:true */ - - /** Function: rawOutput - * User overrideable function that receives raw data sent to the - * connection. - * - * The default function does nothing. User code can override this with - * > Strophe.Connection.rawOutput = function (data) { - * > (user code) - * > }; - * - * Parameters: - * (String) data - The data sent by the connection. - */ - /* jshint unused:false */ - rawOutput: function (data) { - return; - }, - /* jshint unused:true */ - - /** Function: nextValidRid - * User overrideable function that receives the new valid rid. - * - * The default function does nothing. User code can override this with - * > Strophe.Connection.nextValidRid = function (rid) { - * > (user code) - * > }; - * - * Parameters: - * (Number) rid - The next valid rid - */ - /* jshint unused:false */ - nextValidRid: function (rid) { - return; - }, - /* jshint unused:true */ - - /** Function: send - * Send a stanza. - * - * This function is called to push data onto the send queue to - * go out over the wire. Whenever a request is sent to the BOSH - * server, all pending data is sent and the queue is flushed. - * - * Parameters: - * (XMLElement | - * [XMLElement] | - * Strophe.Builder) elem - The stanza to send. - */ - send: function (elem) { - // console.log(elem) - if (elem === null) { - return; - } - if (typeof(elem.sort) === "function") { - for (var i = 0; i < elem.length; i++) { - this._queueData(elem[i]); - } - } else if (typeof(elem.tree) === "function") { - //console.log("ffffffffffff") - this._queueData(elem.tree()); - } else { - this._queueData(elem); - } - - this._proto._send(); - }, - - /** Function: flush - * Immediately send any pending outgoing data. - * - * Normally send() queues outgoing data until the next idle period - * (100ms), which optimizes network use in the common cases when - * several send()s are called in succession. flush() can be used to - * immediately send all pending data. - */ - flush: function () { - // cancel the pending idle period and run the idle function - // immediately - clearTimeout(this._idleTimeout); - this._onIdle(); - }, - - /** Function: sendIQ - * Helper function to send IQ stanzas. - * - * Parameters: - * (XMLElement) elem - The stanza to send. - * (Function) callback - The callback function for a successful request. - * (Function) errback - The callback function for a failed or timed - * out request. On timeout, the stanza will be null. - * (Integer) timeout - The time specified in milliseconds for a - * timeout to occur. - * - * Returns: - * The id used to send the IQ. - */ - sendIQ: function (elem, callback, errback, timeout) { - var timeoutHandler = null; - var that = this; - - if (typeof(elem.tree) === "function") { - elem = elem.tree(); - } - var id = elem.getAttribute('id'); - - // inject id if not found - if (!id) { - id = this.getUniqueId("sendIQ"); - elem.setAttribute("id", id); - } - - var expectedFrom = elem.getAttribute("to"); - var fulljid = this.jid; - - var handler = this.addHandler(function (stanza) { - // remove timeout handler if there is one - if (timeoutHandler) { - that.deleteTimedHandler(timeoutHandler); - } - - var acceptable = false; - var from = stanza.getAttribute("from"); - if (from === expectedFrom || - (!expectedFrom && - (from === Strophe.getBareJidFromJid(fulljid) || - from === Strophe.getDomainFromJid(fulljid) || - from === fulljid))) { - acceptable = true; - } - - if (!acceptable) { - throw { - name: "StropheError", - message: "Got answer to IQ from wrong jid:" + from + - "\nExpected jid: " + expectedFrom - }; - } - - var iqtype = stanza.getAttribute('type'); - if (iqtype == 'result') { - if (callback) { - callback(stanza); - } - } else if (iqtype == 'error') { - if (errback) { - errback(stanza); - } - } else { - throw { - name: "StropheError", - message: "Got bad IQ type of " + iqtype - }; - } - }, null, 'iq', ['error', 'result'], id); - - // if timeout specified, setup timeout handler. - if (timeout) { - timeoutHandler = this.addTimedHandler(timeout, function () { - // get rid of normal handler - that.deleteHandler(handler); - // call errback on timeout with null stanza - if (errback) { - errback(null); - } - return false; - }); - } - this.send(elem); - return id; - }, - - /** PrivateFunction: _queueData - * Queue outgoing data for later sending. Also ensures that the data - * is a DOMElement. - */ - _queueData: function (element) { - if (element === null || !element.tagName || !element.childNodes) { - throw { - name: "StropheError", - message: "Cannot queue non-DOMElement." - }; - } - this._data.push(element); - }, - - /** PrivateFunction: _sendRestart - * Send an xmpp:restart stanza. - */ - _sendRestart: function () { - this._data.push("restart"); - this._proto._sendRestart(); - // XXX: setTimeout should be called only with function expressions (23974bc1) - this._idleTimeout = setTimeout(function () { - this._onIdle(); - }.bind(this), 100); - }, - - /** Function: addTimedHandler - * Add a timed handler to the connection. - * - * This function adds a timed handler. The provided handler will - * be called every period milliseconds until it returns false, - * the connection is terminated, or the handler is removed. Handlers - * that wish to continue being invoked should return true. - * - * Because of method binding it is necessary to save the result of - * this function if you wish to remove a handler with - * deleteTimedHandler(). - * - * Note that user handlers are not active until authentication is - * successful. - * - * Parameters: - * (Integer) period - The period of the handler. - * (Function) handler - The callback function. - * - * Returns: - * A reference to the handler that can be used to remove it. - */ - addTimedHandler: function (period, handler) { - var thand = new Strophe.TimedHandler(period, handler); - this.addTimeds.push(thand); - return thand; - }, - - /** Function: deleteTimedHandler - * Delete a timed handler for a connection. - * - * This function removes a timed handler from the connection. The - * handRef parameter is *not* the function passed to addTimedHandler(), - * but is the reference returned from addTimedHandler(). - * - * Parameters: - * (Strophe.TimedHandler) handRef - The handler reference. - */ - deleteTimedHandler: function (handRef) { - // this must be done in the Idle loop so that we don't change - // the handlers during iteration - this.removeTimeds.push(handRef); - }, - - /** Function: addHandler - * Add a stanza handler for the connection. - * - * This function adds a stanza handler to the connection. The - * handler callback will be called for any stanza that matches - * the parameters. Note that if multiple parameters are supplied, - * they must all match for the handler to be invoked. - * - * The handler will receive the stanza that triggered it as its argument. - * *The handler should return true if it is to be invoked again; - * returning false will remove the handler after it returns.* - * - * As a convenience, the ns parameters applies to the top level element - * and also any of its immediate children. This is primarily to make - * matching /iq/query elements easy. - * - * Options - * ~~~~~~~ - * With the options argument, you can specify boolean flags that affect how - * matches are being done. - * - * Currently two flags exist: - * - * - matchBareFromJid: - * When set to true, the from parameter and the - * from attribute on the stanza will be matched as bare JIDs instead - * of full JIDs. To use this, pass {matchBareFromJid: true} as the - * value of options. The default value for matchBareFromJid is false. - * - * - ignoreNamespaceFragment: - * When set to true, a fragment specified on the stanza's namespace - * URL will be ignored when it's matched with the one configured for - * the handler. - * - * This means that if you register like this: - * > connection.addHandler( - * > handler, - * > 'http://jabber.org/protocol/muc', - * > null, null, null, null, - * > {'ignoreNamespaceFragment': true} - * > ); - * - * Then a stanza with XML namespace of - * 'http://jabber.org/protocol/muc#user' will also be matched. If - * 'ignoreNamespaceFragment' is false, then only stanzas with - * 'http://jabber.org/protocol/muc' will be matched. - * - * Deleting the handler - * ~~~~~~~~~~~~~~~~~~~~ - * The return value should be saved if you wish to remove the handler - * with deleteHandler(). - * - * Parameters: - * (Function) handler - The user callback. - * (String) ns - The namespace to match. - * (String) name - The stanza name to match. - * (String|Array) type - The stanza type (or types if an array) to match. - * (String) id - The stanza id attribute to match. - * (String) from - The stanza from attribute to match. - * (String) options - The handler options - * - * Returns: - * A reference to the handler that can be used to remove it. - */ - addHandler: function (handler, ns, name, type, id, from, options) { - var hand = new Strophe.Handler(handler, ns, name, type, id, from, options); - this.addHandlers.push(hand); - return hand; - }, - - /** Function: deleteHandler - * Delete a stanza handler for a connection. - * - * This function removes a stanza handler from the connection. The - * handRef parameter is *not* the function passed to addHandler(), - * but is the reference returned from addHandler(). - * - * Parameters: - * (Strophe.Handler) handRef - The handler reference. - */ - deleteHandler: function (handRef) { - // this must be done in the Idle loop so that we don't change - // the handlers during iteration - this.removeHandlers.push(handRef); - // If a handler is being deleted while it is being added, - // prevent it from getting added - var i = this.addHandlers.indexOf(handRef); - if (i >= 0) { - this.addHandlers.splice(i, 1); - } - }, - - /** Function: registerSASLMechanisms - * - * Register the SASL mechanisms which will be supported by this instance of - * Strophe.Connection (i.e. which this XMPP client will support). - * - * Parameters: - * (Array) mechanisms - Array of objects with Strophe.SASLMechanism prototypes - * - */ - registerSASLMechanisms: function (mechanisms) { - this.mechanisms = {}; - mechanisms = mechanisms || [ - Strophe.SASLAnonymous, - Strophe.SASLExternal, - Strophe.SASLMD5, - Strophe.SASLOAuthBearer, - Strophe.SASLPlain, - Strophe.SASLSHA1 - ]; - mechanisms.forEach(this.registerSASLMechanism.bind(this)); - }, - - /** Function: registerSASLMechanism - * - * Register a single SASL mechanism, to be supported by this client. - * - * Parameters: - * (Object) mechanism - Object with a Strophe.SASLMechanism prototype - * - */ - registerSASLMechanism: function (mechanism) { - this.mechanisms[mechanism.prototype.name] = mechanism; - }, - - /** Function: disconnect - * Start the graceful disconnection process. - * - * This function starts the disconnection process. This process starts - * by sending unavailable presence and sending BOSH body of type - * terminate. A timeout handler makes sure that disconnection happens - * even if the BOSH server does not respond. - * If the Connection object isn't connected, at least tries to abort all pending requests - * so the connection object won't generate successful requests (which were already opened). - * - * The user supplied connection callback will be notified of the - * progress as this process happens. - * - * Parameters: - * (String) reason - The reason the disconnect is occuring. - */ - disconnect: function (reason) { - this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason); - - Strophe.info("Disconnect was called because: " + reason); - if (this.connected) { - var pres = false; - this.disconnecting = true; - if (this.authenticated) { - pres = $pres({ - xmlns: Strophe.NS.CLIENT, - type: 'unavailable' - }); - } - // setup timeout handler - this._disconnectTimeout = this._addSysTimedHandler( - 3000, this._onDisconnectTimeout.bind(this)); - this._proto._disconnect(pres); - } else { - Strophe.info("Disconnect was called before Strophe connected to the server"); - this._proto._abortAllRequests(); - } - }, - - /** PrivateFunction: _changeConnectStatus - * _Private_ helper function that makes sure plugins and the user's - * callback are notified of connection status changes. - * - * Parameters: - * (Integer) status - the new connection status, one of the values - * in Strophe.Status - * (String) condition - the error condition or null - */ - _changeConnectStatus: function (status, condition) { - // notify all plugins listening for status changes - for (var k in Strophe._connectionPlugins) { - if (Strophe._connectionPlugins.hasOwnProperty(k)) { - var plugin = this[k]; - if (plugin.statusChanged) { - try { - plugin.statusChanged(status, condition); - } catch (err) { - Strophe.error("" + k + " plugin caused an exception " + - "changing status: " + err); - } - } - } - } - - // notify the user's callback - if (this.connect_callback) { - try { - this.connect_callback(status, condition); - } catch (e) { - Strophe._handleError(e); - Strophe.error( - "User connection callback caused an " + "exception: " + e); - } - } - }, - - /** PrivateFunction: _doDisconnect - * _Private_ function to disconnect. - * - * This is the last piece of the disconnection logic. This resets the - * connection and alerts the user's connection callback. - */ - _doDisconnect: function (condition) { - if (typeof this._idleTimeout == "number") { - clearTimeout(this._idleTimeout); - } - - // Cancel Disconnect Timeout - if (this._disconnectTimeout !== null) { - this.deleteTimedHandler(this._disconnectTimeout); - this._disconnectTimeout = null; - } - - Strophe.info("_doDisconnect was called"); - this._proto._doDisconnect(); - - this.authenticated = false; - this.disconnecting = false; - this.restored = false; - - // delete handlers - this.handlers = []; - this.timedHandlers = []; - this.removeTimeds = []; - this.removeHandlers = []; - this.addTimeds = []; - this.addHandlers = []; - - // tell the parent we disconnected - this._changeConnectStatus(Strophe.Status.DISCONNECTED, condition); - this.connected = false; - }, - - /** PrivateFunction: _dataRecv - * _Private_ handler to processes incoming data from the the connection. - * - * Except for _connect_cb handling the initial connection request, - * this function handles the incoming data for all requests. This - * function also fires stanza handlers that match each incoming - * stanza. - * - * Parameters: - * (Strophe.Request) req - The request that has data ready. - * (string) req - The stanza a raw string (optiona). - */ - _dataRecv: function (req, raw) { - Strophe.info("_dataRecv called"); - var elem = this._proto._reqToData(req); - if (elem === null) { - return; - } - - if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { - if (elem.nodeName === this._proto.strip && elem.childNodes.length) { - this.xmlInput(elem.childNodes[0]); - } else { - this.xmlInput(elem); - } - } - if (this.rawInput !== Strophe.Connection.prototype.rawInput) { - if (raw) { - this.rawInput(raw); - } else { - this.rawInput(Strophe.serialize(elem)); - } - } - - // remove handlers scheduled for deletion - var i, hand; - while (this.removeHandlers.length > 0) { - hand = this.removeHandlers.pop(); - i = this.handlers.indexOf(hand); - if (i >= 0) { - this.handlers.splice(i, 1); - } - } - - // add handlers scheduled for addition - while (this.addHandlers.length > 0) { - this.handlers.push(this.addHandlers.pop()); - } - - // handle graceful disconnect - if (this.disconnecting && this._proto._emptyQueue()) { - this._doDisconnect(); - return; - } - - var type = elem.getAttribute("type"); - var cond, conflict; - if (type !== null && type == "terminate") { - // Don't process stanzas that come in after disconnect - if (this.disconnecting) { - return; - } - - // an error occurred - cond = elem.getAttribute("condition"); - conflict = elem.getElementsByTagName("conflict"); - if (cond !== null) { - if (cond == "remote-stream-error" && conflict.length > 0) { - cond = "conflict"; - } - this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); - } else { - this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); - } - this._doDisconnect(cond); - return; - } - - // send each incoming stanza through the handler chain - var that = this; - Strophe.forEachChild(elem, null, function (child) { - var i, newList; - // process handlers - newList = that.handlers; - that.handlers = []; - for (i = 0; i < newList.length; i++) { - var hand = newList[i]; - // encapsulate 'handler.run' not to lose the whole handler list if - // one of the handlers throws an exception - try { - if (hand.isMatch(child) && - (that.authenticated || !hand.user)) { - if (hand.run(child)) { - that.handlers.push(hand); - } - } else { - that.handlers.push(hand); - } - } catch (e) { - // if the handler throws an exception, we consider it as false - Strophe.warn('Removing Strophe handlers due to uncaught exception: ' + e.message); - } - } - }); - }, - - - /** Attribute: mechanisms - * SASL Mechanisms available for Connection. - */ - mechanisms: {}, - - /** PrivateFunction: _connect_cb - * _Private_ handler for initial connection request. - * - * This handler is used to process the initial connection request - * response from the BOSH server. It is used to set up authentication - * handlers and start the authentication process. - * - * SASL authentication will be attempted if available, otherwise - * the code will fall back to legacy authentication. - * - * Parameters: - * (Strophe.Request) req - The current request. - * (Function) _callback - low level (xmpp) connect callback function. - * Useful for plugins with their own xmpp connect callback (when their) - * want to do something special). - */ - _connect_cb: function (req, _callback, raw) { - Strophe.info("_connect_cb was called"); - this.connected = true; - - var bodyWrap; - try { - bodyWrap = this._proto._reqToData(req); - } catch (e) { - if (e != "badformat") { - throw e; - } - this._changeConnectStatus(Strophe.Status.CONNFAIL, 'bad-format'); - this._doDisconnect('bad-format'); - } - if (!bodyWrap) { - return; - } - - if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { - if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) { - this.xmlInput(bodyWrap.childNodes[0]); - } else { - this.xmlInput(bodyWrap); - } - } - if (this.rawInput !== Strophe.Connection.prototype.rawInput) { - if (raw) { - this.rawInput(raw); - } else { - this.rawInput(Strophe.serialize(bodyWrap)); - } - } - - var conncheck = this._proto._connect_cb(bodyWrap); - if (conncheck === Strophe.Status.CONNFAIL) { - return; - } - - // Check for the stream:features tag - var hasFeatures; - if (bodyWrap.getElementsByTagNameNS) { - hasFeatures = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, "features").length > 0; - } else { - hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0 || - bodyWrap.getElementsByTagName("features").length > 0; - } - - //console.log('hasFeatures', hasFeatures, bodyWrap, _callback) - if (!hasFeatures) { - //console.log('hasFeatures2') - try { - this._proto._no_auth_received(_callback); - } catch (e) { - //console.log('_no_auth_received') - } - - return; - } - - var matched = [], i, mech; - var mechanisms = bodyWrap.getElementsByTagName("mechanism"); - if (mechanisms.length > 0) { - for (i = 0; i < mechanisms.length; i++) { - mech = Strophe.getText(mechanisms[i]); - if (this.mechanisms[mech]) matched.push(this.mechanisms[mech]); - } - } - - //console.log('matched', matched, bodyWrap) - if (matched.length === 0) { - if (bodyWrap.getElementsByTagName("auth").length === 0) { - // There are no matching SASL mechanisms and also no legacy - // auth available. - this._proto._no_auth_received(_callback); - return; - } - } - if (this.do_authentication !== false) { - this.authenticate(matched); - } - }, - - /** Function: sortMechanismsByPriority - * - * Sorts an array of objects with prototype SASLMechanism according to - * their priorities. - * - * Parameters: - * (Array) mechanisms - Array of SASL mechanisms. - * - */ - sortMechanismsByPriority: function (mechanisms) { - // Sorting mechanisms according to priority. - var i, j, higher, swap; - for (i = 0; i < mechanisms.length - 1; ++i) { - higher = i; - for (j = i + 1; j < mechanisms.length; ++j) { - if (mechanisms[j].prototype.priority > mechanisms[higher].prototype.priority) { - higher = j; - } - } - if (higher != i) { - swap = mechanisms[i]; - mechanisms[i] = mechanisms[higher]; - mechanisms[higher] = swap; - } - } - return mechanisms; - }, - - /** PrivateFunction: _attemptSASLAuth - * - * Iterate through an array of SASL mechanisms and attempt authentication - * with the highest priority (enabled) mechanism. - * - * Parameters: - * (Array) mechanisms - Array of SASL mechanisms. - * - * Returns: - * (Boolean) mechanism_found - true or false, depending on whether a - * valid SASL mechanism was found with which authentication could be - * started. - */ - _attemptSASLAuth: function (mechanisms) { - mechanisms = this.sortMechanismsByPriority(mechanisms || []); - var i = 0, mechanism_found = false; - for (i = 0; i < mechanisms.length; ++i) { - if (!mechanisms[i].prototype.test(this)) { - continue; - } - this._sasl_success_handler = this._addSysHandler( - this._sasl_success_cb.bind(this), null, - "success", null, null); - this._sasl_failure_handler = this._addSysHandler( - this._sasl_failure_cb.bind(this), null, - "failure", null, null); - this._sasl_challenge_handler = this._addSysHandler( - this._sasl_challenge_cb.bind(this), null, - "challenge", null, null); - - this._sasl_mechanism = new mechanisms[i](); - this._sasl_mechanism.onStart(this); - - var request_auth_exchange = $build("auth", { - xmlns: Strophe.NS.SASL, - mechanism: this._sasl_mechanism.name - }); - if (this._sasl_mechanism.isClientFirst) { - var response = this._sasl_mechanism.onChallenge(this, null); - request_auth_exchange.t(Base64.encode(response)); - } - this.send(request_auth_exchange.tree()); - mechanism_found = true; - break; - } - return mechanism_found; - }, - - /** PrivateFunction: _attemptLegacyAuth - * - * Attempt legacy (i.e. non-SASL) authentication. - * - */ - _attemptLegacyAuth: function () { - if (Strophe.getNodeFromJid(this.jid) === null) { - // we don't have a node, which is required for non-anonymous - // client connections - this._changeConnectStatus( - Strophe.Status.CONNFAIL, - 'x-strophe-bad-non-anon-jid' - ); - this.disconnect('x-strophe-bad-non-anon-jid'); - } else { - // Fall back to legacy authentication - this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); - this._addSysHandler( - this._auth1_cb.bind(this), - null, null, null, "_auth_1" - ); - this.send($iq({ - 'type': "get", - 'to': this.domain, - 'id': "_auth_1" - }).c("query", {xmlns: Strophe.NS.AUTH}) - .c("username", {}).t(Strophe.getNodeFromJid(this.jid)) - .tree()); - } - }, - - /** Function: authenticate - * Set up authentication - * - * Continues the initial connection request by setting up authentication - * handlers and starting the authentication process. - * - * SASL authentication will be attempted if available, otherwise - * the code will fall back to legacy authentication. - * - * Parameters: - * (Array) matched - Array of SASL mechanisms supported. - * - */ - authenticate: function (matched) { - //console.log('authenticate'); - if (!this._attemptSASLAuth(matched)) { - this._attemptLegacyAuth(); - } - }, - - /** PrivateFunction: _sasl_challenge_cb - * _Private_ handler for the SASL challenge - * - */ - _sasl_challenge_cb: function (elem) { - var challenge = Base64.decode(Strophe.getText(elem)); - var response = this._sasl_mechanism.onChallenge(this, challenge); - var stanza = $build('response', { - 'xmlns': Strophe.NS.SASL - }); - if (response !== "") { - stanza.t(Base64.encode(response)); - } - this.send(stanza.tree()); - return true; - }, - - /** PrivateFunction: _auth1_cb - * _Private_ handler for legacy authentication. - * - * This handler is called in response to the initial - * for legacy authentication. It builds an authentication and - * sends it, creating a handler (calling back to _auth2_cb()) to - * handle the result - * - * Parameters: - * (XMLElement) elem - The stanza that triggered the callback. - * - * Returns: - * false to remove the handler. - */ - /* jshint unused:false */ - _auth1_cb: function (elem) { - // build plaintext auth iq - var iq = $iq({type: "set", id: "_auth_2"}) - .c('query', {xmlns: Strophe.NS.AUTH}) - .c('username', {}).t(Strophe.getNodeFromJid(this.jid)) - .up() - .c('password').t(this.pass); - - if (!Strophe.getResourceFromJid(this.jid)) { - // since the user has not supplied a resource, we pick - // a default one here. unlike other auth methods, the server - // cannot do this for us. - this.jid = Strophe.getBareJidFromJid(this.jid) + '/strophe'; - } - iq.up().c('resource', {}).t(Strophe.getResourceFromJid(this.jid)); - - this._addSysHandler(this._auth2_cb.bind(this), null, - null, null, "_auth_2"); - this.send(iq.tree()); - return false; - }, - /* jshint unused:true */ - - /** PrivateFunction: _sasl_success_cb - * _Private_ handler for succesful SASL authentication. - * - * Parameters: - * (XMLElement) elem - The matching stanza. - * - * Returns: - * false to remove the handler. - */ - _sasl_success_cb: function (elem) { - //console.log('_sasl_success_cb', elem) - if (this._sasl_data["server-signature"]) { - var serverSignature; - var success = Base64.decode(Strophe.getText(elem)); - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - var matches = success.match(attribMatch); - if (matches[1] == "v") { - serverSignature = matches[2]; - } - - if (serverSignature != this._sasl_data["server-signature"]) { - // remove old handlers - this.deleteHandler(this._sasl_failure_handler); - this._sasl_failure_handler = null; - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - this._sasl_data = {}; - return this._sasl_failure_cb(null); - } - } - Strophe.info("SASL authentication succeeded."); - - if (this._sasl_mechanism) { - this._sasl_mechanism.onSuccess(); - } - - // remove old handlers - this.deleteHandler(this._sasl_failure_handler); - this._sasl_failure_handler = null; - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - var streamfeature_handlers = []; - var wrapper = function (handlers, elem) { - while (handlers.length) { - this.deleteHandler(handlers.pop()); - } - this._sasl_auth1_cb.bind(this)(elem); - return false; - }; - streamfeature_handlers.push(this._addSysHandler(function (elem) { - wrapper.bind(this)(streamfeature_handlers, elem); - }.bind(this), null, "stream:features", null, null)); - streamfeature_handlers.push(this._addSysHandler(function (elem) { - wrapper.bind(this)(streamfeature_handlers, elem); - }.bind(this), Strophe.NS.STREAM, "features", null, null)); - - // we must send an xmpp:restart now - this._sendRestart(); - - return false; - }, - - /** PrivateFunction: _sasl_auth1_cb - * _Private_ handler to start stream binding. - * - * Parameters: - * (XMLElement) elem - The matching stanza. - * - * Returns: - * false to remove the handler. - */ - _sasl_auth1_cb: function (elem) { - //console.log('_sasl_auth1_cb', elem) - - // save stream:features for future usage - this.features = elem; - var i, child; - for (i = 0; i < elem.childNodes.length; i++) { - child = elem.childNodes[i]; - if (child.nodeName == 'bind') { - this.do_bind = true; - } - - if (child.nodeName == 'session') { - this.do_session = true; - } - } - - if (!this.do_bind) { - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - } else { - this._addSysHandler(this._sasl_bind_cb.bind(this), null, null, - null, "_bind_auth_2"); - - var resource = Strophe.getResourceFromJid(this.jid); - if (resource) { - this.send($iq({type: "set", id: "_bind_auth_2"}) - .c('bind', {xmlns: Strophe.NS.BIND}) - .c('resource', {}).t(resource).tree()); - } else { - this.send($iq({type: "set", id: "_bind_auth_2"}) - .c('bind', {xmlns: Strophe.NS.BIND}) - .tree()); - } - } - return false; - }, - - /** PrivateFunction: _sasl_bind_cb - * _Private_ handler for binding result and session start. - * - * Parameters: - * (XMLElement) elem - The matching stanza. - * - * Returns: - * false to remove the handler. - */ - _sasl_bind_cb: function (elem) { - //console.log('_sasl_bind_cb', elem) - - if (elem.getAttribute("type") == "error") { - Strophe.info("SASL binding failed."); - var conflict = elem.getElementsByTagName("conflict"), condition; - if (conflict.length > 0) { - condition = 'conflict'; - } - this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition); - return false; - } - - // TODO - need to grab errors - var bind = elem.getElementsByTagName("bind"); - var jidNode; - if (bind.length > 0) { - // Grab jid - jidNode = bind[0].getElementsByTagName("jid"); - if (jidNode.length > 0) { - this.jid = Strophe.getText(jidNode[0]); - - if (this.do_session) { - this._addSysHandler(this._sasl_session_cb.bind(this), - null, null, null, "_session_auth_2"); - - this.send($iq({type: "set", id: "_session_auth_2"}) - .c('session', {xmlns: Strophe.NS.SESSION}) - .tree()); - } else { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); - } - } - } else { - Strophe.info("SASL binding failed."); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - } - }, - - /** PrivateFunction: _sasl_session_cb - * _Private_ handler to finish successful SASL connection. - * - * This sets Connection.authenticated to true on success, which - * starts the processing of user handlers. - * - * Parameters: - * (XMLElement) elem - The matching stanza. - * - * Returns: - * false to remove the handler. - */ - _sasl_session_cb: function (elem) { - if (elem.getAttribute("type") == "result") { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); - } else if (elem.getAttribute("type") == "error") { - Strophe.info("Session creation failed."); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - } - return false; - }, - - /** PrivateFunction: _sasl_failure_cb - * _Private_ handler for SASL authentication failure. - * - * Parameters: - * (XMLElement) elem - The matching stanza. - * - * Returns: - * false to remove the handler. - */ - /* jshint unused:false */ - _sasl_failure_cb: function (elem) { - // delete unneeded handlers - if (this._sasl_success_handler) { - this.deleteHandler(this._sasl_success_handler); - this._sasl_success_handler = null; - } - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - if (this._sasl_mechanism) - this._sasl_mechanism.onFailure(); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - }, - /* jshint unused:true */ - - /** PrivateFunction: _auth2_cb - * _Private_ handler to finish legacy authentication. - * - * This handler is called when the result from the jabber:iq:auth - * stanza is returned. - * - * Parameters: - * (XMLElement) elem - The stanza that triggered the callback. - * - * Returns: - * false to remove the handler. - */ - _auth2_cb: function (elem) { - if (elem.getAttribute("type") == "result") { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); - } else if (elem.getAttribute("type") == "error") { - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - this.disconnect('authentication failed'); - } - return false; - }, - - /** PrivateFunction: _addSysTimedHandler - * _Private_ function to add a system level timed handler. - * - * This function is used to add a Strophe.TimedHandler for the - * library code. System timed handlers are allowed to run before - * authentication is complete. - * - * Parameters: - * (Integer) period - The period of the handler. - * (Function) handler - The callback function. - */ - _addSysTimedHandler: function (period, handler) { - var thand = new Strophe.TimedHandler(period, handler); - thand.user = false; - this.addTimeds.push(thand); - return thand; - }, - - /** PrivateFunction: _addSysHandler - * _Private_ function to add a system level stanza handler. - * - * This function is used to add a Strophe.Handler for the - * library code. System stanza handlers are allowed to run before - * authentication is complete. - * - * Parameters: - * (Function) handler - The callback function. - * (String) ns - The namespace to match. - * (String) name - The stanza name to match. - * (String) type - The stanza type attribute to match. - * (String) id - The stanza id attribute to match. - */ - _addSysHandler: function (handler, ns, name, type, id) { - var hand = new Strophe.Handler(handler, ns, name, type, id); - hand.user = false; - this.addHandlers.push(hand); - return hand; - }, - - /** PrivateFunction: _onDisconnectTimeout - * _Private_ timeout handler for handling non-graceful disconnection. - * - * If the graceful disconnect process does not complete within the - * time allotted, this handler finishes the disconnect anyway. - * - * Returns: - * false to remove the handler. - */ - _onDisconnectTimeout: function () { - Strophe.info("_onDisconnectTimeout was called"); - this._changeConnectStatus(Strophe.Status.CONNTIMEOUT, null); - this._proto._onDisconnectTimeout(); - // actually disconnect - this._doDisconnect(); - return false; - }, - - /** PrivateFunction: _onIdle - * _Private_ handler to process events during idle cycle. - * - * This handler is called every 100ms to fire timed handlers that - * are ready and keep poll requests going. - */ - _onIdle: function () { - var i, thand, since, newList; - - // add timed handlers scheduled for addition - // NOTE: we add before remove in the case a timed handler is - // added and then deleted before the next _onIdle() call. - while (this.addTimeds.length > 0) { - this.timedHandlers.push(this.addTimeds.pop()); - } - - // remove timed handlers that have been scheduled for deletion - while (this.removeTimeds.length > 0) { - thand = this.removeTimeds.pop(); - i = this.timedHandlers.indexOf(thand); - if (i >= 0) { - this.timedHandlers.splice(i, 1); - } - } - - // call ready timed handlers - var now = new Date().getTime(); - newList = []; - for (i = 0; i < this.timedHandlers.length; i++) { - thand = this.timedHandlers[i]; - if (this.authenticated || !thand.user) { - since = thand.lastCalled + thand.period; - if (since - now <= 0) { - if (thand.run()) { - newList.push(thand); - } - } else { - newList.push(thand); - } - } - } - this.timedHandlers = newList; - - clearTimeout(this._idleTimeout); - - this._proto._onIdle(); - - // reactivate the timer only if connected - if (this.connected) { - // XXX: setTimeout should be called only with function expressions (23974bc1) - this._idleTimeout = setTimeout(function () { - this._onIdle(); - }.bind(this), 100); - } - } - }; - - /** Class: Strophe.SASLMechanism - * - * encapsulates SASL authentication mechanisms. - * - * User code may override the priority for each mechanism or disable it completely. - * See for information about changing priority and for informatian on - * how to disable a mechanism. - * - * By default, all mechanisms are enabled and the priorities are - * - * EXTERNAL - 60 - * OAUTHBEARER - 50 - * SCRAM-SHA1 - 40 - * DIGEST-MD5 - 30 - * PLAIN - 20 - * ANONYMOUS - 10 - * - * See: Strophe.Connection.addSupportedSASLMechanisms - */ - - /** - * PrivateConstructor: Strophe.SASLMechanism - * SASL auth mechanism abstraction. - * - * Parameters: - * (String) name - SASL Mechanism name. - * (Boolean) isClientFirst - If client should send response first without challenge. - * (Number) priority - Priority. - * - * Returns: - * A new Strophe.SASLMechanism object. - */ - Strophe.SASLMechanism = function (name, isClientFirst, priority) { - /** PrivateVariable: name - * Mechanism name. - */ - this.name = name; - /** PrivateVariable: isClientFirst - * If client sends response without initial server challenge. - */ - this.isClientFirst = isClientFirst; - /** Variable: priority - * Determines which is chosen for authentication (Higher is better). - * Users may override this to prioritize mechanisms differently. - * - * In the default configuration the priorities are - * - * SCRAM-SHA1 - 40 - * DIGEST-MD5 - 30 - * Plain - 20 - * - * Example: (This will cause Strophe to choose the mechanism that the server sent first) - * - * > Strophe.SASLMD5.priority = Strophe.SASLSHA1.priority; - * - * See for a list of available mechanisms. - * - */ - this.priority = priority; - }; - - Strophe.SASLMechanism.prototype = { - /** - * Function: test - * Checks if mechanism able to run. - * To disable a mechanism, make this return false; - * - * To disable plain authentication run - * > Strophe.SASLPlain.test = function() { - * > return false; - * > } - * - * See for a list of available mechanisms. - * - * Parameters: - * (Strophe.Connection) connection - Target Connection. - * - * Returns: - * (Boolean) If mechanism was able to run. - */ - /* jshint unused:false */ - test: function (connection) { - return true; - }, - /* jshint unused:true */ - - /** PrivateFunction: onStart - * Called before starting mechanism on some connection. - * - * Parameters: - * (Strophe.Connection) connection - Target Connection. - */ - onStart: function (connection) { - this._connection = connection; - }, - - /** PrivateFunction: onChallenge - * Called by protocol implementation on incoming challenge. If client is - * first (isClientFirst == true) challenge will be null on the first call. - * - * Parameters: - * (Strophe.Connection) connection - Target Connection. - * (String) challenge - current challenge to handle. - * - * Returns: - * (String) Mechanism response. - */ - /* jshint unused:false */ - onChallenge: function (connection, challenge) { - throw new Error("You should implement challenge handling!"); - }, - /* jshint unused:true */ - - /** PrivateFunction: onFailure - * Protocol informs mechanism implementation about SASL failure. - */ - onFailure: function () { - this._connection = null; - }, - - /** PrivateFunction: onSuccess - * Protocol informs mechanism implementation about SASL success. - */ - onSuccess: function () { - this._connection = null; - } - }; - - /** Constants: SASL mechanisms - * Available authentication mechanisms - * - * Strophe.SASLAnonymous - SASL ANONYMOUS authentication. - * Strophe.SASLPlain - SASL PLAIN authentication. - * Strophe.SASLMD5 - SASL DIGEST-MD5 authentication - * Strophe.SASLSHA1 - SASL SCRAM-SHA1 authentication - * Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication - * Strophe.SASLExternal - SASL EXTERNAL authentication - */ - -// Building SASL callbacks - - /** PrivateConstructor: SASLAnonymous - * SASL ANONYMOUS authentication. - */ - Strophe.SASLAnonymous = function () { - }; - Strophe.SASLAnonymous.prototype = new Strophe.SASLMechanism("ANONYMOUS", false, 10); - - Strophe.SASLAnonymous.prototype.test = function (connection) { - return connection.authcid === null; - }; - - - /** PrivateConstructor: SASLPlain - * SASL PLAIN authentication. - */ - Strophe.SASLPlain = function () { - }; - Strophe.SASLPlain.prototype = new Strophe.SASLMechanism("PLAIN", true, 20); - - Strophe.SASLPlain.prototype.test = function (connection) { - return connection.authcid !== null; - }; - - Strophe.SASLPlain.prototype.onChallenge = function (connection) { - var auth_str = connection.authzid; - auth_str = auth_str + "\u0000"; - auth_str = auth_str + connection.authcid; - auth_str = auth_str + "\u0000"; - auth_str = auth_str + connection.pass; - return utils.utf16to8(auth_str); - }; - - - /** PrivateConstructor: SASLSHA1 - * SASL SCRAM SHA 1 authentication. - */ - Strophe.SASLSHA1 = function () { - }; - Strophe.SASLSHA1.prototype = new Strophe.SASLMechanism("SCRAM-SHA-1", true, 40); - - Strophe.SASLSHA1.prototype.test = function (connection) { - return connection.authcid !== null; - }; - - Strophe.SASLSHA1.prototype.onChallenge = function (connection, challenge, test_cnonce) { - var cnonce = test_cnonce || MD5.hexdigest(Math.random() * 1234567890); - var auth_str = "n=" + utils.utf16to8(connection.authcid); - auth_str += ",r="; - auth_str += cnonce; - connection._sasl_data.cnonce = cnonce; - connection._sasl_data["client-first-message-bare"] = auth_str; - - auth_str = "n,," + auth_str; - - this.onChallenge = function (connection, challenge) { - var nonce, salt, iter, Hi, U, U_old, i, k, pass; - var clientKey, serverKey, clientSignature; - var responseText = "c=biws,"; - var authMessage = connection._sasl_data["client-first-message-bare"] + "," + - challenge + ","; - var cnonce = connection._sasl_data.cnonce; - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - - while (challenge.match(attribMatch)) { - var matches = challenge.match(attribMatch); - challenge = challenge.replace(matches[0], ""); - switch (matches[1]) { - case "r": - nonce = matches[2]; - break; - case "s": - salt = matches[2]; - break; - case "i": - iter = matches[2]; - break; - } - } - - if (nonce.substr(0, cnonce.length) !== cnonce) { - connection._sasl_data = {}; - return connection._sasl_failure_cb(); - } - - responseText += "r=" + nonce; - authMessage += responseText; - - salt = Base64.decode(salt); - salt += "\x00\x00\x00\x01"; - - pass = utils.utf16to8(connection.pass); - Hi = U_old = SHA1.core_hmac_sha1(pass, salt); - for (i = 1; i < iter; i++) { - U = SHA1.core_hmac_sha1(pass, SHA1.binb2str(U_old)); - for (k = 0; k < 5; k++) { - Hi[k] ^= U[k]; - } - U_old = U; - } - Hi = SHA1.binb2str(Hi); - - clientKey = SHA1.core_hmac_sha1(Hi, "Client Key"); - serverKey = SHA1.str_hmac_sha1(Hi, "Server Key"); - clientSignature = SHA1.core_hmac_sha1(SHA1.str_sha1(SHA1.binb2str(clientKey)), authMessage); - connection._sasl_data["server-signature"] = SHA1.b64_hmac_sha1(serverKey, authMessage); - - for (k = 0; k < 5; k++) { - clientKey[k] ^= clientSignature[k]; - } - - responseText += ",p=" + Base64.encode(SHA1.binb2str(clientKey)); - return responseText; - }.bind(this); - - return auth_str; - }; - - - /** PrivateConstructor: SASLMD5 - * SASL DIGEST MD5 authentication. - */ - Strophe.SASLMD5 = function () { - }; - Strophe.SASLMD5.prototype = new Strophe.SASLMechanism("DIGEST-MD5", false, 30); - - Strophe.SASLMD5.prototype.test = function (connection) { - return connection.authcid !== null; - }; - - /** PrivateFunction: _quote - * _Private_ utility function to backslash escape and quote strings. - * - * Parameters: - * (String) str - The string to be quoted. - * - * Returns: - * quoted string - */ - Strophe.SASLMD5.prototype._quote = function (str) { - return '"' + str.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'; - //" end string workaround for emacs - }; - - Strophe.SASLMD5.prototype.onChallenge = function (connection, challenge, test_cnonce) { - var attribMatch = /([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/; - var cnonce = test_cnonce || MD5.hexdigest("" + (Math.random() * 1234567890)); - var realm = ""; - var host = null; - var nonce = ""; - var qop = ""; - var matches; - - while (challenge.match(attribMatch)) { - matches = challenge.match(attribMatch); - challenge = challenge.replace(matches[0], ""); - matches[2] = matches[2].replace(/^"(.+)"$/, "$1"); - switch (matches[1]) { - case "realm": - realm = matches[2]; - break; - case "nonce": - nonce = matches[2]; - break; - case "qop": - qop = matches[2]; - break; - case "host": - host = matches[2]; - break; - } - } - - var digest_uri = connection.servtype + "/" + connection.domain; - if (host !== null) { - digest_uri = digest_uri + "/" + host; - } - - var cred = utils.utf16to8(connection.authcid + ":" + realm + ":" + this._connection.pass); - var A1 = MD5.hash(cred) + ":" + nonce + ":" + cnonce; - var A2 = 'AUTHENTICATE:' + digest_uri; - - var responseText = ""; - responseText += 'charset=utf-8,'; - responseText += 'username=' + this._quote(utils.utf16to8(connection.authcid)) + ','; - responseText += 'realm=' + this._quote(realm) + ','; - responseText += 'nonce=' + this._quote(nonce) + ','; - responseText += 'nc=00000001,'; - responseText += 'cnonce=' + this._quote(cnonce) + ','; - responseText += 'digest-uri=' + this._quote(digest_uri) + ','; - responseText += 'response=' + MD5.hexdigest(MD5.hexdigest(A1) + ":" + - nonce + ":00000001:" + - cnonce + ":auth:" + - MD5.hexdigest(A2)) + ","; - responseText += 'qop=auth'; - - this.onChallenge = function () { - return ""; - }; - return responseText; - }; - - - /** PrivateConstructor: SASLOAuthBearer - * SASL OAuth Bearer authentication. - */ - Strophe.SASLOAuthBearer = function () { - }; - Strophe.SASLOAuthBearer.prototype = new Strophe.SASLMechanism("OAUTHBEARER", true, 50); - - Strophe.SASLOAuthBearer.prototype.test = function (connection) { - return connection.authcid !== null; - }; - - Strophe.SASLOAuthBearer.prototype.onChallenge = function (connection) { - var auth_str = 'n,a='; - auth_str = auth_str + connection.authzid; - auth_str = auth_str + ','; - auth_str = auth_str + "\u0001"; - auth_str = auth_str + 'auth=Bearer '; - auth_str = auth_str + connection.pass; - auth_str = auth_str + "\u0001"; - auth_str = auth_str + "\u0001"; - return utils.utf16to8(auth_str); - }; - - - /** PrivateConstructor: SASLExternal - * SASL EXTERNAL authentication. - * - * The EXTERNAL mechanism allows a client to request the server to use - * credentials established by means external to the mechanism to - * authenticate the client. The external means may be, for instance, - * TLS services. - */ - Strophe.SASLExternal = function () { - }; - Strophe.SASLExternal.prototype = new Strophe.SASLMechanism("EXTERNAL", true, 60); - - Strophe.SASLExternal.prototype.onChallenge = function (connection) { - /** According to XEP-178, an authzid SHOULD NOT be presented when the - * authcid contained or implied in the client certificate is the JID (i.e. - * authzid) with which the user wants to log in as. - * - * To NOT send the authzid, the user should therefore set the authcid equal - * to the JID when instantiating a new Strophe.Connection object. - */ - return connection.authcid === connection.authzid ? '' : connection.authzid; - }; - - return { - Strophe: Strophe, - $build: $build, - $msg: $msg, - $iq: $iq, - $pres: $pres, - SHA1: SHA1, - Base64: Base64, - MD5: MD5, - }; - })); - - - /* - This program is distributed under the terms of the MIT license. - Please see the LICENSE file for details. - - Copyright 2006-2008, OGG, LLC - */ - - /* jshint undef: true, unused: true:, noarg: true, latedef: true */ - /* global define, window, setTimeout, clearTimeout, XMLHttpRequest, ActiveXObject, Strophe, $build */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-bosh', ['strophe-core'], function (core) { - return factory( - core.Strophe, - core.$build - ); - }); - } else { - // Browser globals - return factory(root.Strophe, root.$build); - } - }(this, function (Strophe, $build) { - - /** PrivateClass: Strophe.Request - * _Private_ helper class that provides a cross implementation abstraction - * for a BOSH related XMLHttpRequest. - * - * The Strophe.Request class is used internally to encapsulate BOSH request - * information. It is not meant to be used from user's code. - */ - - /** PrivateConstructor: Strophe.Request - * Create and initialize a new Strophe.Request object. - * - * Parameters: - * (XMLElement) elem - The XML data to be sent in the request. - * (Function) func - The function that will be called when the - * XMLHttpRequest readyState changes. - * (Integer) rid - The BOSH rid attribute associated with this request. - * (Integer) sends - The number of times this same request has been sent. - */ - Strophe.Request = function (elem, func, rid, sends) { - this.id = ++Strophe._requestId; - this.xmlData = elem; - this.data = Strophe.serialize(elem); - // save original function in case we need to make a new request - // from this one. - this.origFunc = func; - this.func = func; - this.rid = rid; - this.date = NaN; - this.sends = sends || 0; - this.abort = false; - this.dead = null; - - this.age = function () { - if (!this.date) { - return 0; - } - var now = new Date(); - return (now - this.date) / 1000; - }; - this.timeDead = function () { - if (!this.dead) { - return 0; - } - var now = new Date(); - return (now - this.dead) / 1000; - }; - this.xhr = this._newXHR(); - }; - - Strophe.Request.prototype = { - /** PrivateFunction: getResponse - * Get a response from the underlying XMLHttpRequest. - * - * This function attempts to get a response from the request and checks - * for errors. - * - * Throws: - * "parsererror" - A parser error occured. - * "badformat" - The entity has sent XML that cannot be processed. - * - * Returns: - * The DOM element tree of the response. - */ - getResponse: function () { - var node = null; - if (this.xhr.responseXML && this.xhr.responseXML.documentElement) { - node = this.xhr.responseXML.documentElement; - if (node.tagName == "parsererror") { - Strophe.error("invalid response received"); - Strophe.error("responseText: " + this.xhr.responseText); - Strophe.error("responseXML: " + - Strophe.serialize(this.xhr.responseXML)); - throw "parsererror"; - } - } else if (this.xhr.responseText) { - Strophe.error("invalid response received"); - Strophe.error("responseText: " + this.xhr.responseText); - throw "badformat"; - } - - return node; - }, - - /** PrivateFunction: _newXHR - * _Private_ helper function to create XMLHttpRequests. - * - * This function creates XMLHttpRequests across all implementations. - * - * Returns: - * A new XMLHttpRequest. - */ - _newXHR: function () { - var xhr = null; - if (window.XMLHttpRequest) { - xhr = new XMLHttpRequest(); - if (xhr.overrideMimeType) { - xhr.overrideMimeType("text/xml; charset=utf-8"); - } - } else if (window.ActiveXObject) { - xhr = new ActiveXObject("Microsoft.XMLHTTP"); - } - // use Function.bind() to prepend ourselves as an argument - xhr.onreadystatechange = this.func.bind(null, this); - return xhr; - } - }; - - /** Class: Strophe.Bosh - * _Private_ helper class that handles BOSH Connections - * - * The Strophe.Bosh class is used internally by Strophe.Connection - * to encapsulate BOSH sessions. It is not meant to be used from user's code. - */ - - /** File: bosh.js - * A JavaScript library to enable BOSH in Strophejs. - * - * this library uses Bidirectional-streams Over Synchronous HTTP (BOSH) - * to emulate a persistent, stateful, two-way connection to an XMPP server. - * More information on BOSH can be found in XEP 124. - */ - - /** PrivateConstructor: Strophe.Bosh - * Create and initialize a Strophe.Bosh object. - * - * Parameters: - * (Strophe.Connection) connection - The Strophe.Connection that will use BOSH. - * - * Returns: - * A new Strophe.Bosh object. - */ - Strophe.Bosh = function (connection) { - this._conn = connection; - /* request id for body tags */ - this.rid = Math.floor(Math.random() * 4294967295); - /* The current session ID. */ - this.sid = null; - - // default BOSH values - this.hold = 1; - this.wait = 60; - this.window = 5; - this.errors = 0; - - this._requests = []; - }; - - Strophe.Bosh.prototype = { - /** Variable: strip - * - * BOSH-Connections will have all stanzas wrapped in a tag when - * passed to or . - * To strip this tag, User code can set to "body": - * - * > Strophe.Bosh.prototype.strip = "body"; - * - * This will enable stripping of the body tag in both - * and . - */ - strip: null, - - /** PrivateFunction: _buildBody - * _Private_ helper function to generate the wrapper for BOSH. - * - * Returns: - * A Strophe.Builder with a element. - */ - _buildBody: function () { - var bodyWrap = $build('body', { - rid: this.rid++, - xmlns: Strophe.NS.HTTPBIND - }); - if (this.sid !== null) { - bodyWrap.attrs({sid: this.sid}); - } - if (this._conn.options.keepalive && this._conn._sessionCachingSupported()) { - this._cacheSession(); - } - return bodyWrap; - }, - - /** PrivateFunction: _reset - * Reset the connection. - * - * This function is called by the reset function of the Strophe Connection - */ - _reset: function () { - this.rid = Math.floor(Math.random() * 4294967295); - this.sid = null; - this.errors = 0; - if (this._conn._sessionCachingSupported()) { - window.sessionStorage.removeItem('strophe-bosh-session'); - } - - this._conn.nextValidRid(this.rid); - }, - - /** PrivateFunction: _connect - * _Private_ function that initializes the BOSH connection. - * - * Creates and sends the Request that initializes the BOSH connection. - */ - _connect: function (wait, hold, route) { - this.wait = wait || this.wait; - this.hold = hold || this.hold; - this.errors = 0; - - // build the body tag - var body = this._buildBody().attrs({ - to: this._conn.domain, - "xml:lang": "en", - wait: this.wait, - hold: this.hold, - content: "text/xml; charset=utf-8", - ver: "1.6", - "xmpp:version": "1.0", - "xmlns:xmpp": Strophe.NS.BOSH - }); - - if (route) { - body.attrs({ - route: route - }); - } - - var _connect_cb = this._conn._connect_cb; - - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, _connect_cb.bind(this._conn)), - body.tree().getAttribute("rid"))); - this._throttledRequestHandler(); - }, - - /** PrivateFunction: _attach - * Attach to an already created and authenticated BOSH session. - * - * This function is provided to allow Strophe to attach to BOSH - * sessions which have been created externally, perhaps by a Web - * application. This is often used to support auto-login type features - * without putting user credentials into the page. - * - * Parameters: - * (String) jid - The full JID that is bound by the session. - * (String) sid - The SID of the BOSH session. - * (String) rid - The current RID of the BOSH session. This RID - * will be used by the next request. - * (Function) callback The connect callback function. - * (Integer) wait - The optional HTTPBIND wait value. This is the - * time the server will wait before returning an empty result for - * a request. The default setting of 60 seconds is recommended. - * Other settings will require tweaks to the Strophe.TIMEOUT value. - * (Integer) hold - The optional HTTPBIND hold value. This is the - * number of connections the server will hold at one time. This - * should almost always be set to 1 (the default). - * (Integer) wind - The optional HTTBIND window value. This is the - * allowed range of request ids that are valid. The default is 5. - */ - _attach: function (jid, sid, rid, callback, wait, hold, wind) { - this._conn.jid = jid; - this.sid = sid; - this.rid = rid; - - this._conn.connect_callback = callback; - - this._conn.domain = Strophe.getDomainFromJid(this._conn.jid); - - this._conn.authenticated = true; - this._conn.connected = true; - - this.wait = wait || this.wait; - this.hold = hold || this.hold; - this.window = wind || this.window; - - this._conn._changeConnectStatus(Strophe.Status.ATTACHED, null); - }, - - /** PrivateFunction: _restore - * Attempt to restore a cached BOSH session - * - * Parameters: - * (String) jid - The full JID that is bound by the session. - * This parameter is optional but recommended, specifically in cases - * where prebinded BOSH sessions are used where it's important to know - * that the right session is being restored. - * (Function) callback The connect callback function. - * (Integer) wait - The optional HTTPBIND wait value. This is the - * time the server will wait before returning an empty result for - * a request. The default setting of 60 seconds is recommended. - * Other settings will require tweaks to the Strophe.TIMEOUT value. - * (Integer) hold - The optional HTTPBIND hold value. This is the - * number of connections the server will hold at one time. This - * should almost always be set to 1 (the default). - * (Integer) wind - The optional HTTBIND window value. This is the - * allowed range of request ids that are valid. The default is 5. - */ - _restore: function (jid, callback, wait, hold, wind) { - var session = JSON.parse(window.sessionStorage.getItem('strophe-bosh-session')); - if (typeof session !== "undefined" && - session !== null && - session.rid && - session.sid && - session.jid && - (typeof jid === "undefined" || jid === null || Strophe.getBareJidFromJid(session.jid) == Strophe.getBareJidFromJid(jid))) { - this._conn.restored = true; - this._attach(session.jid, session.sid, session.rid, callback, wait, hold, wind); - } else { - throw {name: "StropheSessionError", message: "_restore: no restoreable session."}; - } - }, - - /** PrivateFunction: _cacheSession - * _Private_ handler for the beforeunload event. - * - * This handler is used to process the Bosh-part of the initial request. - * Parameters: - * (Strophe.Request) bodyWrap - The received stanza. - */ - _cacheSession: function () { - if (this._conn.authenticated) { - if (this._conn.jid && this.rid && this.sid) { - window.sessionStorage.setItem('strophe-bosh-session', JSON.stringify({ - 'jid': this._conn.jid, - 'rid': this.rid, - 'sid': this.sid - })); - } - } else { - window.sessionStorage.removeItem('strophe-bosh-session'); - } - }, - - /** PrivateFunction: _connect_cb - * _Private_ handler for initial connection request. - * - * This handler is used to process the Bosh-part of the initial request. - * Parameters: - * (Strophe.Request) bodyWrap - The received stanza. - */ - _connect_cb: function (bodyWrap) { - var typ = bodyWrap.getAttribute("type"); - var cond, conflict; - if (typ !== null && typ == "terminate") { - // an error occurred - cond = bodyWrap.getAttribute("condition"); - Strophe.error("BOSH-Connection failed: " + cond); - conflict = bodyWrap.getElementsByTagName("conflict"); - if (cond !== null) { - if (cond == "remote-stream-error" && conflict.length > 0) { - cond = "conflict"; - } - this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, cond); - } else { - this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); - } - this._conn._doDisconnect(cond); - return Strophe.Status.CONNFAIL; - } - - // check to make sure we don't overwrite these if _connect_cb is - // called multiple times in the case of missing stream:features - if (!this.sid) { - this.sid = bodyWrap.getAttribute("sid"); - } - var wind = bodyWrap.getAttribute('requests'); - if (wind) { - this.window = parseInt(wind, 10); - } - var hold = bodyWrap.getAttribute('hold'); - if (hold) { - this.hold = parseInt(hold, 10); - } - var wait = bodyWrap.getAttribute('wait'); - if (wait) { - this.wait = parseInt(wait, 10); - } - }, - - /** PrivateFunction: _disconnect - * _Private_ part of Connection.disconnect for Bosh - * - * Parameters: - * (Request) pres - This stanza will be sent before disconnecting. - */ - _disconnect: function (pres) { - this._sendTerminate(pres); - }, - - /** PrivateFunction: _doDisconnect - * _Private_ function to disconnect. - * - * Resets the SID and RID. - */ - _doDisconnect: function () { - this.sid = null; - this.rid = Math.floor(Math.random() * 4294967295); - if (this._conn._sessionCachingSupported()) { - window.sessionStorage.removeItem('strophe-bosh-session'); - } - - this._conn.nextValidRid(this.rid); - }, - - /** PrivateFunction: _emptyQueue - * _Private_ function to check if the Request queue is empty. - * - * Returns: - * True, if there are no Requests queued, False otherwise. - */ - _emptyQueue: function () { - return this._requests.length === 0; - }, - - /** PrivateFunction: _callProtocolErrorHandlers - * _Private_ function to call error handlers registered for HTTP errors. - * - * Parameters: - * (Strophe.Request) req - The request that is changing readyState. - */ - _callProtocolErrorHandlers: function (req) { - var reqStatus = this._getRequestStatus(req), - err_callback; - err_callback = this._conn.protocolErrorHandlers.HTTP[reqStatus]; - if (err_callback) { - err_callback.call(this, reqStatus); - } - }, - - /** PrivateFunction: _hitError - * _Private_ function to handle the error count. - * - * Requests are resent automatically until their error count reaches - * 5. Each time an error is encountered, this function is called to - * increment the count and disconnect if the count is too high. - * - * Parameters: - * (Integer) reqStatus - The request status. - */ - _hitError: function (reqStatus) { - this.errors++; - Strophe.warn("request errored, status: " + reqStatus + - ", number of errors: " + this.errors); - if (this.errors > 4) { - this._conn._onDisconnectTimeout(); - } - }, - - /** PrivateFunction: _no_auth_received - * - * Called on stream start/restart when no stream:features - * has been received and sends a blank poll request. - */ - _no_auth_received: function (_callback) { - //console.log('_no_auth_received') - - if (_callback) { - _callback = _callback.bind(this._conn); - } else { - _callback = this._conn._connect_cb.bind(this._conn); - } - var body = this._buildBody(); - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, _callback.bind(this._conn)), - body.tree().getAttribute("rid"))); - //console.log(this._requests) - this._throttledRequestHandler(); - }, - - /** PrivateFunction: _onDisconnectTimeout - * _Private_ timeout handler for handling non-graceful disconnection. - * - * Cancels all remaining Requests and clears the queue. - */ - _onDisconnectTimeout: function () { - this._abortAllRequests(); - }, - - /** PrivateFunction: _abortAllRequests - * _Private_ helper function that makes sure all pending requests are aborted. - */ - _abortAllRequests: function _abortAllRequests() { - var req; - while (this._requests.length > 0) { - req = this._requests.pop(); - req.abort = true; - req.xhr.abort(); - // jslint complains, but this is fine. setting to empty func - // is necessary for IE6 - req.xhr.onreadystatechange = function () { - }; // jshint ignore:line - } - }, - - /** PrivateFunction: _onIdle - * _Private_ handler called by Strophe.Connection._onIdle - * - * Sends all queued Requests or polls with empty Request if there are none. - */ - _onIdle: function () { - var data = this._conn._data; - // if no requests are in progress, poll - if (this._conn.authenticated && this._requests.length === 0 && - data.length === 0 && !this._conn.disconnecting) { - Strophe.info("no requests during idle cycle, sending " + - "blank request"); - data.push(null); - } - - if (this._conn.paused) { - return; - } - - if (this._requests.length < 2 && data.length > 0) { - var body = this._buildBody(); - for (var i = 0; i < data.length; i++) { - if (data[i] !== null) { - if (data[i] === "restart") { - body.attrs({ - to: this._conn.domain, - "xml:lang": "en", - "xmpp:restart": "true", - "xmlns:xmpp": Strophe.NS.BOSH - }); - } else { - body.cnode(data[i]).up(); - } - } - } - delete this._conn._data; - this._conn._data = []; - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, this._conn._dataRecv.bind(this._conn)), - body.tree().getAttribute("rid"))); - this._throttledRequestHandler(); - } - - if (this._requests.length > 0) { - var time_elapsed = this._requests[0].age(); - if (this._requests[0].dead !== null) { - if (this._requests[0].timeDead() > - Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) { - this._throttledRequestHandler(); - } - } - - if (time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait)) { - Strophe.warn("Request " + - this._requests[0].id + - " timed out, over " + Math.floor(Strophe.TIMEOUT * this.wait) + - " seconds since last activity"); - this._throttledRequestHandler(); - } - } - }, - - /** PrivateFunction: _getRequestStatus - * - * Returns the HTTP status code from a Strophe.Request - * - * Parameters: - * (Strophe.Request) req - The Strophe.Request instance. - * (Integer) def - The default value that should be returned if no - * status value was found. - */ - _getRequestStatus: function (req, def) { - var reqStatus; - if (req.xhr.readyState == 4) { - try { - reqStatus = req.xhr.status; - } catch (e) { - // ignore errors from undefined status attribute. Works - // around a browser bug - Strophe.error( - "Caught an error while retrieving a request's status, " + - "reqStatus: " + reqStatus); - } - } - if (typeof(reqStatus) == "undefined") { - reqStatus = typeof def === 'number' ? def : 0; - } - return reqStatus; - }, - - /** PrivateFunction: _onRequestStateChange - * _Private_ handler for Strophe.Request state changes. - * - * This function is called when the XMLHttpRequest readyState changes. - * It contains a lot of error handling logic for the many ways that - * requests can fail, and calls the request callback when requests - * succeed. - * - * Parameters: - * (Function) func - The handler for the request. - * (Strophe.Request) req - The request that is changing readyState. - */ - _onRequestStateChange: function (func, req) { - Strophe.debug("request id " + req.id + "." + req.sends + - " state changed to " + req.xhr.readyState); - if (req.abort) { - req.abort = false; - return; - } - if (req.xhr.readyState !== 4) { - // The request is not yet complete - return; - } - var reqStatus = this._getRequestStatus(req); - if (this.disconnecting && reqStatus >= 400) { - this._hitError(reqStatus); - this._callProtocolErrorHandlers(req); - return; - } - - if ((reqStatus > 0 && reqStatus < 500) || req.sends > 5) { - // remove from internal queue - this._removeRequest(req); - Strophe.debug("request id " + req.id + " should now be removed"); - } - - if (reqStatus == 200) { - // request succeeded - var reqIs0 = (this._requests[0] == req); - var reqIs1 = (this._requests[1] == req); - // if request 1 finished, or request 0 finished and request - // 1 is over Strophe.SECONDARY_TIMEOUT seconds old, we need to - // restart the other - both will be in the first spot, as the - // completed request has been removed from the queue already - if (reqIs1 || - (reqIs0 && this._requests.length > 0 && - this._requests[0].age() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait))) { - this._restartRequest(0); - } - this._conn.nextValidRid(Number(req.rid) + 1); - Strophe.debug("request id " + req.id + "." + req.sends + " got 200"); - func(req); // call handler - this.errors = 0; - } else if (reqStatus === 0 || - (reqStatus >= 400 && reqStatus < 600) || - reqStatus >= 12000) { - // request failed - Strophe.error("request id " + req.id + "." + req.sends + " error " + reqStatus + " happened"); - this._hitError(reqStatus); - this._callProtocolErrorHandlers(req); - if (reqStatus >= 400 && reqStatus < 500) { - this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING, null); - this._conn._doDisconnect(); - } - } else { - Strophe.error("request id " + req.id + "." + req.sends + " error " + reqStatus + " happened"); - } - if (!(reqStatus > 0 && reqStatus < 500) || req.sends > 5) { - this._throttledRequestHandler(); - } - }, - - /** PrivateFunction: _processRequest - * _Private_ function to process a request in the queue. - * - * This function takes requests off the queue and sends them and - * restarts dead requests. - * - * Parameters: - * (Integer) i - The index of the request in the queue. - */ - _processRequest: function (i) { - var self = this; - var req = this._requests[i]; - var reqStatus = this._getRequestStatus(req, -1); - - // make sure we limit the number of retries - if (req.sends > this._conn.maxRetries) { - this._conn._onDisconnectTimeout(); - return; - } - - var time_elapsed = req.age(); - var primaryTimeout = (!isNaN(time_elapsed) && - time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait)); - var secondaryTimeout = (req.dead !== null && - req.timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)); - var requestCompletedWithServerError = (req.xhr.readyState == 4 && - (reqStatus < 1 || reqStatus >= 500)); - if (primaryTimeout || secondaryTimeout || - requestCompletedWithServerError) { - if (secondaryTimeout) { - Strophe.error("Request " + this._requests[i].id + - " timed out (secondary), restarting"); - } - req.abort = true; - req.xhr.abort(); - // setting to null fails on IE6, so set to empty function - req.xhr.onreadystatechange = function () { - }; - this._requests[i] = new Strophe.Request(req.xmlData, - req.origFunc, - req.rid, - req.sends); - req = this._requests[i]; - } - - if (req.xhr.readyState === 0) { - Strophe.debug("request id " + req.id + "." + req.sends + " posting"); - - try { - var contentType = this._conn.options.contentType || "text/xml; charset=utf-8"; - req.xhr.open("POST", this._conn.service, this._conn.options.sync ? false : true); - if (typeof req.xhr.setRequestHeader !== 'undefined') { - // IE9 doesn't have setRequestHeader - req.xhr.setRequestHeader("Content-Type", contentType); - } - if (this._conn.options.withCredentials) { - req.xhr.withCredentials = true; - } - } catch (e2) { - Strophe.error("XHR open failed."); - if (!this._conn.connected) { - this._conn._changeConnectStatus( - Strophe.Status.CONNFAIL, "bad-service"); - } - this._conn.disconnect(); - return; - } - - // Fires the XHR request -- may be invoked immediately - // or on a gradually expanding retry window for reconnects - var sendFunc = function () { - req.date = new Date(); - if (self._conn.options.customHeaders) { - var headers = self._conn.options.customHeaders; - for (var header in headers) { - if (headers.hasOwnProperty(header)) { - req.xhr.setRequestHeader(header, headers[header]); - } - } - } - req.xhr.send(req.data); - }; - - // Implement progressive backoff for reconnects -- - // First retry (send == 1) should also be instantaneous - if (req.sends > 1) { - // Using a cube of the retry number creates a nicely - // expanding retry window - var backoff = Math.min(Math.floor(Strophe.TIMEOUT * this.wait), - Math.pow(req.sends, 3)) * 1000; - setTimeout(function () { - // XXX: setTimeout should be called only with function expressions (23974bc1) - sendFunc(); - }, backoff); - } else { - sendFunc(); - } - - req.sends++; - - if (this._conn.xmlOutput !== Strophe.Connection.prototype.xmlOutput) { - if (req.xmlData.nodeName === this.strip && req.xmlData.childNodes.length) { - this._conn.xmlOutput(req.xmlData.childNodes[0]); - } else { - this._conn.xmlOutput(req.xmlData); - } - } - if (this._conn.rawOutput !== Strophe.Connection.prototype.rawOutput) { - this._conn.rawOutput(req.data); - } - } else { - Strophe.debug("_processRequest: " + - (i === 0 ? "first" : "second") + - " request has readyState of " + - req.xhr.readyState); - } - }, - - /** PrivateFunction: _removeRequest - * _Private_ function to remove a request from the queue. - * - * Parameters: - * (Strophe.Request) req - The request to remove. - */ - _removeRequest: function (req) { - Strophe.debug("removing request"); - var i; - for (i = this._requests.length - 1; i >= 0; i--) { - if (req == this._requests[i]) { - this._requests.splice(i, 1); - } - } - // IE6 fails on setting to null, so set to empty function - req.xhr.onreadystatechange = function () { - }; - this._throttledRequestHandler(); - }, - - /** PrivateFunction: _restartRequest - * _Private_ function to restart a request that is presumed dead. - * - * Parameters: - * (Integer) i - The index of the request in the queue. - */ - _restartRequest: function (i) { - var req = this._requests[i]; - if (req.dead === null) { - req.dead = new Date(); - } - - this._processRequest(i); - }, - - /** PrivateFunction: _reqToData - * _Private_ function to get a stanza out of a request. - * - * Tries to extract a stanza out of a Request Object. - * When this fails the current connection will be disconnected. - * - * Parameters: - * (Object) req - The Request. - * - * Returns: - * The stanza that was passed. - */ - _reqToData: function (req) { - try { - return req.getResponse(); - } catch (e) { - if (e != "parsererror") { - throw e; - } - this._conn.disconnect("strophe-parsererror"); - } - }, - - /** PrivateFunction: _sendTerminate - * _Private_ function to send initial disconnect sequence. - * - * This is the first step in a graceful disconnect. It sends - * the BOSH server a terminate body and includes an unavailable - * presence if authentication has completed. - */ - _sendTerminate: function (pres) { - Strophe.info("_sendTerminate was called"); - var body = this._buildBody().attrs({type: "terminate"}); - if (pres) { - body.cnode(pres.tree()); - } - var req = new Strophe.Request( - body.tree(), - this._onRequestStateChange.bind( - this, this._conn._dataRecv.bind(this._conn)), - body.tree().getAttribute("rid") - ); - this._requests.push(req); - this._throttledRequestHandler(); - }, - - /** PrivateFunction: _send - * _Private_ part of the Connection.send function for BOSH - * - * Just triggers the RequestHandler to send the messages that are in the queue - */ - _send: function () { - clearTimeout(this._conn._idleTimeout); - this._throttledRequestHandler(); - - // XXX: setTimeout should be called only with function expressions (23974bc1) - this._conn._idleTimeout = setTimeout(function () { - this._onIdle(); - }.bind(this._conn), 100); - }, - - /** PrivateFunction: _sendRestart - * - * Send an xmpp:restart stanza. - */ - _sendRestart: function () { - this._throttledRequestHandler(); - clearTimeout(this._conn._idleTimeout); - }, - - /** PrivateFunction: _throttledRequestHandler - * _Private_ function to throttle requests to the connection window. - * - * This function makes sure we don't send requests so fast that the - * request ids overflow the connection window in the case that one - * request died. - */ - _throttledRequestHandler: function () { - if (!this._requests) { - Strophe.debug("_throttledRequestHandler called with " + - "undefined requests"); - } else { - Strophe.debug("_throttledRequestHandler called with " + - this._requests.length + " requests"); - } - - if (!this._requests || this._requests.length === 0) { - return; - } - - if (this._requests.length > 0) { - this._processRequest(0); - } - - if (this._requests.length > 1 && - Math.abs(this._requests[0].rid - - this._requests[1].rid) < this.window) { - this._processRequest(1); - } - } - }; - return Strophe; - })); - - /* - This program is distributed under the terms of the MIT license. - Please see the LICENSE file for details. - - Copyright 2006-2008, OGG, LLC - */ - - /* jshint undef: true, unused: true:, noarg: true, latedef: true */ - /* global define, window, clearTimeout, WebSocket, DOMParser, Strophe, $build */ - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('strophe-websocket', ['strophe-core'], function (core) { - return factory( - core.Strophe, - core.$build - ); - }); - } else { - // Browser globals - return factory(root.Strophe, root.$build); - } - }(this, function (Strophe, $build) { - //console.log(Strophe) - /** Class: Strophe.WebSocket - * _Private_ helper class that handles WebSocket Connections - * - * The Strophe.WebSocket class is used internally by Strophe.Connection - * to encapsulate WebSocket sessions. It is not meant to be used from user's code. - */ - - /** File: websocket.js - * A JavaScript library to enable XMPP over Websocket in Strophejs. - * - * This file implements XMPP over WebSockets for Strophejs. - * If a Connection is established with a Websocket url (ws://...) - * Strophe will use WebSockets. - * For more information on XMPP-over-WebSocket see RFC 7395: - * http://tools.ietf.org/html/rfc7395 - * - * WebSocket support implemented by Andreas Guth (andreas.guth@rwth-aachen.de) - */ - - /** PrivateConstructor: Strophe.Websocket - * Create and initialize a Strophe.WebSocket object. - * Currently only sets the connection Object. - * - * Parameters: - * (Strophe.Connection) connection - The Strophe.Connection that will use WebSockets. - * - * Returns: - * A new Strophe.WebSocket object. - */ - Strophe.Websocket = function (connection) { - //console.log(connection) - this._conn = connection; - this.strip = "wrapper"; - - var service = connection.service; //"wss://im-api.sandbox.easemob.com/ws/" - if (service.indexOf("ws:") !== 0 && service.indexOf("wss:") !== 0) { - // If the service is not an absolute URL, assume it is a path and put the absolute - // URL together from options, current URL and the path. - var new_service = ""; - - if (connection.options.protocol === "ws" && window.location.protocol !== "https:") { - new_service += "ws"; - } else { - new_service += "wss"; - } - - new_service += "://" + window.location.host; - - if (service.indexOf("/") !== 0) { - new_service += window.location.pathname + service; - } else { - new_service += service; - } - - connection.service = new_service; - } - }; - - Strophe.Websocket.prototype = { - /** PrivateFunction: _buildStream - * _Private_ helper function to generate the start tag for WebSockets - * - * Returns: - * A Strophe.Builder with a element. - */ - _buildStream: function () { - return $build("open", { - "xmlns": Strophe.NS.FRAMING, - "to": this._conn.domain, - "version": '1.0' - }); - }, - - /** PrivateFunction: _check_streamerror - * _Private_ checks a message for stream:error - * - * Parameters: - * (Strophe.Request) bodyWrap - The received stanza. - * connectstatus - The ConnectStatus that will be set on error. - * Returns: - * true if there was a streamerror, false otherwise. - */ - _check_streamerror: function (bodyWrap, connectstatus) { - var errors; - if (bodyWrap.getElementsByTagNameNS) { - errors = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, "error"); - } else { - errors = bodyWrap.getElementsByTagName("stream:error"); - } - if (errors.length === 0) { - return false; - } - var error = errors[0]; - - var condition = ""; - var text = ""; - - var ns = "urn:ietf:params:xml:ns:xmpp-streams"; - for (var i = 0; i < error.childNodes.length; i++) { - var e = error.childNodes[i]; - if (e.getAttribute("xmlns") !== ns) { - break; - } - if (e.nodeName === "text") { - text = e.textContent; - } else { - condition = e.nodeName; - } - } - - var errorString = "WebSocket stream error: "; - - if (condition) { - errorString += condition; - } else { - errorString += "unknown"; - } - - if (text) { - errorString += " - " + condition; - } - - Strophe.error(errorString); - - // close the connection on stream_error - this._conn._changeConnectStatus(connectstatus, condition); - this._conn._doDisconnect(); - return true; - }, - - /** PrivateFunction: _reset - * Reset the connection. - * - * This function is called by the reset function of the Strophe Connection. - * Is not needed by WebSockets. - */ - _reset: function () { - return; - }, - - /** PrivateFunction: _connect - * _Private_ function called by Strophe.Connection.connect - * - * Creates a WebSocket for a connection and assigns Callbacks to it. - * Does nothing if there already is a WebSocket. - */ - - _connect: function () { - // Ensure that there is no open WebSocket from a previous Connection. - //wx.closeSocket() - // Create the new WobSocket - - this.socket = {} - var self = this; - //console.log('service', this._conn.service) - - this.socket.onopen = this._onOpen; - this.socket.onmessage = this._connect_cb_wrapper; - this.socket.onerror = this._onError; - this.socket.onclose = this._onClose; - this.socket.send = function (str) { - wx.sendSocketMessage({data: str}) - } - console.log('isSocketConnnected', isSocketConnnected) - - wx.connectSocket({url: this._conn.service, method: "GET"}) - // isSocketConnnected && self._onOpen() - - wx.onSocketOpen(function (res) { - console.log('WebSocket连接已打开!') - isSocketConnnected = true - // wx.sendSocketMessage({ - // data: "Hello,World:" - // }) - self.socket.onopen.call(self) - }) - wx.onSocketMessage(function (msg) { - // //console.log('onSocketMessage', msg, JSON.stringify(msg)) - self.socket.onmessage.call(self, msg); - }) - wx.onSocketClose(function () { - console.log('WebSocket连接已经关闭!') - - self.socket.onclose.call(self); - }) - }, - - /** PrivateFunction: _connect_cb - * _Private_ function called by Strophe.Connection._connect_cb - * - * checks for stream:error - * - * Parameters: - * (Strophe.Request) bodyWrap - The received stanza. - */ - _connect_cb: function (bodyWrap) { - //console.log('connnect_cb', bodyWrap) - var error = this._check_streamerror(bodyWrap, Strophe.Status.CONNFAIL); - if (error) { - return Strophe.Status.CONNFAIL; - } - }, - - /** PrivateFunction: _handleStreamStart - * _Private_ function that checks the opening tag for errors. - * - * Disconnects if there is an error and returns false, true otherwise. - * - * Parameters: - * (Node) message - Stanza containing the tag. - */ - _handleStreamStart: function (message) { - var error = false; - - //console.log('_handleStreamStart', message, typeof message) - - // Check for errors in the tag - var ns = message.getAttribute("xmlns"); - if (typeof ns !== "string") { - error = "Missing xmlns in "; - } else if (ns !== Strophe.NS.FRAMING) { - error = "Wrong xmlns in : " + ns; - } - - var ver = message.getAttribute("version"); - if (typeof ver !== "string") { - error = "Missing version in "; - } else if (ver !== "1.0") { - error = "Wrong version in : " + ver; - } - - if (error) { - this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, error); - this._conn._doDisconnect(); - return false; - } - - return true; - }, - - /** PrivateFunction: _connect_cb_wrapper - * _Private_ function that handles the first connection messages. - * - * On receiving an opening stream tag this callback replaces itself with the real - * message handler. On receiving a stream error the connection is terminated. - */ - _connect_cb_wrapper: function (message) { - //console.log('_connect_cb_wrapper inited') - - if (message.data.indexOf("\s*)*/, ""); - //console.log('_connect_cb_wrapper open 3', data) - - if (data === '') return; - - //console.log(new DOMParser().parseFromString(data, "text/xml")) - //console.log('_connect_cb_wrapper open 3.1', data) - - var streamStart = new DOMParser().parseFromString(data, "text/xml").documentElement; - //console.log('_connect_cb_wrapper open 4', streamStart) - this._conn.xmlInput(streamStart); - this._conn.rawInput(message.data); - - //_handleStreamSteart will check for XML errors and disconnect on error - //console.log('_handleStreamStart', streamStart) - if (this._handleStreamStart(streamStart)) { - //_connect_cb will check for stream:error and disconnect on error - //console.log('_connect_cb') - this._connect_cb(streamStart); - } - } else if (message.data.indexOf(" tag."); - } - } - this._conn._doDisconnect(); - }, - - /** PrivateFunction: _doDisconnect - * _Private_ function to disconnect. - * - * Just closes the Socket for WebSockets - */ - _doDisconnect: function () { - Strophe.info("WebSockets _doDisconnect was called"); - this._closeSocket(); - }, - - /** PrivateFunction _streamWrap - * _Private_ helper function to wrap a stanza in a tag. - * This is used so Strophe can process stanzas from WebSockets like BOSH - */ - _streamWrap: function (stanza) { - return "" + stanza + ''; - }, - - - /** PrivateFunction: _closeSocket - * _Private_ function to close the WebSocket. - * - * Closes the socket if it is still open and deletes it - */ - // _closeSocket: function () { - // if (this.socket) { try { - // this.socket.close(); - // } catch (e) {} } - // this.socket = null; - // }, - - /** PrivateFunction: _emptyQueue - * _Private_ function to check if the message queue is empty. - * - * Returns: - * True, because WebSocket messages are send immediately after queueing. - */ - _emptyQueue: function () { - return true; - }, - - /** PrivateFunction: _onClose - * _Private_ function to handle websockets closing. - * - * Nothing to do here for WebSockets - */ - _onClose: function () { - if (this._conn.connected && !this._conn.disconnecting) { - Strophe.error("Websocket closed unexpectedly"); - this._conn._doDisconnect(); - } else { - Strophe.info("Websocket closed"); - } - }, - - /** PrivateFunction: _no_auth_received - * - * Called on stream start/restart when no stream:features - * has been received. - */ - _no_auth_received: function (_callback) { - Strophe.error("Server did not send any auth methods"); - this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "Server did not send any auth methods"); - if (_callback) { - _callback = _callback.bind(this._conn); - _callback(); - } - this._conn._doDisconnect(); - }, - - /** PrivateFunction: _onDisconnectTimeout - * _Private_ timeout handler for handling non-graceful disconnection. - * - * This does nothing for WebSockets - */ - _onDisconnectTimeout: function () { - }, - - /** PrivateFunction: _abortAllRequests - * _Private_ helper function that makes sure all pending requests are aborted. - */ - _abortAllRequests: function () { - }, - - /** PrivateFunction: _onError - * _Private_ function to handle websockets errors. - * - * Parameters: - * (Object) error - The websocket error. - */ - _onError: function (error) { - wx.onSocketError(function (res) { - //console.log('WebSocket连接打开失败,请检查!') - }) - // Strophe.error("Websocket error " + error); - // this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "The WebSocket connection could not be established or was disconnected."); - // this._disconnect(); - }, - - /** PrivateFunction: _onIdle - * _Private_ function called by Strophe.Connection._onIdle - * - * sends all queued stanzas - */ - _onIdle: function () { - var data = this._conn._data; - if (data.length > 0 && !this._conn.paused) { - for (var i = 0; i < data.length; i++) { - if (data[i] !== null) { - var stanza, rawStanza; - if (data[i] === "restart") { - stanza = this._buildStream().tree(); - } else { - stanza = data[i]; - } - rawStanza = Strophe.serialize(stanza); - this._conn.xmlOutput(stanza); - this._conn.rawOutput(rawStanza); - - // onsend todo - wx.sendSocketMessage({data: rawStanza}) - //this.socket.send(rawStanza); - } - } - this._conn._data = []; - } - }, - - /** PrivateFunction: _onMessage - * _Private_ function to handle websockets messages. - * - * This function parses each of the messages as if they are full documents. - * [TODO : We may actually want to use a SAX Push parser]. - * - * Since all XMPP traffic starts with - * - * - * The first stanza will always fail to be parsed. - * - * Additionally, the seconds stanza will always be with - * the stream NS defined in the previous stanza, so we need to 'force' - * the inclusion of the NS in this stanza. - * - * Parameters: - * (string) message - The websocket message. - */ - _onMessage: function (message) { - //console.log('_onMessage') - // wx.sendSocketMessage({ - // data: message - // }) - var elem, data; - // check for closing stream - var close = ''; - if (message.data === close) { - this._conn.rawInput(close); - this._conn.xmlInput(message); - if (!this._conn.disconnecting) { - this._conn._doDisconnect(); - } - return; - } else if (message.data.search(" tag before we close the connection - return; - } - this._conn._dataRecv(elem, message.data); - }, - - /** PrivateFunction: _onOpen - * _Private_ function to handle websockets connection setup. - * - * The opening stream tag is sent here. - */ - _onOpen: function () { - Strophe.info("Websocket open"); - var start = this._buildStream(); - this._conn.xmlOutput(start.tree()); - - var startString = Strophe.serialize(start); - this._conn.rawOutput(startString); - // onsend todo - //console.log('startString', startString) - wx.sendSocketMessage({data: startString}) - //this.socket.send(rawStanza); - // this.socket.send(startString); - }, - - /** PrivateFunction: _reqToData - * _Private_ function to get a stanza out of a request. - * - * WebSockets don't use requests, so the passed argument is just returned. - * - * Parameters: - * (Object) stanza - The stanza. - * - * Returns: - * The stanza that was passed. - */ - _reqToData: function (stanza) { - return stanza; - }, - - /** PrivateFunction: _send - * _Private_ part of the Connection.send function for WebSocket - * - * Just flushes the messages that are in the queue - */ - _send: function () { - this._conn.flush(); - }, - - /** PrivateFunction: _sendRestart - * - * Send an xmpp:restart stanza. - */ - _sendRestart: function () { - clearTimeout(this._conn._idleTimeout); - this._conn._onIdle.bind(this._conn)(); - } - }; - return Strophe; - })); - - (function (root) { - if (typeof define === 'function' && define.amd) { - define("strophe", [ - "strophe-core", - "strophe-bosh", - "strophe-websocket" - ], function (wrapper) { - return wrapper; - }); - } - })(this); - - /* jshint ignore:start */ - if (callback) { - if (typeof define === 'function' && define.amd) { - //For backwards compatability - var n_callback = callback; - if (typeof requirejs === 'function') { - requirejs(["strophe"], function (o) { - n_callback(o.Strophe, o.$build, o.$msg, o.$iq, o.$pres); - }); - } else { - require(["strophe"], function (o) { - n_callback(o.Strophe, o.$build, o.$msg, o.$iq, o.$pres); - }); - } - } else { - return callback(Strophe, $build, $msg, $iq, $pres); - } - } - - -}.bind(window))(function (Strophe, build, msg, iq, pres) { - // window.Strophe = Strophe; - // //console.log(window.Strophe) - // window.$build = build; - // window.$msg = msg; - // window.$iq = iq; - // window.$pres = pres; -}); -/* jshint ignore:end */ diff --git a/littleApp_child/utils/xmldom/.npmignore b/littleApp_child/utils/xmldom/.npmignore deleted file mode 100644 index b094a44..0000000 --- a/littleApp_child/utils/xmldom/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -test -t -travis.yml -.project -changelog diff --git a/littleApp_child/utils/xmldom/.travis.yml b/littleApp_child/utils/xmldom/.travis.yml deleted file mode 100644 index b95408e..0000000 --- a/littleApp_child/utils/xmldom/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: node_js - -node_js: - - '0.10' - -branches: - only: - - master - - proof - - travis-ci - -# Not using `npm install --dev` because it is recursive. It will pull in the all -# development dependencies for CoffeeScript. Way too much spew in the Travis CI -# build output. - -before_install: - - npm install - - npm install istanbul coveralls - -env: - global: - - secure: "BxUHTsa1WVANLQoimilbZwa1MCWSdM9hOmPWBE/rsYb7uT/iiqkRXXwnWhKtN5CLvTvIQbiAzq4iyPID0S8UHrnxClYQrOuA6QkrtwgIEuDAmijao/bgxobPOremvkwXcpMGIwzYKyYQQtSEaEIQbqf6gSSKW9dBh/GZ/vfTsqo=" diff --git a/littleApp_child/utils/xmldom/LICENSE b/littleApp_child/utils/xmldom/LICENSE deleted file mode 100644 index 68a9b5e..0000000 --- a/littleApp_child/utils/xmldom/LICENSE +++ /dev/null @@ -1,8 +0,0 @@ -You can choose any one of those: - -The MIT License (MIT): - -link:http://opensource.org/licenses/MIT - -LGPL: -http://www.gnu.org/licenses/lgpl.html diff --git a/littleApp_child/utils/xmldom/__package__.js b/littleApp_child/utils/xmldom/__package__.js deleted file mode 100644 index b4cad28..0000000 --- a/littleApp_child/utils/xmldom/__package__.js +++ /dev/null @@ -1,4 +0,0 @@ -this.addScript('dom.js',['DOMImplementation','XMLSerializer']); -this.addScript('dom-parser.js',['DOMHandler','DOMParser'], - ['DOMImplementation','XMLReader']); -this.addScript('sax.js','XMLReader'); \ No newline at end of file diff --git a/littleApp_child/utils/xmldom/changelog b/littleApp_child/utils/xmldom/changelog deleted file mode 100644 index ab815bb..0000000 --- a/littleApp_child/utils/xmldom/changelog +++ /dev/null @@ -1,14 +0,0 @@ -### Version 0.1.16 - -Sat May 4 14:58:03 UTC 2013 - - * Correctly handle multibyte Unicode greater than two byts. #57. #56. - * Initial unit testing and test coverage. #53. #46. #19. - * Create Bower `component.json` #52. - -### Version 0.1.8 - - * Add: some test case from node-o3-xml(excludes xpath support) - * Fix: remove existed attribute before setting (bug introduced in v0.1.5) - * Fix: index direct access for childNodes and any NodeList collection(not w3c standard) - * Fix: remove last child bug diff --git a/littleApp_child/utils/xmldom/component.json b/littleApp_child/utils/xmldom/component.json deleted file mode 100644 index 93b4d57..0000000 --- a/littleApp_child/utils/xmldom/component.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "xmldom", - "version": "0.1.15", - "main": "dom-parser.js", - "ignore": [ - "**/.*", - "node_modules", - "components" - ] -} diff --git a/littleApp_child/utils/xmldom/dom-parser.js b/littleApp_child/utils/xmldom/dom-parser.js deleted file mode 100644 index d974518..0000000 --- a/littleApp_child/utils/xmldom/dom-parser.js +++ /dev/null @@ -1,261 +0,0 @@ -function DOMParser(options) { - this.options = options || {locator: {}}; - -} -DOMParser.prototype.parseFromString = function (source, mimeType) { - var options = this.options; - var sax = new XMLReader(); - var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler - var errorHandler = options.errorHandler; - var locator = options.locator; - var defaultNSMap = options.xmlns || {}; - var entityMap = {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': "'"} - if (locator) { - domBuilder.setDocumentLocator(locator) - } - - sax.errorHandler = buildErrorHandler(errorHandler, domBuilder, locator); - sax.domBuilder = options.domBuilder || domBuilder; - if (/\/x?html?$/.test(mimeType)) { - entityMap.nbsp = '\xa0'; - entityMap.copy = '\xa9'; - defaultNSMap[''] = 'http://www.w3.org/1999/xhtml'; - } - defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace'; - if (source) { - sax.parse(source, defaultNSMap, entityMap); - } else { - sax.errorHandler.error("invalid document source"); - } - return domBuilder.document; -} -function buildErrorHandler(errorImpl, domBuilder, locator) { - if (!errorImpl) { - if (domBuilder instanceof DOMHandler) { - return domBuilder; - } - errorImpl = domBuilder; - } - var errorHandler = {} - var isCallback = errorImpl instanceof Function; - locator = locator || {} - function build(key) { - var fn = errorImpl[key]; - if (!fn && isCallback) { - fn = errorImpl.length == 2 ? function (msg) { - errorImpl(key, msg) - } : errorImpl; - } - errorHandler[key] = fn && function (msg) { - fn('[xmldom ' + key + ']\t' + msg + _locator(locator)); - } || function () { - }; - } - - build('warning'); - build('error'); - build('fatalError'); - return errorHandler; -} - -//console.log('#\n\n\n\n\n\n\n####') -/** - * +ContentHandler+ErrorHandler - * +LexicalHandler+EntityResolver2 - * -DeclHandler-DTDHandler - * - * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler - * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 - * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html - */ -function DOMHandler() { - this.cdata = false; -} -function position(locator, node) { - node.lineNumber = locator.lineNumber; - node.columnNumber = locator.columnNumber; -} -/** - * @see org.xml.sax.ContentHandler#startDocument - * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html - */ -DOMHandler.prototype = { - startDocument: function () { - this.document = new DOMImplementation().createDocument(null, null, null); - if (this.locator) { - this.document.documentURI = this.locator.systemId; - } - }, - startElement: function (namespaceURI, localName, qName, attrs) { - var doc = this.document; - var el = doc.createElementNS(namespaceURI, qName || localName); - var len = attrs.length; - appendElement(this, el); - this.currentElement = el; - - this.locator && position(this.locator, el) - for (var i = 0; i < len; i++) { - var namespaceURI = attrs.getURI(i); - var value = attrs.getValue(i); - var qName = attrs.getQName(i); - var attr = doc.createAttributeNS(namespaceURI, qName); - if (attr.getOffset) { - position(attr.getOffset(1), attr) - } - attr.value = attr.nodeValue = value; - el.setAttributeNode(attr) - } - }, - endElement: function (namespaceURI, localName, qName) { - var current = this.currentElement; - var tagName = current.tagName; - this.currentElement = current.parentNode; - }, - startPrefixMapping: function (prefix, uri) { - }, - endPrefixMapping: function (prefix) { - }, - processingInstruction: function (target, data) { - var ins = this.document.createProcessingInstruction(target, data); - this.locator && position(this.locator, ins) - appendElement(this, ins); - }, - ignorableWhitespace: function (ch, start, length) { - }, - characters: function (chars, start, length) { - chars = _toString.apply(this, arguments) - //console.log(chars) - if (this.currentElement && chars) { - if (this.cdata) { - var charNode = this.document.createCDATASection(chars); - this.currentElement.appendChild(charNode); - } else { - var charNode = this.document.createTextNode(chars); - this.currentElement.appendChild(charNode); - } - this.locator && position(this.locator, charNode) - } - }, - skippedEntity: function (name) { - }, - endDocument: function () { - this.document.normalize(); - }, - setDocumentLocator: function (locator) { - if (this.locator = locator) {// && !('lineNumber' in locator)){ - locator.lineNumber = 0; - } - }, - //LexicalHandler - comment: function (chars, start, length) { - chars = _toString.apply(this, arguments) - var comm = this.document.createComment(chars); - this.locator && position(this.locator, comm) - appendElement(this, comm); - }, - - startCDATA: function () { - //used in characters() methods - this.cdata = true; - }, - endCDATA: function () { - this.cdata = false; - }, - - startDTD: function (name, publicId, systemId) { - var impl = this.document.implementation; - if (impl && impl.createDocumentType) { - var dt = impl.createDocumentType(name, publicId, systemId); - this.locator && position(this.locator, dt) - appendElement(this, dt); - } - }, - /** - * @see org.xml.sax.ErrorHandler - * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html - */ - warning: function (error) { - //console.warn('[xmldom warning]\t' + error, _locator(this.locator)); - }, - error: function (error) { - //console.error('[xmldom error]\t' + error, _locator(this.locator)); - }, - fatalError: function (error) { - //console.error('[xmldom fatalError]\t' + error, _locator(this.locator)); - throw error; - } -} -function _locator(l) { - if (l) { - return '\n@' + (l.systemId || '') + '#[line:' + l.lineNumber + ',col:' + l.columnNumber + ']' - } -} -function _toString(chars, start, length) { - if (typeof chars == 'string') { - return chars.substr(start, length) - } else {//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") - if (chars.length >= start + length || start) { - return new java.lang.String(chars, start, length) + ''; - } - return chars; - } -} - -/* - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html - * used method of org.xml.sax.ext.LexicalHandler: - * #comment(chars, start, length) - * #startCDATA() - * #endCDATA() - * #startDTD(name, publicId, systemId) - * - * - * IGNORED method of org.xml.sax.ext.LexicalHandler: - * #endDTD() - * #startEntity(name) - * #endEntity(name) - * - * - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html - * IGNORED method of org.xml.sax.ext.DeclHandler - * #attributeDecl(eName, aName, type, mode, value) - * #elementDecl(name, model) - * #externalEntityDecl(name, publicId, systemId) - * #internalEntityDecl(name, value) - * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html - * IGNORED method of org.xml.sax.EntityResolver2 - * #resolveEntity(String name,String publicId,String baseURI,String systemId) - * #resolveEntity(publicId, systemId) - * #getExternalSubset(name, baseURI) - * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html - * IGNORED method of org.xml.sax.DTDHandler - * #notationDecl(name, publicId, systemId) {}; - * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; - */ -"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g, function (key) { - DOMHandler.prototype[key] = function () { - return null - } -}) - -/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */ -function appendElement(hander, node) { - if (!hander.currentElement) { - hander.document.appendChild(node); - } else { - hander.currentElement.appendChild(node); - } -}//appendChild and setAttributeNS are preformance key - -if (typeof require == 'function') { - var XMLReader = require('./sax').XMLReader; - var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation; - var XMLSerializer = exports.XMLSerializer = require('./dom').XMLSerializer; - exports.DOMParser = DOMParser; - var DOMParser = { - DOMImplementation: DOMImplementation, - XMLSerializer: XMLSerializer, - DOMParser: DOMParser - } - module.exports = DOMParser -} diff --git a/littleApp_child/utils/xmldom/dom.js b/littleApp_child/utils/xmldom/dom.js deleted file mode 100644 index 1a94de5..0000000 --- a/littleApp_child/utils/xmldom/dom.js +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * DOM Level 2 - * Object DOMException - * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html - * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html - */ - -function copy(src, dest) { - for (var p in src) { - dest[p] = src[p]; - } -} -/** - ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));? - ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));? - */ -function _extends(Class, Super) { - var pt = Class.prototype; - if (Object.create) { - var ppt = Object.create(Super.prototype) - pt.__proto__ = ppt; - } - if (!(pt instanceof Super)) { - function t() { - }; - t.prototype = Super.prototype; - t = new t(); - copy(pt, t); - Class.prototype = pt = t; - } - if (pt.constructor != Class) { - if (typeof Class != 'function') { - //console.error("unknow Class:" + Class) - } - pt.constructor = Class - } -} -var htmlns = 'http://www.w3.org/1999/xhtml'; -// Node Types -var NodeType = {} -var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1; -var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2; -var TEXT_NODE = NodeType.TEXT_NODE = 3; -var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4; -var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5; -var ENTITY_NODE = NodeType.ENTITY_NODE = 6; -var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7; -var COMMENT_NODE = NodeType.COMMENT_NODE = 8; -var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9; -var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10; -var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11; -var NOTATION_NODE = NodeType.NOTATION_NODE = 12; - -// ExceptionCode -var ExceptionCode = {} -var ExceptionMessage = {}; -var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1] = "Index size error"), 1); -var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2] = "DOMString size error"), 2); -var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3] = "Hierarchy request error"), 3); -var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4] = "Wrong document"), 4); -var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5] = "Invalid character"), 5); -var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6] = "No data allowed"), 6); -var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7] = "No modification allowed"), 7); -var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8] = "Not found"), 8); -var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9] = "Not supported"), 9); -var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10] = "Attribute in use"), 10); -//level2 -var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11] = "Invalid state"), 11); -var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12] = "Syntax error"), 12); -var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13] = "Invalid modification"), 13); -var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14] = "Invalid namespace"), 14); -var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15] = "Invalid access"), 15); - - -function DOMException(code, message) { - if (message instanceof Error) { - var error = message; - } else { - error = this; - Error.call(this, ExceptionMessage[code]); - this.message = ExceptionMessage[code]; - if (Error.captureStackTrace) Error.captureStackTrace(this, DOMException); - } - error.code = code; - if (message) this.message = this.message + ": " + message; - return error; -}; -DOMException.prototype = Error.prototype; -copy(ExceptionCode, DOMException) -/** - * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177 - * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live. - * The items in the NodeList are accessible via an integral index, starting from 0. - */ -function NodeList() { -}; -NodeList.prototype = { - /** - * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive. - * @standard level1 - */ - length: 0, - /** - * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. - * @standard level1 - * @param index unsigned long - * Index into the collection. - * @return Node - * The node at the indexth position in the NodeList, or null if that is not a valid index. - */ - item: function (index) { - return this[index] || null; - }, - toString: function () { - for (var buf = [], i = 0; i < this.length; i++) { - serializeToString(this[i], buf); - } - return buf.join(''); - } -}; -function LiveNodeList(node, refresh) { - this._node = node; - this._refresh = refresh - _updateLiveList(this); -} -function _updateLiveList(list) { - var inc = list._node._inc || list._node.ownerDocument._inc; - if (list._inc != inc) { - var ls = list._refresh(list._node); - //console.log(ls.length) - __set__(list, 'length', ls.length); - copy(ls, list); - list._inc = inc; - } -} -LiveNodeList.prototype.item = function (i) { - _updateLiveList(this); - return this[i]; -} - -_extends(LiveNodeList, NodeList); -/** - * - * Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes. - * NamedNodeMap objects in the DOM are live. - * used for attributes or DocumentType entities - */ -function NamedNodeMap() { -}; - -function _findNodeIndex(list, node) { - var i = list.length; - while (i--) { - if (list[i] === node) { - return i - } - } -} - -function _addNamedNode(el, list, newAttr, oldAttr) { - if (oldAttr) { - list[_findNodeIndex(list, oldAttr)] = newAttr; - } else { - list[list.length++] = newAttr; - } - if (el) { - newAttr.ownerElement = el; - var doc = el.ownerDocument; - if (doc) { - oldAttr && _onRemoveAttribute(doc, el, oldAttr); - _onAddAttribute(doc, el, newAttr); - } - } -} -function _removeNamedNode(el, list, attr) { - var i = _findNodeIndex(list, attr); - if (i >= 0) { - var lastIndex = list.length - 1 - while (i < lastIndex) { - list[i] = list[++i] - } - list.length = lastIndex; - if (el) { - var doc = el.ownerDocument; - if (doc) { - _onRemoveAttribute(doc, el, attr); - attr.ownerElement = null; - } - } - } else { - throw DOMException(NOT_FOUND_ERR, new Error()) - } -} -NamedNodeMap.prototype = { - length: 0, - item: NodeList.prototype.item, - getNamedItem: function (key) { -// if(key.indexOf(':')>0 || key == 'xmlns'){ -// return null; -// } - var i = this.length; - while (i--) { - var attr = this[i]; - if (attr.nodeName == key) { - return attr; - } - } - }, - setNamedItem: function (attr) { - var el = attr.ownerElement; - if (el && el != this._ownerElement) { - throw new DOMException(INUSE_ATTRIBUTE_ERR); - } - var oldAttr = this.getNamedItem(attr.nodeName); - _addNamedNode(this._ownerElement, this, attr, oldAttr); - return oldAttr; - }, - /* returns Node */ - setNamedItemNS: function (attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR - var el = attr.ownerElement, oldAttr; - if (el && el != this._ownerElement) { - throw new DOMException(INUSE_ATTRIBUTE_ERR); - } - oldAttr = this.getNamedItemNS(attr.namespaceURI, attr.localName); - _addNamedNode(this._ownerElement, this, attr, oldAttr); - return oldAttr; - }, - - /* returns Node */ - removeNamedItem: function (key) { - var attr = this.getNamedItem(key); - _removeNamedNode(this._ownerElement, this, attr); - return attr; - - - },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR - - //for level2 - removeNamedItemNS: function (namespaceURI, localName) { - var attr = this.getNamedItemNS(namespaceURI, localName); - _removeNamedNode(this._ownerElement, this, attr); - return attr; - }, - getNamedItemNS: function (namespaceURI, localName) { - var i = this.length; - while (i--) { - var node = this[i]; - if (node.localName == localName && node.namespaceURI == namespaceURI) { - return node; - } - } - return null; - } -}; -/** - * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 - */ -function DOMImplementation(/* Object */ features) { - this._features = {}; - if (features) { - for (var feature in features) { - this._features = features[feature]; - } - } -}; - -DOMImplementation.prototype = { - hasFeature: function (/* string */ feature, /* string */ version) { - var versions = this._features[feature.toLowerCase()]; - if (versions && (!version || version in versions)) { - return true; - } else { - return false; - } - }, - // Introduced in DOM Level 2: - createDocument: function (namespaceURI, qualifiedName, doctype) {// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR - var doc = new Document(); - doc.implementation = this; - doc.childNodes = new NodeList(); - doc.doctype = doctype; - if (doctype) { - doc.appendChild(doctype); - } - if (qualifiedName) { - var root = doc.createElementNS(namespaceURI, qualifiedName); - doc.appendChild(root); - } - return doc; - }, - // Introduced in DOM Level 2: - createDocumentType: function (qualifiedName, publicId, systemId) {// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR - var node = new DocumentType(); - node.name = qualifiedName; - node.nodeName = qualifiedName; - node.publicId = publicId; - node.systemId = systemId; - // Introduced in DOM Level 2: - //readonly attribute DOMString internalSubset; - - //TODO:.. - // readonly attribute NamedNodeMap entities; - // readonly attribute NamedNodeMap notations; - return node; - } -}; - - -/** - * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 - */ - -function Node() { -}; - -Node.prototype = { - firstChild: null, - lastChild: null, - previousSibling: null, - nextSibling: null, - attributes: null, - parentNode: null, - childNodes: null, - ownerDocument: null, - nodeValue: null, - namespaceURI: null, - prefix: null, - localName: null, - // Modified in DOM Level 2: - insertBefore: function (newChild, refChild) {//raises - return _insertBefore(this, newChild, refChild); - }, - replaceChild: function (newChild, oldChild) {//raises - this.insertBefore(newChild, oldChild); - if (oldChild) { - this.removeChild(oldChild); - } - }, - removeChild: function (oldChild) { - return _removeChild(this, oldChild); - }, - appendChild: function (newChild) { - return this.insertBefore(newChild, null); - }, - hasChildNodes: function () { - return this.firstChild != null; - }, - cloneNode: function (deep) { - return cloneNode(this.ownerDocument || this, this, deep); - }, - // Modified in DOM Level 2: - normalize: function () { - var child = this.firstChild; - while (child) { - var next = child.nextSibling; - if (next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE) { - this.removeChild(next); - child.appendData(next.data); - } else { - child.normalize(); - child = next; - } - } - }, - // Introduced in DOM Level 2: - isSupported: function (feature, version) { - return this.ownerDocument.implementation.hasFeature(feature, version); - }, - // Introduced in DOM Level 2: - hasAttributes: function () { - return this.attributes.length > 0; - }, - lookupPrefix: function (namespaceURI) { - var el = this; - while (el) { - var map = el._nsMap; - //console.dir(map) - if (map) { - for (var n in map) { - if (map[n] == namespaceURI) { - return n; - } - } - } - el = el.nodeType == 2 ? el.ownerDocument : el.parentNode; - } - return null; - }, - // Introduced in DOM Level 3: - lookupNamespaceURI: function (prefix) { - var el = this; - while (el) { - var map = el._nsMap; - //console.dir(map) - if (map) { - if (prefix in map) { - return map[prefix]; - } - } - el = el.nodeType == 2 ? el.ownerDocument : el.parentNode; - } - return null; - }, - // Introduced in DOM Level 3: - isDefaultNamespace: function (namespaceURI) { - var prefix = this.lookupPrefix(namespaceURI); - return prefix == null; - } -}; - - -function _xmlEncoder(c) { - return c == '<' && '<' || - c == '>' && '>' || - c == '&' && '&' || - c == '"' && '"' || - '&#' + c.charCodeAt() + ';' -} - - -copy(NodeType, Node); -copy(NodeType, Node.prototype); - -/** - * @param callback return true for continue,false for break - * @return boolean true: break visit; - */ -function _visitNode(node, callback) { - if (callback(node)) { - return true; - } - if (node = node.firstChild) { - do { - if (_visitNode(node, callback)) { - return true - } - } while (node = node.nextSibling) - } -} - - -function Document() { -} -function _onAddAttribute(doc, el, newAttr) { - doc && doc._inc++; - var ns = newAttr.namespaceURI; - if (ns == 'http://www.w3.org/2000/xmlns/') { - //update namespace - el._nsMap[newAttr.prefix ? newAttr.localName : ''] = newAttr.value - } -} -function _onRemoveAttribute(doc, el, newAttr, remove) { - doc && doc._inc++; - var ns = newAttr.namespaceURI; - if (ns == 'http://www.w3.org/2000/xmlns/') { - //update namespace - delete el._nsMap[newAttr.prefix ? newAttr.localName : ''] - } -} -function _onUpdateChild(doc, el, newChild) { - if (doc && doc._inc) { - doc._inc++; - //update childNodes - var cs = el.childNodes; - if (newChild) { - cs[cs.length++] = newChild; - } else { - //console.log(1) - var child = el.firstChild; - var i = 0; - while (child) { - cs[i++] = child; - child = child.nextSibling; - } - cs.length = i; - } - } -} - -/** - * attributes; - * children; - * - * writeable properties: - * nodeValue,Attr:value,CharacterData:data - * prefix - */ -function _removeChild(parentNode, child) { - var previous = child.previousSibling; - var next = child.nextSibling; - if (previous) { - previous.nextSibling = next; - } else { - parentNode.firstChild = next - } - if (next) { - next.previousSibling = previous; - } else { - parentNode.lastChild = previous; - } - _onUpdateChild(parentNode.ownerDocument, parentNode); - return child; -} -/** - * preformance key(refChild == null) - */ -function _insertBefore(parentNode, newChild, nextChild) { - var cp = newChild.parentNode; - if (cp) { - cp.removeChild(newChild);//remove and update - } - if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) { - var newFirst = newChild.firstChild; - if (newFirst == null) { - return newChild; - } - var newLast = newChild.lastChild; - } else { - newFirst = newLast = newChild; - } - var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild; - - newFirst.previousSibling = pre; - newLast.nextSibling = nextChild; - - - if (pre) { - pre.nextSibling = newFirst; - } else { - parentNode.firstChild = newFirst; - } - if (nextChild == null) { - parentNode.lastChild = newLast; - } else { - nextChild.previousSibling = newLast; - } - do { - newFirst.parentNode = parentNode; - } while (newFirst !== newLast && (newFirst = newFirst.nextSibling)) - _onUpdateChild(parentNode.ownerDocument || parentNode, parentNode); - //console.log(parentNode.lastChild.nextSibling == null) - if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { - newChild.firstChild = newChild.lastChild = null; - } - return newChild; -} -function _appendSingleChild(parentNode, newChild) { - var cp = newChild.parentNode; - if (cp) { - var pre = parentNode.lastChild; - cp.removeChild(newChild);//remove and update - var pre = parentNode.lastChild; - } - var pre = parentNode.lastChild; - newChild.parentNode = parentNode; - newChild.previousSibling = pre; - newChild.nextSibling = null; - if (pre) { - pre.nextSibling = newChild; - } else { - parentNode.firstChild = newChild; - } - parentNode.lastChild = newChild; - _onUpdateChild(parentNode.ownerDocument, parentNode, newChild); - return newChild; - //console.log("__aa",parentNode.lastChild.nextSibling == null) -} -Document.prototype = { - //implementation : null, - nodeName: '#document', - nodeType: DOCUMENT_NODE, - doctype: null, - documentElement: null, - _inc: 1, - - insertBefore: function (newChild, refChild) {//raises - if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { - var child = newChild.firstChild; - while (child) { - var next = child.nextSibling; - this.insertBefore(child, refChild); - child = next; - } - return newChild; - } - if (this.documentElement == null && newChild.nodeType == 1) { - this.documentElement = newChild; - } - - return _insertBefore(this, newChild, refChild), (newChild.ownerDocument = this), newChild; - }, - removeChild: function (oldChild) { - if (this.documentElement == oldChild) { - this.documentElement = null; - } - return _removeChild(this, oldChild); - }, - // Introduced in DOM Level 2: - importNode: function (importedNode, deep) { - return importNode(this, importedNode, deep); - }, - // Introduced in DOM Level 2: - getElementById: function (id) { - var rtv = null; - _visitNode(this.documentElement, function (node) { - if (node.nodeType == 1) { - if (node.getAttribute('id') == id) { - rtv = node; - return true; - } - } - }) - return rtv; - }, - - //document factory method: - createElement: function (tagName) { - var node = new Element(); - node.ownerDocument = this; - node.nodeName = tagName; - node.tagName = tagName; - node.childNodes = new NodeList(); - var attrs = node.attributes = new NamedNodeMap(); - attrs._ownerElement = node; - return node; - }, - createDocumentFragment: function () { - var node = new DocumentFragment(); - node.ownerDocument = this; - node.childNodes = new NodeList(); - return node; - }, - createTextNode: function (data) { - var node = new Text(); - node.ownerDocument = this; - node.appendData(data) - return node; - }, - createComment: function (data) { - var node = new Comment(); - node.ownerDocument = this; - node.appendData(data) - return node; - }, - createCDATASection: function (data) { - var node = new CDATASection(); - node.ownerDocument = this; - node.appendData(data) - return node; - }, - createProcessingInstruction: function (target, data) { - var node = new ProcessingInstruction(); - node.ownerDocument = this; - node.tagName = node.target = target; - node.nodeValue = node.data = data; - return node; - }, - createAttribute: function (name) { - var node = new Attr(); - node.ownerDocument = this; - node.name = name; - node.nodeName = name; - node.localName = name; - node.specified = true; - return node; - }, - createEntityReference: function (name) { - var node = new EntityReference(); - node.ownerDocument = this; - node.nodeName = name; - return node; - }, - // Introduced in DOM Level 2: - createElementNS: function (namespaceURI, qualifiedName) { - var node = new Element(); - var pl = qualifiedName.split(':'); - var attrs = node.attributes = new NamedNodeMap(); - node.childNodes = new NodeList(); - node.ownerDocument = this; - node.nodeName = qualifiedName; - node.tagName = qualifiedName; - node.namespaceURI = namespaceURI; - if (pl.length == 2) { - node.prefix = pl[0]; - node.localName = pl[1]; - } else { - //el.prefix = null; - node.localName = qualifiedName; - } - attrs._ownerElement = node; - return node; - }, - // Introduced in DOM Level 2: - createAttributeNS: function (namespaceURI, qualifiedName) { - var node = new Attr(); - var pl = qualifiedName.split(':'); - node.ownerDocument = this; - node.nodeName = qualifiedName; - node.name = qualifiedName; - node.namespaceURI = namespaceURI; - node.specified = true; - if (pl.length == 2) { - node.prefix = pl[0]; - node.localName = pl[1]; - } else { - //el.prefix = null; - node.localName = qualifiedName; - } - return node; - } -}; -_extends(Document, Node); - - -function Element() { - this._nsMap = {}; -}; -Element.prototype = { - nodeType: ELEMENT_NODE, - hasAttribute: function (name) { - return this.getAttributeNode(name) != null; - }, - getAttribute: function (name) { - var attr = this.getAttributeNode(name); - return attr && attr.value || ''; - }, - getAttributeNode: function (name) { - return this.attributes.getNamedItem(name); - }, - setAttribute: function (name, value) { - var attr = this.ownerDocument.createAttribute(name); - attr.value = attr.nodeValue = "" + value; - this.setAttributeNode(attr) - }, - removeAttribute: function (name) { - var attr = this.getAttributeNode(name) - attr && this.removeAttributeNode(attr); - }, - - //four real opeartion method - appendChild: function (newChild) { - if (newChild.nodeType === DOCUMENT_FRAGMENT_NODE) { - return this.insertBefore(newChild, null); - } else { - return _appendSingleChild(this, newChild); - } - }, - setAttributeNode: function (newAttr) { - return this.attributes.setNamedItem(newAttr); - }, - setAttributeNodeNS: function (newAttr) { - return this.attributes.setNamedItemNS(newAttr); - }, - removeAttributeNode: function (oldAttr) { - return this.attributes.removeNamedItem(oldAttr.nodeName); - }, - //get real attribute name,and remove it by removeAttributeNode - removeAttributeNS: function (namespaceURI, localName) { - var old = this.getAttributeNodeNS(namespaceURI, localName); - old && this.removeAttributeNode(old); - }, - - hasAttributeNS: function (namespaceURI, localName) { - return this.getAttributeNodeNS(namespaceURI, localName) != null; - }, - getAttributeNS: function (namespaceURI, localName) { - var attr = this.getAttributeNodeNS(namespaceURI, localName); - return attr && attr.value || ''; - }, - setAttributeNS: function (namespaceURI, qualifiedName, value) { - var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName); - attr.value = attr.nodeValue = "" + value; - this.setAttributeNode(attr) - }, - getAttributeNodeNS: function (namespaceURI, localName) { - return this.attributes.getNamedItemNS(namespaceURI, localName); - }, - - getElementsByTagName: function (tagName) { - return new LiveNodeList(this, function (base) { - var ls = []; - _visitNode(base, function (node) { - if (node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)) { - ls.push(node); - } - }); - return ls; - }); - }, - getElementsByTagNameNS: function (namespaceURI, localName) { - return new LiveNodeList(this, function (base) { - var ls = []; - _visitNode(base, function (node) { - if (node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)) { - ls.push(node); - } - }); - return ls; - }); - } -}; -Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName; -Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS; - - -_extends(Element, Node); -function Attr() { -}; -Attr.prototype.nodeType = ATTRIBUTE_NODE; -_extends(Attr, Node); - - -function CharacterData() { -}; -CharacterData.prototype = { - data: '', - substringData: function (offset, count) { - return this.data.substring(offset, offset + count); - }, - appendData: function (text) { - text = this.data + text; - this.nodeValue = this.data = text; - this.length = text.length; - }, - insertData: function (offset, text) { - this.replaceData(offset, 0, text); - - }, - appendChild: function (newChild) { - //if(!(newChild instanceof CharacterData)){ - throw new Error(ExceptionMessage[3]) - //} - return Node.prototype.appendChild.apply(this, arguments) - }, - deleteData: function (offset, count) { - this.replaceData(offset, count, ""); - }, - replaceData: function (offset, count, text) { - var start = this.data.substring(0, offset); - var end = this.data.substring(offset + count); - text = start + text + end; - this.nodeValue = this.data = text; - this.length = text.length; - } -} -_extends(CharacterData, Node); -function Text() { -}; -Text.prototype = { - nodeName: "#text", - nodeType: TEXT_NODE, - splitText: function (offset) { - var text = this.data; - var newText = text.substring(offset); - text = text.substring(0, offset); - this.data = this.nodeValue = text; - this.length = text.length; - var newNode = this.ownerDocument.createTextNode(newText); - if (this.parentNode) { - this.parentNode.insertBefore(newNode, this.nextSibling); - } - return newNode; - } -} -_extends(Text, CharacterData); -function Comment() { -}; -Comment.prototype = { - nodeName: "#comment", - nodeType: COMMENT_NODE -} -_extends(Comment, CharacterData); - -function CDATASection() { -}; -CDATASection.prototype = { - nodeName: "#cdata-section", - nodeType: CDATA_SECTION_NODE -} -_extends(CDATASection, CharacterData); - - -function DocumentType() { -}; -DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE; -_extends(DocumentType, Node); - -function Notation() { -}; -Notation.prototype.nodeType = NOTATION_NODE; -_extends(Notation, Node); - -function Entity() { -}; -Entity.prototype.nodeType = ENTITY_NODE; -_extends(Entity, Node); - -function EntityReference() { -}; -EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE; -_extends(EntityReference, Node); - -function DocumentFragment() { -}; -DocumentFragment.prototype.nodeName = "#document-fragment"; -DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE; -_extends(DocumentFragment, Node); - - -function ProcessingInstruction() { -} -ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE; -_extends(ProcessingInstruction, Node); -function XMLSerializer() { -} -XMLSerializer.prototype.serializeToString = function (node, attributeSorter) { - return node.toString(attributeSorter); -} -Node.prototype.toString = function (attributeSorter) { - var buf = []; - serializeToString(this, buf, attributeSorter); - return buf.join(''); -} -function serializeToString(node, buf, attributeSorter, isHTML) { - switch (node.nodeType) { - case ELEMENT_NODE: - var attrs = node.attributes; - var len = attrs.length; - var child = node.firstChild; - var nodeName = node.tagName; - isHTML = (htmlns === node.namespaceURI) || isHTML - buf.push('<', nodeName); - if (attributeSorter) { - buf.sort.apply(attrs, attributeSorter); - } - for (var i = 0; i < len; i++) { - serializeToString(attrs.item(i), buf, attributeSorter, isHTML); - } - if (child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)) { - buf.push('>'); - //if is cdata child node - if (isHTML && /^script$/i.test(nodeName)) { - if (child) { - buf.push(child.data); - } - } else { - while (child) { - serializeToString(child, buf, attributeSorter, isHTML); - child = child.nextSibling; - } - } - buf.push(''); - } else { - buf.push('/>'); - } - return; - case DOCUMENT_NODE: - case DOCUMENT_FRAGMENT_NODE: - var child = node.firstChild; - while (child) { - serializeToString(child, buf, attributeSorter, isHTML); - child = child.nextSibling; - } - return; - case ATTRIBUTE_NODE: - return buf.push(' ', node.name, '="', node.value.replace(/[<&"]/g, _xmlEncoder), '"'); - case TEXT_NODE: - return buf.push(node.data.replace(/[<&]/g, _xmlEncoder)); - case CDATA_SECTION_NODE: - return buf.push(''); - case COMMENT_NODE: - return buf.push(""); - case DOCUMENT_TYPE_NODE: - var pubid = node.publicId; - var sysid = node.systemId; - buf.push(''); - } else if (sysid && sysid != '.') { - buf.push(' SYSTEM "', sysid, '">'); - } else { - var sub = node.internalSubset; - if (sub) { - buf.push(" [", sub, "]"); - } - buf.push(">"); - } - return; - case PROCESSING_INSTRUCTION_NODE: - return buf.push(""); - case ENTITY_REFERENCE_NODE: - return buf.push('&', node.nodeName, ';'); - //case ENTITY_NODE: - //case NOTATION_NODE: - default: - buf.push('??', node.nodeName); - } -} -function importNode(doc, node, deep) { - var node2; - switch (node.nodeType) { - case ELEMENT_NODE: - node2 = node.cloneNode(false); - node2.ownerDocument = doc; - //var attrs = node2.attributes; - //var len = attrs.length; - //for(var i=0;i=0.1" - }, - "gitHead": "29a83b315aef56c156602286b2d884a3b4c2521f", - "homepage": "https://github.com/jindw/xmldom", - "keywords": [ - "w3c", - "dom", - "xml", - "parser", - "javascript", - "DOMParser", - "XMLSerializer" - ], - "licenses": [ - { - "type": "LGPL", - "url": "http://www.gnu.org/licenses/lgpl.html", - "MIT": "http://opensource.org/licenses/MIT" - } - ], - "main": "./dom-parser.js", - "maintainers": [ - { - "name": "bigeasy", - "email": "alan@prettyrobots.com" - }, - { - "name": "jindw", - "email": "jindw@xidea.org" - }, - { - "name": "jinjinyun", - "email": "jinyun.jin@gmail.com" - }, - { - "name": "kethinov", - "email": "kethinov@gmail.com" - }, - { - "name": "yaron", - "email": "yaronn01@gmail.com" - } - ], - "name": "xmldom", - "optionalDependencies": {}, - "publish_time": 1454154611848, - "readme": "ERROR: No README data found!", - "repository": { - "type": "git", - "url": "git://github.com/jindw/xmldom.git" - }, - "scripts": { - "test": "proof platform win32 && proof test */*/*.t.js || t/test" - }, - "version": "0.1.22" -} diff --git a/littleApp_child/utils/xmldom/readme.md b/littleApp_child/utils/xmldom/readme.md deleted file mode 100644 index f832c44..0000000 --- a/littleApp_child/utils/xmldom/readme.md +++ /dev/null @@ -1,219 +0,0 @@ -# XMLDOM [![Build Status](https://secure.travis-ci.org/bigeasy/xmldom.png?branch=master)](http://travis-ci.org/bigeasy/xmldom) [![Coverage Status](https://coveralls.io/repos/bigeasy/xmldom/badge.png?branch=master)](https://coveralls.io/r/bigeasy/xmldom) [![NPM version](https://badge.fury.io/js/xmldom.png)](http://badge.fury.io/js/xmldom) - -A JavaScript implementation of W3C DOM for Node.js, Rhino and the browser. Fully -compatible with `W3C DOM level2`; and some compatible with `level3`. Supports -`DOMParser` and `XMLSerializer` interface such as in browser. - -Install: -------- ->npm install xmldom - -Example: -==== -```javascript -var DOMParser = require('xmldom').DOMParser; -var doc = new DOMParser().parseFromString( - '\n'+ - '\ttest\n'+ - '\t\n'+ - '\t\n'+ - '' - ,'text/xml'); -doc.documentElement.setAttribute('x','y'); -doc.documentElement.setAttributeNS('./lite','c:x','y2'); -var nsAttr = doc.documentElement.getAttributeNS('./lite','x') -console.info(nsAttr) -console.info(doc) -``` -API Reference -===== - - * [DOMParser](https://developer.mozilla.org/en/DOMParser): - - ```javascript - parseFromString(xmlsource,mimeType) - ``` - * **options extension** _by xmldom_(not BOM standard!!) - - ```javascript - //added the options argument - new DOMParser(options) - - //errorHandler is supported - new DOMParser({ - /** - * locator is always need for error position info - */ - locator:{}, - /** - * you can override the errorHandler for xml parser - * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html - */ - errorHandler:{warning:function(w){console.warn(w)},error:callback,fatalError:callback} - //only callback model - //errorHandler:function(level,msg){console.log(level,msg)} - }) - - ``` - - * [XMLSerializer](https://developer.mozilla.org/en/XMLSerializer) - - ```javascript - serializeToString(node) - ``` -DOM level2 method and attribute: ------- - - * [Node](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247) - - attribute: - nodeValue|prefix - readonly attribute: - nodeName|nodeType|parentNode|childNodes|firstChild|lastChild|previousSibling|nextSibling|attributes|ownerDocument|namespaceURI|localName - method: - insertBefore(newChild, refChild) - replaceChild(newChild, oldChild) - removeChild(oldChild) - appendChild(newChild) - hasChildNodes() - cloneNode(deep) - normalize() - isSupported(feature, version) - hasAttributes() - - * [DOMImplementation](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-102161490) - - method: - hasFeature(feature, version) - createDocumentType(qualifiedName, publicId, systemId) - createDocument(namespaceURI, qualifiedName, doctype) - - * [Document](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document) : Node - - readonly attribute: - doctype|implementation|documentElement - method: - createElement(tagName) - createDocumentFragment() - createTextNode(data) - createComment(data) - createCDATASection(data) - createProcessingInstruction(target, data) - createAttribute(name) - createEntityReference(name) - getElementsByTagName(tagname) - importNode(importedNode, deep) - createElementNS(namespaceURI, qualifiedName) - createAttributeNS(namespaceURI, qualifiedName) - getElementsByTagNameNS(namespaceURI, localName) - getElementById(elementId) - - * [DocumentFragment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-B63ED1A3) : Node - * [Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614) : Node - - readonly attribute: - tagName - method: - getAttribute(name) - setAttribute(name, value) - removeAttribute(name) - getAttributeNode(name) - setAttributeNode(newAttr) - removeAttributeNode(oldAttr) - getElementsByTagName(name) - getAttributeNS(namespaceURI, localName) - setAttributeNS(namespaceURI, qualifiedName, value) - removeAttributeNS(namespaceURI, localName) - getAttributeNodeNS(namespaceURI, localName) - setAttributeNodeNS(newAttr) - getElementsByTagNameNS(namespaceURI, localName) - hasAttribute(name) - hasAttributeNS(namespaceURI, localName) - - * [Attr](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-637646024) : Node - - attribute: - value - readonly attribute: - name|specified|ownerElement - - * [NodeList](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177) - - readonly attribute: - length - method: - item(index) - - * [NamedNodeMap](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1780488922) - - readonly attribute: - length - method: - getNamedItem(name) - setNamedItem(arg) - removeNamedItem(name) - item(index) - getNamedItemNS(namespaceURI, localName) - setNamedItemNS(arg) - removeNamedItemNS(namespaceURI, localName) - - * [CharacterData](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-FF21A306) : Node - - method: - substringData(offset, count) - appendData(arg) - insertData(offset, arg) - deleteData(offset, count) - replaceData(offset, count, arg) - - * [Text](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1312295772) : CharacterData - - method: - splitText(offset) - - * [CDATASection](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-667469212) - * [Comment](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1728279322) : CharacterData - - * [DocumentType](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-412266927) - - readonly attribute: - name|entities|notations|publicId|systemId|internalSubset - - * Notation : Node - - readonly attribute: - publicId|systemId - - * Entity : Node - - readonly attribute: - publicId|systemId|notationName - - * EntityReference : Node - * ProcessingInstruction : Node - - attribute: - data - readonly attribute: - target - -DOM level 3 support: ------ - - * [Node](http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-textContent) - - attribute: - textContent - method: - isDefaultNamespace(namespaceURI){ - lookupNamespaceURI(prefix) - -DOM extension by xmldom ---- - * [Node] Source position extension; - - attribute: - //Numbered starting from '1' - lineNumber - //Numbered starting from '1' - columnNumber diff --git a/littleApp_child/utils/xmldom/sax.js b/littleApp_child/utils/xmldom/sax.js deleted file mode 100644 index f5ab8f4..0000000 --- a/littleApp_child/utils/xmldom/sax.js +++ /dev/null @@ -1,614 +0,0 @@ -//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] -//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] -//[5] Name ::= NameStartChar (NameChar)* -var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF -var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\u00B7\u0300-\u036F\\u203F-\u2040]"); -var tagNamePattern = new RegExp('^' + nameStartChar.source + nameChar.source + '*(?:\:' + nameStartChar.source + nameChar.source + '*)?$'); -//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ -//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',') - -//S_TAG, S_ATTR, S_EQ, S_V -//S_ATTR_S, S_E, S_S, S_C -var S_TAG = 0;//tag name offerring -var S_ATTR = 1;//attr name offerring -var S_ATTR_S = 2;//attr name end and space offer -var S_EQ = 3;//=space? -var S_V = 4;//attr value(no quot value only) -var S_E = 5;//attr value end and no space(quot end) -var S_S = 6;//(attr value end || tag end ) && (space offer) -var S_C = 7;//closed el - -function XMLReader() { - -} - -XMLReader.prototype = { - parse: function (source, defaultNSMap, entityMap) { - var domBuilder = this.domBuilder; - domBuilder.startDocument(); - _copy(defaultNSMap, defaultNSMap = {}) - parse(source, defaultNSMap, entityMap, - domBuilder, this.errorHandler); - domBuilder.endDocument(); - } -} -function parse(source, defaultNSMapCopy, entityMap, domBuilder, errorHandler) { - function fixedFromCharCode(code) { - // String.prototype.fromCharCode does not supports - // > 2 bytes unicode chars directly - if (code > 0xffff) { - code -= 0x10000; - var surrogate1 = 0xd800 + (code >> 10) - , surrogate2 = 0xdc00 + (code & 0x3ff); - - return String.fromCharCode(surrogate1, surrogate2); - } else { - return String.fromCharCode(code); - } - } - - function entityReplacer(a) { - var k = a.slice(1, -1); - if (k in entityMap) { - return entityMap[k]; - } else if (k.charAt(0) === '#') { - return fixedFromCharCode(parseInt(k.substr(1).replace('x', '0x'))) - } else { - errorHandler.error('entity not found:' + a); - return a; - } - } - - function appendText(end) {//has some bugs - if (end > start) { - var xt = source.substring(start, end).replace(/&#?\w+;/g, entityReplacer); - locator && position(start); - domBuilder.characters(xt, 0, end - start); - start = end - } - } - - function position(p, m) { - while (p >= lineEnd && (m = linePattern.exec(source))) { - lineStart = m.index; - lineEnd = lineStart + m[0].length; - locator.lineNumber++; - ////console.log('line++:',locator,startPos,endPos) - } - locator.columnNumber = p - lineStart + 1; - } - - var lineStart = 0; - var lineEnd = 0; - var linePattern = /.+(?:\r\n?|\n)|.*$/g - var locator = domBuilder.locator; - - var parseStack = [{currentNSMap: defaultNSMapCopy}] - var closeMap = {}; - var start = 0; - while (true) { - try { - var tagStart = source.indexOf('<', start); - if (tagStart < 0) { - if (!source.substr(start).match(/^\s*$/)) { - var doc = domBuilder.document; - var text = doc.createTextNode(source.substr(start)); - doc.appendChild(text); - domBuilder.currentElement = text; - } - return; - } - if (tagStart > start) { - appendText(tagStart); - } - switch (source.charAt(tagStart + 1)) { - case '/': - var end = source.indexOf('>', tagStart + 3); - var tagName = source.substring(tagStart + 2, end); - var config = parseStack.pop(); - var localNSMap = config.localNSMap; - if (config.tagName != tagName) { - errorHandler.fatalError("end tag name: " + tagName + ' is not match the current start tagName:' + config.tagName); - } - domBuilder.endElement(config.uri, config.localName, tagName); - if (localNSMap) { - for (var prefix in localNSMap) { - domBuilder.endPrefixMapping(prefix); - } - } - end++; - break; - // end elment - case '?':// - locator && position(tagStart); - end = parseInstruction(source, tagStart, domBuilder); - break; - case '!':// start) { - start = end; - } else { - //TODO: 这里有可能sax回退,有位置错误风险 - appendText(Math.max(tagStart, start) + 1); - } - } -} -function copyLocator(f, t) { - t.lineNumber = f.lineNumber; - t.columnNumber = f.columnNumber; - return t; -} - -/** - * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack); - * @return end of the elementStartPart(end of elementEndPart for selfClosed el) - */ -function parseElementStartPart(source, start, el, entityReplacer, errorHandler) { - var attrName; - var value; - var p = ++start; - var s = S_TAG;//status - while (true) { - var c = source.charAt(p); - switch (c) { - case '=': - if (s === S_ATTR) {//attrName - attrName = source.slice(start, p); - s = S_EQ; - } else if (s === S_ATTR_S) { - s = S_EQ; - } else { - //fatalError: equal must after attrName or space after attrName - throw new Error('attribute equal must after attrName'); - } - break; - case '\'': - case '"': - if (s === S_EQ) {//equal - start = p + 1; - p = source.indexOf(c, start) - if (p > 0) { - value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); - el.add(attrName, value, start - 1); - s = S_E; - } else { - //fatalError: no end quot match - throw new Error('attribute value no end \'' + c + '\' match'); - } - } else if (s == S_V) { - value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); - ////console.log(attrName,value,start,p) - el.add(attrName, value, start); - //console.dir(el) - errorHandler.warning('attribute "' + attrName + '" missed start quot(' + c + ')!!'); - start = p + 1; - s = S_E - } else { - //fatalError: no equal before - throw new Error('attribute value must after "="'); - } - break; - case '/': - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p)); - case S_E: - case S_S: - case S_C: - s = S_C; - el.closed = true; - case S_V: - case S_ATTR: - case S_ATTR_S: - break; - //case S_EQ: - default: - throw new Error("attribute invalid close char('/')") - } - break; - case ''://end document - //throw new Error('unexpected end of input') - errorHandler.error('unexpected end of input'); - case '>': - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p)); - case S_E: - case S_S: - case S_C: - break;//normal - case S_V://Compatible state - case S_ATTR: - value = source.slice(start, p); - if (value.slice(-1) === '/') { - el.closed = true; - value = value.slice(0, -1) - } - case S_ATTR_S: - if (s === S_ATTR_S) { - value = attrName; - } - if (s == S_V) { - errorHandler.warning('attribute "' + value + '" missed quot(")!!'); - el.add(attrName, value.replace(/&#?\w+;/g, entityReplacer), start) - } else { - errorHandler.warning('attribute "' + value + '" missed value!! "' + value + '" instead!!') - el.add(value, value, start) - } - break; - case S_EQ: - throw new Error('attribute value missed!!'); - } -// //console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) - return p; - /*xml space '\x20' | #x9 | #xD | #xA; */ - case '\u0080': - c = ' '; - default: - if (c <= ' ') {//space - switch (s) { - case S_TAG: - el.setTagName(source.slice(start, p));//tagName - s = S_S; - break; - case S_ATTR: - attrName = source.slice(start, p) - s = S_ATTR_S; - break; - case S_V: - var value = source.slice(start, p).replace(/&#?\w+;/g, entityReplacer); - errorHandler.warning('attribute "' + value + '" missed quot(")!!'); - el.add(attrName, value, start) - case S_E: - s = S_S; - break; - //case S_S: - //case S_EQ: - //case S_ATTR_S: - // void();break; - //case S_C: - //ignore warning - } - } else {//not space -//S_TAG, S_ATTR, S_EQ, S_V -//S_ATTR_S, S_E, S_S, S_C - switch (s) { - //case S_TAG:void();break; - //case S_ATTR:void();break; - //case S_V:void();break; - case S_ATTR_S: - errorHandler.warning('attribute "' + attrName + '" missed value!! "' + attrName + '" instead!!') - el.add(attrName, attrName, start); - start = p; - s = S_ATTR; - break; - case S_E: - errorHandler.warning('attribute space is required"' + attrName + '"!!') - case S_S: - s = S_ATTR; - start = p; - break; - case S_EQ: - s = S_V; - start = p; - break; - case S_C: - throw new Error("elements closed character '/' and '>' must be connected to"); - } - } - } - p++; - } -} -/** - * @return end of the elementStartPart(end of elementEndPart for selfClosed el) - */ -function appendElement(el, domBuilder, parseStack) { - var tagName = el.tagName; - var localNSMap = null; - var currentNSMap = parseStack[parseStack.length - 1].currentNSMap; - var i = el.length; - while (i--) { - var a = el[i]; - var qName = a.qName; - var value = a.value; - var nsp = qName.indexOf(':'); - if (nsp > 0) { - var prefix = a.prefix = qName.slice(0, nsp); - var localName = qName.slice(nsp + 1); - var nsPrefix = prefix === 'xmlns' && localName - } else { - localName = qName; - prefix = null - nsPrefix = qName === 'xmlns' && '' - } - //can not set prefix,because prefix !== '' - a.localName = localName; - //prefix == null for no ns prefix attribute - if (nsPrefix !== false) {//hack!! - if (localNSMap == null) { - localNSMap = {} - ////console.log(currentNSMap,0) - _copy(currentNSMap, currentNSMap = {}) - ////console.log(currentNSMap,1) - } - currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; - a.uri = 'http://www.w3.org/2000/xmlns/' - domBuilder.startPrefixMapping(nsPrefix, value) - } - } - var i = el.length; - while (i--) { - a = el[i]; - var prefix = a.prefix; - if (prefix) {//no prefix attribute has no namespace - if (prefix === 'xml') { - a.uri = 'http://www.w3.org/XML/1998/namespace'; - } - if (prefix !== 'xmlns') { - a.uri = currentNSMap[prefix] - - //{//console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} - } - } - } - var nsp = tagName.indexOf(':'); - if (nsp > 0) { - prefix = el.prefix = tagName.slice(0, nsp); - localName = el.localName = tagName.slice(nsp + 1); - } else { - prefix = null;//important!! - localName = el.localName = tagName; - } - //no prefix element has default namespace - var ns = el.uri = currentNSMap[prefix || '']; - domBuilder.startElement(ns, localName, tagName, el); - //endPrefixMapping and startPrefixMapping have not any help for dom builder - //localNSMap = null - if (el.closed) { - domBuilder.endElement(ns, localName, tagName); - if (localNSMap) { - for (prefix in localNSMap) { - domBuilder.endPrefixMapping(prefix) - } - } - } else { - el.currentNSMap = currentNSMap; - el.localNSMap = localNSMap; - parseStack.push(el); - } -} -function parseHtmlSpecialContent(source, elStartEnd, tagName, entityReplacer, domBuilder) { - if (/^(?:script|textarea)$/i.test(tagName)) { - var elEndStart = source.indexOf('', elStartEnd); - var text = source.substring(elStartEnd + 1, elEndStart); - if (/[&<]/.test(text)) { - if (/^script$/i.test(tagName)) { - //if(!/\]\]>/.test(text)){ - //lexHandler.startCDATA(); - domBuilder.characters(text, 0, text.length); - //lexHandler.endCDATA(); - return elEndStart; - //} - }//}else{//text area - text = text.replace(/&#?\w+;/g, entityReplacer); - domBuilder.characters(text, 0, text.length); - return elEndStart; - //} - - } - } - return elStartEnd + 1; -} -function fixSelfClosed(source, elStartEnd, tagName, closeMap) { - //if(tagName in closeMap){ - var pos = closeMap[tagName]; - if (pos == null) { - ////console.log(tagName) - pos = closeMap[tagName] = source.lastIndexOf('') - } - return pos < elStartEnd; - //} -} -function _copy(source, target) { - for (var n in source) { - target[n] = source[n] - } -} -function parseDCC(source, start, domBuilder, errorHandler) {//sure start with '', start + 4); - //append comment source.substring(4,end)//