|
|
@ -1,4 +1,12 @@ |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* WeeChat protocol handling. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* This object parses messages for the WeeChat protocol. It's |
|
|
|
|
|
|
|
* independent from the communication layer and thus may be used |
|
|
|
|
|
|
|
* with any network mechanism. |
|
|
|
|
|
|
|
*/ |
|
|
|
var WeeChatProtocol = function() { |
|
|
|
var WeeChatProtocol = function() { |
|
|
|
|
|
|
|
// specific parsing for each message type
|
|
|
|
this._types = { |
|
|
|
this._types = { |
|
|
|
'chr': this._getChar, |
|
|
|
'chr': this._getChar, |
|
|
|
'int': this._getInt, |
|
|
|
'int': this._getInt, |
|
|
@ -10,8 +18,13 @@ var WeeChatProtocol = function() { |
|
|
|
'tim': this._getTime, |
|
|
|
'tim': this._getTime, |
|
|
|
'buf': this._getString, |
|
|
|
'buf': this._getString, |
|
|
|
'arr': this._getArray, |
|
|
|
'arr': this._getArray, |
|
|
|
'htb': this._getHashTable |
|
|
|
'htb': this._getHashTable, |
|
|
|
|
|
|
|
'inl': function() { |
|
|
|
|
|
|
|
this._warnUnimplemented('infolist'); |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// string value for some message types
|
|
|
|
this._typesStr = { |
|
|
|
this._typesStr = { |
|
|
|
'chr': this._strDirect, |
|
|
|
'chr': this._strDirect, |
|
|
|
'str': this._strDirect, |
|
|
|
'str': this._strDirect, |
|
|
@ -20,6 +33,13 @@ var WeeChatProtocol = function() { |
|
|
|
'ptr': this._strDirect |
|
|
|
'ptr': this._strDirect |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Unsigned integer array to string. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param uia Unsigned integer array |
|
|
|
|
|
|
|
* @return Decoded string |
|
|
|
|
|
|
|
*/ |
|
|
|
WeeChatProtocol._uia2s = function(uia) { |
|
|
|
WeeChatProtocol._uia2s = function(uia) { |
|
|
|
var str = []; |
|
|
|
var str = []; |
|
|
|
|
|
|
|
|
|
|
@ -29,36 +49,95 @@ WeeChatProtocol._uia2s = function(uia) { |
|
|
|
|
|
|
|
|
|
|
|
return decodeURIComponent(escape(str.join(''))); |
|
|
|
return decodeURIComponent(escape(str.join(''))); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
WeeChatProtocol.prototype = { |
|
|
|
WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Warns that message parsing is not implemented for a |
|
|
|
|
|
|
|
* specific type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param type Message type to display |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
_warnUnimplemented: function(type) { |
|
|
|
|
|
|
|
console.log('Warning: ' + type + ' message parsing is not implemented'); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a 3-character message type token value from current |
|
|
|
|
|
|
|
* set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Type |
|
|
|
|
|
|
|
*/ |
|
|
|
_getType: function() { |
|
|
|
_getType: function() { |
|
|
|
var t = this._getSlice(3); |
|
|
|
var t = this._getSlice(3); |
|
|
|
|
|
|
|
|
|
|
|
return WeeChatProtocol._uia2s(new Uint8Array(t)); |
|
|
|
return WeeChatProtocol._uia2s(new Uint8Array(t)); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Runs the appropriate read routine for the specified message type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param type Message type |
|
|
|
|
|
|
|
* @return Data value |
|
|
|
|
|
|
|
*/ |
|
|
|
_runType: function(type) { |
|
|
|
_runType: function(type) { |
|
|
|
var cb = this._types[type]; |
|
|
|
var cb = this._types[type]; |
|
|
|
var boundCb = cb.bind(this); |
|
|
|
var boundCb = cb.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
return boundCb(); |
|
|
|
return boundCb(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a "number as a string" token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Number as a string |
|
|
|
|
|
|
|
*/ |
|
|
|
_getStrNumber: function() { |
|
|
|
_getStrNumber: function() { |
|
|
|
var len = this._getByte(); |
|
|
|
var len = this._getByte(); |
|
|
|
var str = this._getSlice(len); |
|
|
|
var str = this._getSlice(len); |
|
|
|
|
|
|
|
|
|
|
|
return WeeChatProtocol._uia2s(new Uint8Array(str)); |
|
|
|
return WeeChatProtocol._uia2s(new Uint8Array(str)); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the passed object. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param obj Object |
|
|
|
|
|
|
|
* @return Passed object |
|
|
|
|
|
|
|
*/ |
|
|
|
_strDirect: function(obj) { |
|
|
|
_strDirect: function(obj) { |
|
|
|
return obj; |
|
|
|
return obj; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Calls toString() on the passed object and returns the value. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param obj Object to call toString() on |
|
|
|
|
|
|
|
* @return String value of object |
|
|
|
|
|
|
|
*/ |
|
|
|
_strToString: function(obj) { |
|
|
|
_strToString: function(obj) { |
|
|
|
return obj.toString(); |
|
|
|
return obj.toString(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Gets the string value of an object representing the message |
|
|
|
|
|
|
|
* value for a specified type. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param obj Object for which to get the string value |
|
|
|
|
|
|
|
* @param type Message type |
|
|
|
|
|
|
|
* @return String value of object |
|
|
|
|
|
|
|
*/ |
|
|
|
_objToString: function(obj, type) { |
|
|
|
_objToString: function(obj, type) { |
|
|
|
var cb = this._typesStr[type]; |
|
|
|
var cb = this._typesStr[type]; |
|
|
|
var boundCb = cb.bind(this); |
|
|
|
var boundCb = cb.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
return boundCb(obj); |
|
|
|
return boundCb(obj); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an info token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Info object |
|
|
|
|
|
|
|
*/ |
|
|
|
_getInfo: function() { |
|
|
|
_getInfo: function() { |
|
|
|
var info = {}; |
|
|
|
var info = {}; |
|
|
|
info.key = this._getString(); |
|
|
|
info.key = this._getString(); |
|
|
@ -66,6 +145,12 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return info; |
|
|
|
return info; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an hdata token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Hdata object |
|
|
|
|
|
|
|
*/ |
|
|
|
_getHdata: function() { |
|
|
|
_getHdata: function() { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var paths; |
|
|
|
var paths; |
|
|
@ -95,14 +180,32 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return objs; |
|
|
|
return objs; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a pointer token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Pointer value |
|
|
|
|
|
|
|
*/ |
|
|
|
_getPointer: function() { |
|
|
|
_getPointer: function() { |
|
|
|
return this._getStrNumber(); |
|
|
|
return this._getStrNumber(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a time token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Time value (Date) |
|
|
|
|
|
|
|
*/ |
|
|
|
_getTime: function() { |
|
|
|
_getTime: function() { |
|
|
|
var str = this._getStrNumber(); |
|
|
|
var str = this._getStrNumber(); |
|
|
|
|
|
|
|
|
|
|
|
return new Date(parseInt(str)); |
|
|
|
return new Date(parseInt(str)); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an integer token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Integer value |
|
|
|
|
|
|
|
*/ |
|
|
|
_getInt: function() { |
|
|
|
_getInt: function() { |
|
|
|
var parsedData = new Uint8Array(this._getSlice(4)); |
|
|
|
var parsedData = new Uint8Array(this._getSlice(4)); |
|
|
|
|
|
|
|
|
|
|
@ -111,14 +214,32 @@ WeeChatProtocol.prototype = { |
|
|
|
((parsedData[2] & 0xff) << 8) | |
|
|
|
((parsedData[2] & 0xff) << 8) | |
|
|
|
(parsedData[3] & 0xff); |
|
|
|
(parsedData[3] & 0xff); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a byte from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Byte value (integer) |
|
|
|
|
|
|
|
*/ |
|
|
|
_getByte: function() { |
|
|
|
_getByte: function() { |
|
|
|
var parsedData = new Uint8Array(this._getSlice(1)); |
|
|
|
var parsedData = new Uint8Array(this._getSlice(1)); |
|
|
|
|
|
|
|
|
|
|
|
return parsedData[0]; |
|
|
|
return parsedData[0]; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a character token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Character (string) |
|
|
|
|
|
|
|
*/ |
|
|
|
_getChar: function() { |
|
|
|
_getChar: function() { |
|
|
|
return String.fromCharCode(this._getByte()); |
|
|
|
return String.fromCharCode(this._getByte()); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a string token value from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return String value |
|
|
|
|
|
|
|
*/ |
|
|
|
_getString: function() { |
|
|
|
_getString: function() { |
|
|
|
var l = this._getInt(); |
|
|
|
var l = this._getInt(); |
|
|
|
|
|
|
|
|
|
|
@ -131,6 +252,12 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return ""; |
|
|
|
return ""; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a message header from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Header object |
|
|
|
|
|
|
|
*/ |
|
|
|
_getHeader: function() { |
|
|
|
_getHeader: function() { |
|
|
|
var len = this._getInt(); |
|
|
|
var len = this._getInt(); |
|
|
|
var comp = this._getByte(); |
|
|
|
var comp = this._getByte(); |
|
|
@ -140,9 +267,21 @@ WeeChatProtocol.prototype = { |
|
|
|
compression: comp, |
|
|
|
compression: comp, |
|
|
|
}; |
|
|
|
}; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a message header ID from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Message ID (string) |
|
|
|
|
|
|
|
*/ |
|
|
|
_getId: function() { |
|
|
|
_getId: function() { |
|
|
|
return this._getString(); |
|
|
|
return this._getString(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an arbitrary object token from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Object value |
|
|
|
|
|
|
|
*/ |
|
|
|
_getObject: function() { |
|
|
|
_getObject: function() { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var type = this._getType(); |
|
|
|
var type = this._getType(); |
|
|
@ -154,6 +293,12 @@ WeeChatProtocol.prototype = { |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an hash table token from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Hash table |
|
|
|
|
|
|
|
*/ |
|
|
|
_getHashTable: function() { |
|
|
|
_getHashTable: function() { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var typeKeys, typeValues, count; |
|
|
|
var typeKeys, typeValues, count; |
|
|
@ -172,6 +317,12 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return dict; |
|
|
|
return dict; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads an array token from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return Array |
|
|
|
|
|
|
|
*/ |
|
|
|
_getArray: function() { |
|
|
|
_getArray: function() { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
var type; |
|
|
|
var type; |
|
|
@ -188,6 +339,13 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return values; |
|
|
|
return values; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Reads a specified number of bytes from current set data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param length Number of bytes to read |
|
|
|
|
|
|
|
* @return Sliced array |
|
|
|
|
|
|
|
*/ |
|
|
|
_getSlice: function(length) { |
|
|
|
_getSlice: function(length) { |
|
|
|
var slice = this._data.slice(this._dataAt, this._dataAt + length); |
|
|
|
var slice = this._data.slice(this._dataAt, this._dataAt + length); |
|
|
|
|
|
|
|
|
|
|
@ -195,9 +353,22 @@ WeeChatProtocol.prototype = { |
|
|
|
|
|
|
|
|
|
|
|
return slice; |
|
|
|
return slice; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Sets the current data. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param data Current data |
|
|
|
|
|
|
|
*/ |
|
|
|
_setData: function (data) { |
|
|
|
_setData: function (data) { |
|
|
|
this._data = data; |
|
|
|
this._data = data; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Parses a WeeChat message. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param data Message data (ArrayBuffer) |
|
|
|
|
|
|
|
* @return Message value |
|
|
|
|
|
|
|
*/ |
|
|
|
parse: function(data) { |
|
|
|
parse: function(data) { |
|
|
|
var self = this; |
|
|
|
var self = this; |
|
|
|
|
|
|
|
|
|
|
|