Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. // imported from https://github.com/socketio/engine.io-parser/tree/2.2.x
  2. /**
  3. * Module dependencies.
  4. */
  5. var utf8 = require('./utf8');
  6. /**
  7. * Current protocol version.
  8. */
  9. exports.protocol = 3;
  10. const hasBinary = (packets) => {
  11. for (const packet of packets) {
  12. if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
  13. return true;
  14. }
  15. }
  16. return false;
  17. }
  18. /**
  19. * Packet types.
  20. */
  21. var packets = exports.packets = {
  22. open: 0 // non-ws
  23. , close: 1 // non-ws
  24. , ping: 2
  25. , pong: 3
  26. , message: 4
  27. , upgrade: 5
  28. , noop: 6
  29. };
  30. var packetslist = Object.keys(packets);
  31. /**
  32. * Premade error packet.
  33. */
  34. var err = { type: 'error', data: 'parser error' };
  35. const EMPTY_BUFFER = Buffer.concat([]);
  36. /**
  37. * Encodes a packet.
  38. *
  39. * <packet type id> [ <data> ]
  40. *
  41. * Example:
  42. *
  43. * 5hello world
  44. * 3
  45. * 4
  46. *
  47. * Binary is encoded in an identical principle
  48. *
  49. * @api private
  50. */
  51. exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
  52. if (typeof supportsBinary === 'function') {
  53. callback = supportsBinary;
  54. supportsBinary = null;
  55. }
  56. if (typeof utf8encode === 'function') {
  57. callback = utf8encode;
  58. utf8encode = null;
  59. }
  60. if (Buffer.isBuffer(packet.data)) {
  61. return encodeBuffer(packet, supportsBinary, callback);
  62. } else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) {
  63. return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback);
  64. }
  65. // Sending data as a utf-8 string
  66. var encoded = packets[packet.type];
  67. // data fragment is optional
  68. if (undefined !== packet.data) {
  69. encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
  70. }
  71. return callback('' + encoded);
  72. };
  73. /**
  74. * Encode Buffer data
  75. */
  76. function encodeBuffer(packet, supportsBinary, callback) {
  77. if (!supportsBinary) {
  78. return exports.encodeBase64Packet(packet, callback);
  79. }
  80. var data = packet.data;
  81. var typeBuffer = Buffer.allocUnsafe(1);
  82. typeBuffer[0] = packets[packet.type];
  83. return callback(Buffer.concat([typeBuffer, data]));
  84. }
  85. /**
  86. * Encodes a packet with binary data in a base64 string
  87. *
  88. * @param {Object} packet, has `type` and `data`
  89. * @return {String} base64 encoded message
  90. */
  91. exports.encodeBase64Packet = function(packet, callback){
  92. var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data);
  93. var message = 'b' + packets[packet.type];
  94. message += data.toString('base64');
  95. return callback(message);
  96. };
  97. /**
  98. * Decodes a packet. Data also available as an ArrayBuffer if requested.
  99. *
  100. * @return {Object} with `type` and `data` (if any)
  101. * @api private
  102. */
  103. exports.decodePacket = function (data, binaryType, utf8decode) {
  104. if (data === undefined) {
  105. return err;
  106. }
  107. var type;
  108. // String data
  109. if (typeof data === 'string') {
  110. type = data.charAt(0);
  111. if (type === 'b') {
  112. return exports.decodeBase64Packet(data.substr(1), binaryType);
  113. }
  114. if (utf8decode) {
  115. data = tryDecode(data);
  116. if (data === false) {
  117. return err;
  118. }
  119. }
  120. if (Number(type) != type || !packetslist[type]) {
  121. return err;
  122. }
  123. if (data.length > 1) {
  124. return { type: packetslist[type], data: data.substring(1) };
  125. } else {
  126. return { type: packetslist[type] };
  127. }
  128. }
  129. // Binary data
  130. if (binaryType === 'arraybuffer') {
  131. // wrap Buffer/ArrayBuffer data into an Uint8Array
  132. var intArray = new Uint8Array(data);
  133. type = intArray[0];
  134. return { type: packetslist[type], data: intArray.buffer.slice(1) };
  135. }
  136. if (data instanceof ArrayBuffer) {
  137. data = arrayBufferToBuffer(data);
  138. }
  139. type = data[0];
  140. return { type: packetslist[type], data: data.slice(1) };
  141. };
  142. function tryDecode(data) {
  143. try {
  144. data = utf8.decode(data, { strict: false });
  145. } catch (e) {
  146. return false;
  147. }
  148. return data;
  149. }
  150. /**
  151. * Decodes a packet encoded in a base64 string.
  152. *
  153. * @param {String} base64 encoded message
  154. * @return {Object} with `type` and `data` (if any)
  155. */
  156. exports.decodeBase64Packet = function(msg, binaryType) {
  157. var type = packetslist[msg.charAt(0)];
  158. var data = Buffer.from(msg.substr(1), 'base64');
  159. if (binaryType === 'arraybuffer') {
  160. var abv = new Uint8Array(data.length);
  161. for (var i = 0; i < abv.length; i++){
  162. abv[i] = data[i];
  163. }
  164. data = abv.buffer;
  165. }
  166. return { type: type, data: data };
  167. };
  168. /**
  169. * Encodes multiple messages (payload).
  170. *
  171. * <length>:data
  172. *
  173. * Example:
  174. *
  175. * 11:hello world2:hi
  176. *
  177. * If any contents are binary, they will be encoded as base64 strings. Base64
  178. * encoded strings are marked with a b before the length specifier
  179. *
  180. * @param {Array} packets
  181. * @api private
  182. */
  183. exports.encodePayload = function (packets, supportsBinary, callback) {
  184. if (typeof supportsBinary === 'function') {
  185. callback = supportsBinary;
  186. supportsBinary = null;
  187. }
  188. if (supportsBinary && hasBinary(packets)) {
  189. return exports.encodePayloadAsBinary(packets, callback);
  190. }
  191. if (!packets.length) {
  192. return callback('0:');
  193. }
  194. function encodeOne(packet, doneCallback) {
  195. exports.encodePacket(packet, supportsBinary, false, function(message) {
  196. doneCallback(null, setLengthHeader(message));
  197. });
  198. }
  199. map(packets, encodeOne, function(err, results) {
  200. return callback(results.join(''));
  201. });
  202. };
  203. function setLengthHeader(message) {
  204. return message.length + ':' + message;
  205. }
  206. /**
  207. * Async array map using after
  208. */
  209. function map(ary, each, done) {
  210. const results = new Array(ary.length);
  211. let count = 0;
  212. for (let i = 0; i < ary.length; i++) {
  213. each(ary[i], (error, msg) => {
  214. results[i] = msg;
  215. if (++count === ary.length) {
  216. done(null, results);
  217. }
  218. });
  219. }
  220. }
  221. /*
  222. * Decodes data when a payload is maybe expected. Possible binary contents are
  223. * decoded from their base64 representation
  224. *
  225. * @param {String} data, callback method
  226. * @api public
  227. */
  228. exports.decodePayload = function (data, binaryType, callback) {
  229. if (typeof data !== 'string') {
  230. return exports.decodePayloadAsBinary(data, binaryType, callback);
  231. }
  232. if (typeof binaryType === 'function') {
  233. callback = binaryType;
  234. binaryType = null;
  235. }
  236. if (data === '') {
  237. // parser error - ignoring payload
  238. return callback(err, 0, 1);
  239. }
  240. var length = '', n, msg, packet;
  241. for (var i = 0, l = data.length; i < l; i++) {
  242. var chr = data.charAt(i);
  243. if (chr !== ':') {
  244. length += chr;
  245. continue;
  246. }
  247. if (length === '' || (length != (n = Number(length)))) {
  248. // parser error - ignoring payload
  249. return callback(err, 0, 1);
  250. }
  251. msg = data.substr(i + 1, n);
  252. if (length != msg.length) {
  253. // parser error - ignoring payload
  254. return callback(err, 0, 1);
  255. }
  256. if (msg.length) {
  257. packet = exports.decodePacket(msg, binaryType, false);
  258. if (err.type === packet.type && err.data === packet.data) {
  259. // parser error in individual packet - ignoring payload
  260. return callback(err, 0, 1);
  261. }
  262. var more = callback(packet, i + n, l);
  263. if (false === more) return;
  264. }
  265. // advance cursor
  266. i += n;
  267. length = '';
  268. }
  269. if (length !== '') {
  270. // parser error - ignoring payload
  271. return callback(err, 0, 1);
  272. }
  273. };
  274. /**
  275. *
  276. * Converts a buffer to a utf8.js encoded string
  277. *
  278. * @api private
  279. */
  280. function bufferToString(buffer) {
  281. var str = '';
  282. for (var i = 0, l = buffer.length; i < l; i++) {
  283. str += String.fromCharCode(buffer[i]);
  284. }
  285. return str;
  286. }
  287. /**
  288. *
  289. * Converts a utf8.js encoded string to a buffer
  290. *
  291. * @api private
  292. */
  293. function stringToBuffer(string) {
  294. var buf = Buffer.allocUnsafe(string.length);
  295. for (var i = 0, l = string.length; i < l; i++) {
  296. buf.writeUInt8(string.charCodeAt(i), i);
  297. }
  298. return buf;
  299. }
  300. /**
  301. *
  302. * Converts an ArrayBuffer to a Buffer
  303. *
  304. * @api private
  305. */
  306. function arrayBufferToBuffer(data) {
  307. // data is either an ArrayBuffer or ArrayBufferView.
  308. var length = data.byteLength || data.length;
  309. var offset = data.byteOffset || 0;
  310. return Buffer.from(data.buffer || data, offset, length);
  311. }
  312. /**
  313. * Encodes multiple messages (payload) as binary.
  314. *
  315. * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
  316. * 255><data>
  317. *
  318. * Example:
  319. * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
  320. *
  321. * @param {Array} packets
  322. * @return {Buffer} encoded payload
  323. * @api private
  324. */
  325. exports.encodePayloadAsBinary = function (packets, callback) {
  326. if (!packets.length) {
  327. return callback(EMPTY_BUFFER);
  328. }
  329. map(packets, encodeOneBinaryPacket, function(err, results) {
  330. return callback(Buffer.concat(results));
  331. });
  332. };
  333. function encodeOneBinaryPacket(p, doneCallback) {
  334. function onBinaryPacketEncode(packet) {
  335. var encodingLength = '' + packet.length;
  336. var sizeBuffer;
  337. if (typeof packet === 'string') {
  338. sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
  339. sizeBuffer[0] = 0; // is a string (not true binary = 0)
  340. for (var i = 0; i < encodingLength.length; i++) {
  341. sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
  342. }
  343. sizeBuffer[sizeBuffer.length - 1] = 255;
  344. return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
  345. }
  346. sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
  347. sizeBuffer[0] = 1; // is binary (true binary = 1)
  348. for (var i = 0; i < encodingLength.length; i++) {
  349. sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
  350. }
  351. sizeBuffer[sizeBuffer.length - 1] = 255;
  352. doneCallback(null, Buffer.concat([sizeBuffer, packet]));
  353. }
  354. exports.encodePacket(p, true, true, onBinaryPacketEncode);
  355. }
  356. /*
  357. * Decodes data when a payload is maybe expected. Strings are decoded by
  358. * interpreting each byte as a key code for entries marked to start with 0. See
  359. * description of encodePayloadAsBinary
  360. * @param {Buffer} data, callback method
  361. * @api public
  362. */
  363. exports.decodePayloadAsBinary = function (data, binaryType, callback) {
  364. if (typeof binaryType === 'function') {
  365. callback = binaryType;
  366. binaryType = null;
  367. }
  368. var bufferTail = data;
  369. var buffers = [];
  370. var i;
  371. while (bufferTail.length > 0) {
  372. var strLen = '';
  373. var isString = bufferTail[0] === 0;
  374. for (i = 1; ; i++) {
  375. if (bufferTail[i] === 255) break;
  376. // 310 = char length of Number.MAX_VALUE
  377. if (strLen.length > 310) {
  378. return callback(err, 0, 1);
  379. }
  380. strLen += '' + bufferTail[i];
  381. }
  382. bufferTail = bufferTail.slice(strLen.length + 1);
  383. var msgLength = parseInt(strLen, 10);
  384. var msg = bufferTail.slice(1, msgLength + 1);
  385. if (isString) msg = bufferToString(msg);
  386. buffers.push(msg);
  387. bufferTail = bufferTail.slice(msgLength + 1);
  388. }
  389. var total = buffers.length;
  390. for (i = 0; i < total; i++) {
  391. var buffer = buffers[i];
  392. callback(exports.decodePacket(buffer, binaryType, true), i, total);
  393. }
  394. };