input.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. const whiskers = require('whiskers');
  2. const fs = require('fs');
  3. const PasteContent = require('../models/pasteContent.js').PasteContent;
  4. const mCrypto = require('../src/crypto.js');
  5. const Security = require('../src/security.js');
  6. async function renderRawPage(app, req, res, entity) {
  7. if (entity.type === 'paste')
  8. return await app.routerUtils.staticServe(res, app.getData(entity.privId));
  9. else if (entity.type === 'file') {
  10. let data = JSON.parse(entity.data);
  11. return await app.routerUtils.staticDownload(res, app.getData(entity.privId), data.name, data.type);
  12. }
  13. else if (entity.type === 'short')
  14. return res.end(entity.data); // FIXME stats + ?rel
  15. app.routerUtils.onInternalError(res, "Unknown type: " +entity.type);
  16. }
  17. async function renderPublicPage(app, req, res, entity) {
  18. if (entity.type === 'paste')
  19. return await app.routerUtils.staticServe(res, app.getData(entity.privId));
  20. else if (entity.type === 'file') {
  21. let data = JSON.parse(entity.data);
  22. return await app.routerUtils.staticDownload(res, app.getData(entity.privId), data.name, data.type);
  23. }
  24. else if (entity.type === 'short')
  25. return app.routerUtils.redirect(res, entity.data);
  26. app.routerUtils.onInternalError(res, "Unknown type: " +entity.type);
  27. }
  28. function renderPrivatePage(app, res, entity) {
  29. let stat;
  30. try { stat = fs.statSync(app.dataDir+entity.privId); } catch (e) { stat = { error: e }; }
  31. app.routerUtils.jsonResponse(res, { ...entity.describe(), ...stat, ...{ path: app.getData(entity.privId) } });
  32. }
  33. module.exports = { register: app => {
  34. // Root
  35. app.router.get("/", (req, res) => {
  36. app.routerUtils.redirect(res, '/pastit');
  37. });
  38. // Access page
  39. app.router.get("/x/:id", async (req, res) => {
  40. let entity = await app.databaseHelper.findOne(PasteContent, { privId: req.params.id, publicId: req.params.id }, " or ");
  41. if (entity && entity.privId === req.params.id)
  42. return renderPrivatePage(app, res, entity);
  43. if (entity && !entity.expired)
  44. return renderPublicPage(app, req, res, entity);
  45. app.routerUtils.onPageNotFound(res);
  46. });
  47. app.router.get("/x/raw/:id", async (req, res) => {
  48. let entity = await app.databaseHelper.findOne(PasteContent, { privId: req.params.id, publicId: req.params.id }, " or ");
  49. if (entity && !entity.expired)
  50. return renderRawPage(app, req, res, entity);
  51. app.routerUtils.onPageNotFound(res);
  52. });
  53. // pastebin tool
  54. app.router.get("/pastit", (req, res) => {
  55. let context = app.routerUtils.commonRenderInfos();
  56. context.page_title += " - Pastit";
  57. res.end(whiskers.render(require('../templates/pastit.js'), context));
  58. });
  59. app.router.post("/pastit", async (req, res) => {
  60. const content = req.body.content;
  61. const privId = mCrypto.string(content);
  62. const captchaOk = await Security.captchaCheck(req.body['g-recaptcha-response'], req.headers['x-forwarded-for'] || req.socket.remoteAddress);
  63. let entity = await app.databaseHelper.findOne(PasteContent, { privId: privId });
  64. if (!captchaOk)
  65. return app.routerUtils.jsonResponse(res, { err: "Invalid captcha input", id: null });
  66. if (!content || !content.length)
  67. return app.routerUtils.jsonResponse(res, { err: "Empty input", id: null });
  68. if (entity && !entity.expired) {
  69. entity.renew();
  70. await app.databaseHelper.update({privId: privId}, entity);
  71. } else {
  72. entity = entity || new PasteContent(privId, "paste");
  73. entity.expired = false;
  74. entity.renew();
  75. fs.writeFileSync(app.getData(privId), content);
  76. await app.databaseHelper.upsertOne(entity);
  77. }
  78. app.routerUtils.jsonResponse(res, { err: null, id: entity.publicId });
  79. });
  80. // URL shortener tool
  81. app.router.get("/short", (req, res) => {
  82. let context = app.routerUtils.commonRenderInfos();
  83. context.page_title += " - Shortener";
  84. res.end(whiskers.render(require('../templates/short.js'), context));
  85. });
  86. app.router.post("/short", async (req, res) => {
  87. const link = req.body.content;
  88. const privId = mCrypto.string(await app.databaseHelper.count(PasteContent) + link);
  89. const captchaOk = await Security.captchaCheck(req.body['g-recaptcha-response'], req.headers['x-forwarded-for'] || req.socket.remoteAddress);
  90. if (!captchaOk)
  91. return app.routerUtils.jsonResponse(res, { err: "Invalid captcha input", id: null });
  92. if (!link || !link.length)
  93. return app.routerUtils.jsonResponse(res, { err: "Empty input", id: null });
  94. entity = new PasteContent(privId, "short");
  95. entity.data = link;
  96. await app.databaseHelper.insertOne(entity);
  97. app.routerUtils.jsonResponse(res, { err: null, id: entity.privId });
  98. });
  99. // Files tool
  100. app.router.get("/files", (req, res) => {
  101. let context = app.routerUtils.commonRenderInfos();
  102. context.page_title += " - File host";
  103. res.end(whiskers.render(require('../templates/files.js'), context));
  104. });
  105. app.router.post("/files", async (req, res) => {
  106. const formData = (req.body["multipart-data"] || []).reduce((res, x) => { res[x.fieldName] = x; return res; }, {});
  107. const privId = mCrypto.string(await app.databaseHelper.count(PasteContent) + (req.content?.fileName || ""));
  108. const captchaOk = await Security.captchaCheck(formData["g-recaptcha-response"]?.fileData, req.headers['x-forwarded-for'] || req.socket.remoteAddress);
  109. if (!captchaOk)
  110. return app.routerUtils.jsonResponse(res, { err: "Invalid captcha input", id: null });
  111. if (!formData.content?.fileData || !formData.content.fileData.length)
  112. return app.routerUtils.jsonResponse(res, { err: "Empty input", id: null });
  113. const entity = new PasteContent(privId, "file");
  114. entity.data = JSON.stringify({ name: formData.content.fileName, type: formData.content.fileType });
  115. fs.writeFileSync(app.getData(privId), formData.content.fileData, {encoding: formData.content.fileType.indexOf('text') >= 0 ? 'utf8' : 'binary'});
  116. await app.databaseHelper.insertOne(entity);
  117. app.routerUtils.jsonResponse(res, { err: null, id: entity.privId });
  118. });
  119. }};