Light12306/Web12306/js/platform/messageCoder.js
2015-07-31 23:11:30 +08:00

209 lines
4.6 KiB
JavaScript

define(function (require, exports, module) {
var sessMgr = require("../account/sessionMgr.js");
var keystr = "iFishMessagePack";
var step = Math.pow(2, 32);
exports.encode = function (item) {
if (!item)
return [];
if (!item.fromUser)
item.fromUser = {
username: sessMgr.current.username,
realname: sessMgr.current.dispname
};
var buffer = [];
var keyidx = Math.floor(Math.random() * keystr.length);
var key = keystr.charCodeAt(keyidx);
//helper
var putInt16 = function (value) {
value = value || 0;
for (var i = 0; i < 2; i++) {
buffer.push(value - (value >> 8 << 8));
value >>= 8;
}
};
var putInt32 = function (value) {
value = value || 0;
for (var i = 0; i < 4; i++) {
buffer.push(value - (value >> 8 << 8));
value >>= 8;
}
};
var putInt64 = function (value) {
value = value || 0;
var int1 = value % step;
var int2 = Math.floor((value - int1) / step);
putInt32(int1);
putInt32(int2);
};
var putBool = function (value) {
value = value || false;
buffer.push(value ? 1 : 0);
};
var putString = function (str, unicode, writeLengthPrefix) {
str = str || "";
if (typeof writeLengthPrefix === 'undefined')
writeLengthPrefix = true;
if (writeLengthPrefix) {
putInt32((unicode ? 2 : 1) * str.length);
}
for (var i = 0; i < str.length; i++) {
var code = str.charCodeAt(i);
if (unicode)
putInt16(code);
else buffer.push(code);
}
};
//1.
buffer.push(keyidx);
//2. keystr
putString(keystr, false, false);
//3.action
putInt64(item.id);
putString(item.action, false);
//4.success
putBool(item.success);
//5.time
putInt64(item.time.getTime());
//6.system message
putBool(item.systemMessage);
//7.8.
putInt32(item.sysMsgType);
putInt32(item.userMsgType);
//9.content
putString(item.content, true);
//10.color
putString(item.color, false);
//11.images
putInt32(item.images ? item.images.length || 0 : 0);
if (item.images) {
item.images.forEach(function (image) {
putString(image, false);
});
}
//12.from user
putString(item.fromUser.username || "", false);
putString(item.fromUser.realname || "", true);
//13.images
putInt32(item.toUsers ? item.toUsers.length || 0 : 0);
if (item.toUsers) {
item.toUsers.forEach(function (user) {
putString(user.username, false);
putString(user.realname, true);
});
}
//encrypt
for (var j = 1; j < buffer.length; j++) {
key = buffer[j] ^= key;
}
return buffer;
};
exports.decode = function (data) {
var keyIndex = data[0];
var key = keystr.charCodeAt(keyIndex);
//decrypt
for (var i = 1; i < data.length; i++) {
var bit = data[i];
data[i] = bit ^ key;
key = bit;
}
var pos = 1;
//helper
var readInt16 = function () {
var b1 = data[pos++];
var b2 = data[pos++];
return b1 | b2 << 8;
};
var readInt32 = function () {
var b1 = data[pos++];
var b2 = data[pos++];
var b3 = data[pos++];
var b4 = data[pos++];
return b1 + b2 * 256 + b3 * Math.pow(2, 16) | b4 * Math.pow(2, 24);
};
var readInt64 = function () {
var int1 = readInt32();
var int2 = readInt32();
return int2 * step + int1;
};
var readString = function (unicode, length) {
if (typeof (unicode) === 'undefined') {
unicode = false;
}
if (typeof (length) === 'undefined') {
length = readInt32();
}
var buffer = [];
var textLength = length / (unicode ? 2 : 1);
for (var j = 0; j < textLength; j++) {
if (unicode) {
buffer.push(String.fromCharCode(readInt16()));
} else {
buffer.push(String.fromCharCode(data[pos++]));
}
}
return buffer.join("");
};
var readMessageUser = function () {
return {
username: readString(false),
realname: readString(true)
};
};
//check package header
if (readString(false, keystr.length) !== keystr)
return null;
var item = {};
item.id = readInt64();
item.action = readString(false);
item.success = data[pos++] === 1;
item.time = new Date(readInt64());
item.systemMessage = data[pos++] === 1;
item.sysMsgType = readInt32();
item.userMsgType = readInt32();
item.content = readString(true);
item.color = readString(false);
var imgCount = readInt32();
if (imgCount > 0) {
item.images = [];
for (var j = 0; j < imgCount; j++) {
item.images.push(readString(false));
}
}
item.fromUser = readMessageUser();
var toUserCount = readInt32();
if (toUserCount > 0) {
item.toUsers = [];
for (var j = 0; j < toUserCount; j++) {
item.toUsers.push(readMessageUser());
}
}
return item;
};
});