Advertisement
Guest User

Untitled

a guest
Aug 8th, 2018
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.84 KB | None | 0 0
  1. var app = require("express")();
  2. var http = require("http").Server(app);
  3. var request = require("request");
  4. var io = require("socket.io")(http);
  5. var mySQL = require("mysql");
  6. var sql = mySQL.createConnection({
  7. host: "localhost",
  8. user: "us",
  9. password: "pass",
  10. database: "db",
  11. dateStrings: true
  12. });
  13. io.origins("http://orchidea.margonem.pl:*");
  14. http.listen(8080, () => { console.log("Started listening on port 8080"); });
  15.  
  16. // VARIABLES AND FUNCTIONS
  17. var is = {
  18. set: a => typeof a !== "undefined" && a != null,
  19. num: a => typeof a === "number",
  20. str: a => typeof a === "string",
  21. bool: a => typeof a === "boolean",
  22. fun: a => typeof a === "function",
  23. arr: a => a instanceof Array,
  24. obj: a => typeof a === "object" && typeof a !== "function" && !(a instanceof Array),
  25. in: (a, min, max) => min <= a && max >= a,
  26. inArr: function(a, arr, bool) {
  27. for (let i = 0; i < arr.length; i++) if (arr[i] === a) return is.set(bool) ? !0 : i;
  28. return is.set(bool) ? !1 : -1;
  29. },
  30. inArrObj: function(a, arr, prop, bool) {
  31. for (let i = 0; i < arr.length; i++)
  32. if (!arr[i].hasOwnProperty(prop)) return is.set(bool) ? !1 : -1;
  33. else if (arr[i][prop] === a) return is.set(bool) ? !0 : i;
  34. return is.set(bool) ? !1 : -1;
  35. },
  36. correct: function(a, step, user) {
  37. for (let i in a) switch(i) {
  38. case "type":
  39. if (!is.num(a[i])) {
  40. _.log(step + ": " + i + " is not a number", user);
  41. return false;
  42. } else if (!is.in(a[i], 0, 5)) {
  43. _.log(step + ": " + i + " is not in a range", user);
  44. return false;
  45. }
  46. break;
  47. case "id":
  48. if (!is.num(a[i])) {
  49. _.log(step + ": " + i + " is not a number", user);
  50. return false;
  51. } else if (!is.in(a[i], 0, 999999999)) {
  52. _.log(step + ": " + i + " is not in a range", user);
  53. return false;
  54. } else if (is.inArr(a[i], _.arrs.banned, true)) {
  55. _.log(step + ": " + i + " is banned", user);
  56. return false;
  57. }
  58. break;
  59. case "nick":
  60. if (!is.str(a[i])) {
  61. _.log(step + ": " + i + " is not a string", user);
  62. return false;
  63. }
  64. break;
  65. case "c":
  66. if (a[i] != null && !is.str(a[i])) {
  67. _.log(step + ": " + i + " is neither a string nor a null", user);
  68. return false;
  69. }
  70. break;
  71. case "addon":
  72. if (!is.bool(a[i])) {
  73. _.log(step + ": " + i + " is not a boolean", user);
  74. return false;
  75. } else if (!a[i]) {
  76. _.log(step + ": " + i + " is false so user blocked addon", user);
  77. return false;
  78. }
  79. break;
  80. case "guest":
  81. if (!is.bool(a[i])) {
  82. _.log(step + ": " + i + " is not a boolean", user);
  83. return false;
  84. }
  85. break;
  86. case "settings":
  87. if (!is.obj(a[i])) {
  88. _.log(step + ": " + i + " is not an object", user);
  89. return false;
  90. }
  91. break;
  92. case "getAll":
  93. if (!is.bool(a[i])) {
  94. _.log(step + ": " + i + " is not an object", user);
  95. return false;
  96. }
  97. break;
  98. case "message":
  99. if (!is.str(a[i])) {
  100. _.log(step + ": " + i + " is not a string", user);
  101. return false;
  102. }
  103. break;
  104. case "time":
  105. if (!is.str(a[i])) {
  106. _.log(step + ": " + i + " is not a strnig", user);
  107. return false;
  108. }
  109. break;
  110. default:
  111. _.log(step + ": found unknown property " + i, user);
  112. return false;
  113. }
  114. return true;
  115. },
  116. online: function(a, inLogged) {
  117. if (is.set(inLogged)) for (let i = 0; i < _.arrs.logged.length; i++) { if (_.arrs.logged[i].sid === a.sid && _.arrs.logged[i].mid === a.mid && _.arrs.logged[i].ip === a.ip) return true; }
  118. else for (let i = 0; i < _.arrs.onlineA.length; i++) if (_.arrs.onlineA[i].charNick === a) return true;
  119. return false;
  120. }
  121. };
  122.  
  123. var get = {
  124. info: {
  125. decoded: s => {
  126. if (s.search(/[^;0-9]/g) > -1) return null;
  127. s = s.split(";");
  128. if (!is.in(s.length, 8, 20)) return null;
  129. else {
  130. var c = +s[0], t = "", d = a => a.split("").reverse().map(a => +a - 1 > -1 ? +a - 1 : 9).join("");
  131. for (let i = 1; i < s.length; i++)
  132. if (i < 3) s[i] = +d(s[i]) - c;
  133. else if (i == 3) continue;
  134. else t += s[i] = String.fromCharCode(+d(s[i]) - c);
  135. s = s.slice(0, 4); s.push(t);
  136. return s;
  137. }
  138. },
  139. encoded: (id, time, random, nick) => {
  140. var r = +get.str(3, true), s = "", c = a => a.toString().split("").map(a => (+a + 1) % 10).reverse().join("");
  141. if (r === 0) r = 23;
  142. id += r; time += r;
  143. nick = nick.split("").map(a => c(a.charCodeAt() + r));
  144. s = r + ";" + c(id) + ";" + c(time) + ";" + random + ";" + nick.join(";");
  145. return s;
  146. },
  147. cookie: id => {
  148. if (id < 1) return id == 0 ? 1 : -1;
  149. var t = 31 - Math.floor(Math.log(id) * Math.LOG2E);
  150. return id + "_o" + (~(id << t) >>> t);
  151. }
  152. },
  153. time: () => Date.now(),
  154. ip: socket => socket.handshake.address.replace(/^.{7}/g, ""),
  155. str: (len, onlyNumbers) => {
  156. var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", s = "";
  157. for (let i = 0; i < len; i++) s += chars[Math.floor(Math.random() * (is.set(onlyNumbers) ? 9 : chars.length))];
  158. return s;
  159. },
  160. logged: a => {
  161. for (let i = 0; i < _.arrs.logged.length; i++) if (_.arrs.logged[i].sid === a.sid && _.arrs.logged[i].mid === a.mid) return _.arrs.logged[i].nick;
  162. return null;
  163. },
  164. online: () => {
  165. request({
  166. url: "https://www.margonem.pl",
  167. method: "POST",
  168. qs: {task: "stats"}
  169. }, (a, b, c) => {
  170. if (a != null) _.log("GET ONLINE: could not reach stats");
  171. else {
  172. let t = /<h2>Świat Orchidea(.|\n)*?<\/p>/g.exec(c);
  173. if (!is.set(t)) _.log("GET ONLINE: orchidea world not found in stats");
  174. else {
  175. t = t[0].match(/<p.+>/g)[0].replace(/<.*?>/g, "");
  176. let o = t.split(",").map(x => x.replace(/^ +| +$/g, ""));
  177. _.arrs.onlineNA = o.filter(x => !is.online(x));
  178. io.emit("online", _.countOnline());
  179. }
  180. }
  181. });
  182. }
  183. };
  184.  
  185. var _ = {
  186. arrs: {
  187. banned: [5256570, 4521505],
  188. themes: [
  189. {
  190. css: "themes/wing/tWing.css",
  191. js: "themes/wing/tWing.min.js"
  192. },
  193. {
  194. css: "themes/second/tSecond.css",
  195. js: "themes/second/tSecond.js"
  196. },
  197. {
  198. css: "themes/brown/tBrown.css",
  199. js: "themes/brown/tBrown.js"
  200. }
  201. ],
  202. // data format: {mid::number, randString::string}
  203. logging: [],
  204. // data format: {sid::string, mid::number, nick::string, charNick::string, ip::string, guest::boolean}
  205. logged: [],
  206. // data format: {sid::string, charNick::string}
  207. onlineA: [],
  208. // data format: charNick::string
  209. onlineNA: [],
  210. // data format: {mid::number, nick::string, colour::string}
  211. colours: []
  212. },
  213. escapeHTML: str => {
  214. let c = {
  215. "<": "&lt;",
  216. ">": "&gt;",
  217. "'": "&quot;",
  218. '"': "&#39;",
  219. "`": "&#x60;",
  220. "=": "&#x3D;",
  221. "&": "&amp;",
  222. "/": "&#x2F;"
  223. };
  224. return str.replace(/[<>'"`=&\/]/g, (b) => c[b]);
  225. },
  226. countOnline: retArr => {
  227. var t = [[], []];
  228. for (let i = 0; i < _.arrs.onlineA.length; i++) t[0].push(_.arrs.onlineA[i].charNick);
  229. for (let i = 0; i < _.arrs.onlineNA.length; i++) t[1].push(_.arrs.onlineNA[i]);
  230. return is.set(retArr) ? {type: 1, n : t[0].length + t[1].length, online: t} : {type: 0, n: t[0].length + t[1].length, online: null};
  231. },
  232. log: (a, user) => {
  233. var t = is.set(user);
  234. console.log(a + (t ? ". User " + user.nick + " with acc id " + user.id + " and IP " + get.ip(user.s) : ""));
  235. if (t) user.s.disconnect(true);
  236. },
  237. db: (q, f) => {
  238. sql.query(q, (e, r) => {
  239. if (e) console.log("DB: error [" + e + "] while quering with query " + q);
  240. else if (is.set(f)) f(r);
  241. });
  242. }
  243. };
  244.  
  245. // START
  246. _.db("SELECT * FROM `colours`", a => {
  247. for (let i = 0; i < a.length; i++) _.arrs.colours.push({mid: a[i].mID, nick: a[i].nick, colour: a[i].colour});
  248. });
  249. get.online();
  250. setInterval(get.online, 120000);
  251.  
  252. io.on("connection", s => {
  253.  
  254. // DISCONNECT
  255. s.on("disconnect", () => {
  256. _.arrs.logging = _.arrs.logging.filter(a => a.sid !== s.id);
  257. _.arrs.logged = _.arrs.logged.filter(a => a.sid !== s.id);
  258. _.arrs.onlineA = _.arrs.onlineA.filter(a => a.sid !== s.id);
  259. s.broadcast.emit("online", _.countOnline());
  260. });
  261.  
  262. // LOGIN
  263. // data format: {type::number, id::number, nick::string, guest::boolean, addon::boolean, c::nullORstring}
  264. // output format: {type::number, error::booleanORstring, c::nullORstring, rs::nullORstring, p::nullORstring}
  265. s.on("login", (m, f) => {
  266. var ip = get.ip(s), guest = null, user = {
  267. s: s,
  268. id: m.id,
  269. nick: m.nick
  270. };
  271.  
  272. if (is.correct(m, "LOGIN", user)) {
  273.  
  274. // if user is guest check id
  275. if (m.guest) request({
  276. url: "https://www.margonem.pl",
  277. method: "POST",
  278. qs: {task: "profile", id: m.id}
  279. }, (a, b, c) => {
  280. if (is.set(a)) _.log("LOGIN: could not reach profile while checking guest", user);
  281. else {
  282. let t = /<a href=\?task=profile&id=[0-9]+>/g.exec(c);
  283. if (!is.set(t)) _.log("LOGIN: could not check guest", user);
  284. else {
  285. guest = +t[0].match(/[0-9]+/g)[0];
  286. let r = get.str(20);
  287. _.arrs.logging.push({id: guest, randString: r});
  288. _.log("New logging attempt from " + m.nick + "'s guest with acc id " + guest + " and IP " + ip);
  289. f({
  290. type: 2,
  291. error: !1,
  292. id: guest,
  293. c: get.info.cookie(guest),
  294. rs: null,
  295. p: null
  296. });
  297. }
  298. }
  299. });
  300. else switch(m.type) {
  301.  
  302. // cookie exists or first login step (generate string)
  303. case 0:
  304. let _f = e => {
  305. _.db("DELETE FROM `logged` WHERE `mID` = " + mySQL.escape(m.id));
  306. var n = is.inArrObj(m.id, _.arrs.logging, "id"), r = n > -1 ? _.arrs.logging[n].randString : get.str(20);
  307. if (n == -1) {
  308. _.arrs.logging.push({id: m.id, randString: r});
  309. _.log("New logging attempt from " + m.nick + " with acc id " + m.id + " and IP " + ip);
  310. }
  311. f({
  312. type: 0,
  313. error: is.set(e) ? e : !1,
  314. id: m.id,
  315. c: get.info.cookie(m.id),
  316. rs: r,
  317. p: null
  318. });
  319. };
  320.  
  321. // cookie is set
  322. if (is.set(m.c)) {
  323. let t = get.info.decoded(m.c);
  324.  
  325. // check cookie data
  326. if (!is.set(t)) {
  327. _.log("LOGIN 0: user " + m.nick + " with id " + m.id + " has incorrect data");
  328. _f("Twoje dane są niepoprawne – musisz zalogować się ponownie.");
  329. } else if (!is.in(get.time() - t[2], 0, 259200000)) {
  330. _.log("LOGIN 0: user " + m.nick + " with id " + m.id + " has too old data");
  331. _f("Twoje dane były przestarzałe – musisz zalogować się ponownie.");
  332. } else _.db(
  333. "SELECT `mID`, `IP`, `nick`, `last_date`, `randString` FROM `logged` WHERE `mID` = " + mySQL.escape(t[1]),
  334. a => {
  335. if (a.length < 1) {
  336. _.log("LOGIN 0: user " + m.nick + " with id " + m.id + " was not found in database");
  337. _f("Twoje dane nie zostały odnalezione w bazie danych – musisz zalogować się ponownie.");
  338. } else {
  339. a = a[0];
  340. if (t[1] !== a.mID || t[3] !== a.randString || t[4] !== a.nick || ip !== a.IP) {
  341. _.log("LOGIN 0: user " + m.nick + " with id " + m.id + " has cookie data which differs from database");
  342. _f("Twoje dane są niepoprawne – musisz zalogować się ponownie.");
  343. } else {
  344. let _t = get.time(), r = get.info.encoded(t[1], _t, t[3], t[4]);
  345. _.arrs.logging = _.arrs.logging.filter(a => a.id !== m.id);
  346. _.arrs.logged.push({sid: s.id, mid: t[1], nick: t[4], charNick: m.nick, ip: ip});
  347. _.arrs.onlineA.push({sid: s.id, charNick: m.nick});
  348. _.arrs.onlineNA = _.arrs.onlineNA.filter(a => a !== m.nick);
  349. _.log("New connection from IP " + ip + " with profile nick " + t[4] + ", game nick " + m.nick + " and ID " + t[1] + ".");
  350. s.broadcast.emit("online", _.countOnline());
  351. _.db("UPDATE `logged` SET `last_date` = " + _t + " WHERE `mID` = " + mySQL.escape(t[1]));
  352. f({
  353. type: 1,
  354. error: !0,
  355. id: t[1],
  356. c: get.info.cookie(t[1]),
  357. rs: r,
  358. p: "http://dev.d4nte.pl/orchidea/"
  359. });
  360. }
  361. }
  362. }
  363. );
  364. } else _f();
  365. break;
  366.  
  367. // second login step (check profile for string)
  368. case 1:
  369. request({
  370. url: "https://www.margonem.pl",
  371. method: "POST",
  372. qs: {task: "profile", id: m.id}
  373. }, (a, b, c) => {
  374. if (is.set(a)) _.log("LOGIN 1: could not load user profile", user);
  375. else {
  376. let n = is.inArrObj(m.id, _.arrs.logging, "id");
  377. if (n == -1) {
  378. _.log("LOGIN 1: user " + m.id + " not found in logging array");
  379. f({
  380. type: 0,
  381. error: "Informacja o twoich danych nie została odnaleziona. Odśwież stronę i spróbuj ponownie.",
  382. id: m.id,
  383. c: get.info.cookie(m.id),
  384. rs: null,
  385. p: null
  386. });
  387. } else {
  388. let t = /id="nick" tip="([a-z]| |[ąęóćśźżńł]|-)+"/ig.exec(c), str = new RegExp(_.arrs.logging[n].randString, "g").exec(c);
  389. if (!is.set(t)) {
  390. _.log("LOGIN 1: could not check user " + m.id + " profile nick");
  391. f({
  392. type: 0,
  393. error: "Wystąpił błąd przy pobieraniu twoich danych z profilu. Spróbuj ponownie później, bądź zgłoś ten błąd autorowi dodatku.",
  394. id: m.id,
  395. c: get.info.cookie(m.id),
  396. rs: null,
  397. p: null
  398. });
  399. } else if (!is.set(str)) f({
  400. type: 0,
  401. error: "Na twoim profilu nie znajduje się podany ciąg znaków, bądź jest on niepoprawny.",
  402. id: m.id,
  403. c: get.info.cookie(m.id),
  404. rs: null,
  405. p: null
  406. });
  407. else {
  408. let nick = t[0].replace(/id="nick" tip=|"/g, ""), _t = get.time(), r = get.str(15, !0), c = get.info.encoded(m.id, _t, r, nick);
  409. _.arrs.logging = _.arrs.logging.filter(a => a.id !== m.id);
  410. _.arrs.logged.push({sid: s.id, mid: m.id, nick: nick, charNick: m.nick, ip: ip});
  411. _.arrs.onlineA.push({sid: s.id, charNick: m.nick});
  412. _.arrs.onlineNA = _.arrs.onlineNA.filter(a => a !== m.nick);
  413. _.log("New connection from IP " + ip + " with profile nick " + nick + ", game nick " + m.nick + " and ID " + m.id + ".");
  414. s.broadcast.emit("online", JSON.stringify(_.countOnline(!0)));
  415. _.db(
  416. "INSERT INTO `logged` (`mID`, `IP`, `nick`, `last_date`, `randString`) VALUES (" +
  417. mySQL.escape(m.id) + ", '" + ip + "', '" + nick + "', " + _t + ", '" + r + "')"
  418. );
  419. f({
  420. type: 1,
  421. error: !1,
  422. id: m.id,
  423. c: get.info.cookie(m.id),
  424. rs: c,
  425. p: "http://dev.d4nte.pl/orchidea/"
  426. });
  427. }
  428. }
  429. }
  430. });
  431. break;
  432. default:
  433. _.log("LOGIN: type avoided cases. User " + m.nick + " with acc id " + m.id + " and IP " + get.ip(s));
  434. }
  435. }
  436. });
  437.  
  438. // SETTINGS
  439. // data format: {id::number, nick::string, settings::object}
  440. // output format: {error::booleanORstinrg, theme::nullORobject, adds::object, h::string, l::string}
  441. s.on("settings", (m, f) => {
  442. var user = {
  443. s: s,
  444. id: m.id,
  445. nick: m.nick
  446. };
  447.  
  448. // check if is online
  449. if (!is.online({sid: s.id, mid: m.id, ip: get.ip(s)}, !0)) _.log("SETTINGS: #WARNING# could not found in logged array", user);
  450.  
  451. // proccess data
  452. else if (is.correct(m, "SETTINGS", user)) {
  453. let t = {
  454. error: false,
  455. theme: null,
  456. adds: "additionals/additionals.min.js",
  457. l: "<link rel='stylesheet' type='text/css' href='&&&'>",
  458. h: "head"
  459. };
  460. switch (m.settings.theme) {
  461. case "tWing":
  462. t.theme = _.arrs.themes[0];
  463. break;
  464. case "tSecond":
  465. t.theme = _.arrs.themes[1];
  466. break;
  467. case "tBrown":
  468. t.theme = _.arrs.themes[2];
  469. break;
  470. default:
  471. _.log("SETTINGS: theme not found");
  472. t.error = true;
  473. }
  474. f(t);
  475. }
  476. });
  477.  
  478. // ONLINE
  479. // data format: {id::number, nick::string, world::string, getAll::boolean}
  480. // output format: {type::number, n::number, online::nullORobject}
  481. s.on("online", (m, f) => {
  482. var user = {
  483. s: s,
  484. id: m.id,
  485. nick: m.nick
  486. };
  487.  
  488. // check if is online
  489. if (!is.online({sid: s.id, mid: m.id, ip: get.ip(s)}, !0)) _.log("ONLINE: #WARNING# could not found in logged array", user);
  490.  
  491. // proccess data
  492. else if (is.correct(m, "ONLINE", user)) {
  493. if (m.getAll) f(_.countOnline(!0));
  494. else f(_.countOnline());
  495. }
  496. });
  497.  
  498. // CHAT
  499. // data format: {type::number, id::number, nick::string, world::string, message::string, time::string}
  500. // output format: {type::number, error::booleanORstring, mes::nullORarrayORobject}
  501. s.on("chat", (m, f) => {
  502. var user = {
  503. s: s,
  504. id: m.id,
  505. nick: m.nick
  506. };
  507.  
  508. // check if is online
  509. if (!is.online({sid: s.id, mid: m.id, ip: get.ip(s)}, !0)) _.log("CHAT: #WARNING# could not found in logged array", user);
  510.  
  511. // proccess data
  512. else if (is.correct(m, "CHAT", user)) {
  513. switch (m.type) {
  514. case 0:
  515. _.db("SELECT * FROM (SELECT * FROM `chat` WHERE UNIX_TIMESTAMP() * 1000 - `date` < 3600000 ORDER BY `id` DESC LIMIT 30) sub ORDER BY `id` ASC", a => {
  516. let t = [];
  517. for (let i = 0; i < a.length; i++) {
  518. let j = is.inArrObj(a[i].mID, _.arrs.colours, "mid");
  519. t.push({
  520. type: a[i].type,
  521. style: j > -1 ? "color: " + _.arrs.colours[j].colour + ";" : undefined,
  522. time: a[i].time,
  523. nick: a[i].nick,
  524. message: a[i].message
  525. });
  526. }
  527. f({type: 0, error: !1, mes: t});
  528. });
  529. break;
  530. case 1:
  531. let nick = get.logged({sid: s.id, mid: m.id});
  532. m.message = m.message.trim();
  533. if (!is.set(nick)) _.log("CHAT: nick is not set", user);
  534. else if (m.message.length > 250) f({error: "Błąd: wiadomość ma zbyt dużo znaków"});
  535. else if (m.message.length < 1) f({error: "Błąd: wiadomość jest pusta"});
  536. else if (m.message.search(/[^ -~ąćęłńóśżź]/gi) > -1) f({error: "Błąd: wiadomość zawiera niedozwolone znaki"});
  537. else {
  538. m.message = _.escapeHTML(m.message);
  539. m.time = _.escapeHTML(m.time);
  540. _.db(
  541. "INSERT INTO `chat` (`mID`, `date`, `time`, `type`, `nick`, `message`) VALUES (" +
  542. mySQL.escape(m.id) + ", " + get.time() + ", " + mySQL.escape(m.time) + ", 'textMes', '" + nick + "', " + mySQL.escape(m.message) + ")"
  543. );
  544. let t = is.inArrObj(m.id, _.arrs.colours, "mid");
  545. io.emit("chat", {
  546. type: 1,
  547. error: !1,
  548. mes: {
  549. type: "textMes",
  550. style: t > -1 ? "color: " + _.arrs.colours[t].colour + ";" : undefined,
  551. time: m.time,
  552. nick: nick,
  553. message: m.message
  554. }
  555. });
  556. }
  557. break;
  558. default:
  559. _.log("LOGIN: type avoided cases. User " + m.nick + " with acc id " + m.id + " and IP " + get.ip(s));
  560. }
  561. }
  562. });
  563. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement