2023-02-19 15:19:46 +01:00
|
|
|
const Sequelize = require('../models');
|
2023-02-27 02:04:47 +01:00
|
|
|
const xml = require('xml');
|
2023-03-12 03:28:05 +01:00
|
|
|
const handler = require('express-async-handler');
|
2023-04-20 08:40:47 +02:00
|
|
|
const Helpers = require('../helpers');
|
2023-06-06 03:25:43 +02:00
|
|
|
const crypto = require('crypto');
|
2023-02-20 03:43:53 +01:00
|
|
|
|
2023-06-06 03:25:43 +02:00
|
|
|
const send_error = async (req, res, error) => {
|
|
|
|
const code = crypto.randomBytes(2).toString('hex');
|
|
|
|
req.session.gb_error = {
|
|
|
|
text: error,
|
|
|
|
code
|
|
|
|
}
|
|
|
|
return res.redirect('/guestbook?error=' + code);
|
2023-02-20 03:43:53 +01:00
|
|
|
};
|
2023-02-19 06:30:02 +01:00
|
|
|
|
2023-03-12 03:28:05 +01:00
|
|
|
async function guestbook(req, res, next) {
|
2023-02-19 08:07:44 +01:00
|
|
|
try {
|
2023-02-19 16:12:09 +01:00
|
|
|
|
2023-06-06 03:25:43 +02:00
|
|
|
if (!req.query.error) {
|
|
|
|
delete req.session.gb_error;
|
|
|
|
}
|
|
|
|
if (req.query.error && req.session.gb_error === undefined) {
|
|
|
|
return res.redirect('/guestbook');
|
|
|
|
}
|
|
|
|
|
|
|
|
const errors =
|
|
|
|
req.query.error && req.session.gb_error ?
|
|
|
|
req.session.gb_error.code == req.query.error ?
|
|
|
|
req.session.gb_error.text :
|
|
|
|
null
|
|
|
|
: false;
|
2023-02-20 03:43:53 +01:00
|
|
|
|
2023-02-20 05:07:48 +01:00
|
|
|
const data = await Sequelize.Guestbook.findAll({
|
2023-02-19 16:12:09 +01:00
|
|
|
where: {
|
|
|
|
hidden: false
|
2023-02-20 03:53:03 +01:00
|
|
|
},
|
|
|
|
order: [
|
|
|
|
['id', 'DESC']
|
|
|
|
]
|
2023-02-19 16:12:09 +01:00
|
|
|
});
|
2023-02-20 05:07:48 +01:00
|
|
|
if (!data) throw new Error('Failed to get guestbook entries');
|
2023-02-19 16:12:09 +01:00
|
|
|
|
2023-03-11 16:54:53 +01:00
|
|
|
res.template('guestbook.pug', {
|
2023-02-19 08:07:44 +01:00
|
|
|
current_route: req.originalUrl,
|
|
|
|
ip: req.ip,
|
2023-02-20 03:43:53 +01:00
|
|
|
data,
|
2023-02-27 02:08:44 +01:00
|
|
|
errors,
|
|
|
|
name: req.session.gb_name,
|
2023-02-27 02:17:40 +01:00
|
|
|
email: req.session.gb_email,
|
|
|
|
hidemail: req.session.gb_hidemail
|
2023-03-11 16:54:53 +01:00
|
|
|
});
|
2023-02-19 08:07:44 +01:00
|
|
|
return;
|
|
|
|
} catch (err) {
|
|
|
|
next(err);
|
|
|
|
}
|
2023-02-19 06:30:02 +01:00
|
|
|
}
|
|
|
|
|
2023-02-19 16:12:09 +01:00
|
|
|
async function submit(req, res, next) {
|
2023-02-19 08:07:44 +01:00
|
|
|
const { name, email, message } = req.body;
|
|
|
|
const hidemail = req.body.hidemail ? (req.body.hidemail == 'on' ? true : false) : false;
|
|
|
|
|
2023-02-22 07:42:43 +01:00
|
|
|
// check for errors
|
2023-02-20 07:54:08 +01:00
|
|
|
let errors = [];
|
2023-02-20 06:34:26 +01:00
|
|
|
if (message.length >= 512) {
|
2023-02-20 07:54:08 +01:00
|
|
|
errors.push('Maximum length is 512 characters.');
|
|
|
|
}
|
2023-03-18 04:14:58 +01:00
|
|
|
if (name.match(/^(\s|\u00A0|[\u2000-\u2009]|\u200A|\u2028|\u205F|\u3000)*$/g)) {
|
2023-02-20 07:54:08 +01:00
|
|
|
errors.push('Name must be specified.');
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!email
|
|
|
|
.toLowerCase()
|
|
|
|
.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
|
|
|
|
&&
|
|
|
|
email !== ''
|
|
|
|
) {
|
|
|
|
errors.push('Email is of invalid format.');
|
|
|
|
}
|
|
|
|
if (message == '') {
|
|
|
|
errors.push('Message should not be empty!');
|
|
|
|
}
|
2023-04-20 08:40:47 +02:00
|
|
|
|
|
|
|
if (process.env.DISALLOW_TOR.split(',').indexOf('guestbook') !== -1) {
|
|
|
|
let ip4 = req.ip.startsWith('::ffff:') ? req.ip.replace(/^::ffff:/, '') : req.ip;
|
|
|
|
if (await Helpers.TorChecker.check(ip4)) {
|
|
|
|
errors.push('Using tor is not allowed: IP ' + ip4 + ' is listed as a tor exit');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 07:54:08 +01:00
|
|
|
if (errors.length !== 0) {
|
2023-06-06 03:25:43 +02:00
|
|
|
send_error(req, res, "<p>" + errors.join('<br/>') + "</p>");
|
2023-02-20 06:34:26 +01:00
|
|
|
return;
|
|
|
|
}
|
2023-03-18 04:11:11 +01:00
|
|
|
// done checking for errors
|
2023-02-20 06:34:26 +01:00
|
|
|
|
2023-02-27 02:08:44 +01:00
|
|
|
req.session.gb_name = name;
|
|
|
|
req.session.gb_email = email;
|
2023-02-27 02:17:40 +01:00
|
|
|
req.session.gb_hidemail = req.body.hidemail;
|
2023-02-22 07:42:43 +01:00
|
|
|
|
|
|
|
let records = await Sequelize.Guestbook.findAll({
|
|
|
|
where: {
|
|
|
|
ip: req.ip
|
|
|
|
}
|
|
|
|
});
|
|
|
|
let latest = 0;
|
|
|
|
for (const record of records) {
|
|
|
|
if (record.time > latest) latest = record.time;
|
|
|
|
}
|
|
|
|
const time = Math.floor(Date.now() / 1000);
|
|
|
|
|
|
|
|
if (time - latest < 60) {
|
2023-06-06 03:25:43 +02:00
|
|
|
send_error(
|
|
|
|
req,
|
|
|
|
res,
|
|
|
|
'You are allowed to send 1 message per minute. You will be able to send next message in ' + ((latest + 60) - time) + ' seconds.'
|
2023-02-22 07:42:43 +01:00
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-19 16:12:09 +01:00
|
|
|
let data = await Sequelize.Guestbook.create({
|
|
|
|
name,
|
|
|
|
email,
|
|
|
|
text: message,
|
|
|
|
hidemail,
|
|
|
|
ip: req.ip,
|
|
|
|
hidden: false,
|
|
|
|
time: Math.floor(Date.now() / 1000)
|
|
|
|
});
|
2023-02-20 03:43:53 +01:00
|
|
|
if (!data) {
|
2023-03-11 16:54:53 +01:00
|
|
|
res.template('guestbook.pug', {
|
2023-02-20 03:43:53 +01:00
|
|
|
current_route: req.originalUrl,
|
|
|
|
ip: req.ip,
|
|
|
|
errors: 'Could not create a new record'
|
2023-03-11 16:54:53 +01:00
|
|
|
});
|
2023-02-20 03:43:53 +01:00
|
|
|
}
|
2023-02-19 16:12:09 +01:00
|
|
|
|
|
|
|
res.redirect('/guestbook#gb_entry_' + data.id);
|
2023-02-19 15:19:46 +01:00
|
|
|
|
2023-02-19 07:05:36 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-20 03:43:53 +01:00
|
|
|
async function del(req, res, next) {
|
|
|
|
try
|
|
|
|
{
|
|
|
|
let record = await Sequelize.Guestbook.findAndCountAll({
|
|
|
|
where: {id: req.params.id}
|
|
|
|
});
|
|
|
|
if (record.count == 0) {
|
|
|
|
res.redirect('/guestbook');
|
|
|
|
}
|
|
|
|
const data = record.rows[0];
|
|
|
|
if (
|
|
|
|
data.ip == req.ip &&
|
|
|
|
Math.floor(Date.now() / 1000) - data.time <= (60 * 60 * 24)
|
|
|
|
) {
|
|
|
|
await Sequelize.Guestbook.update({hidden: true}, {where: {id: req.params.id}})
|
|
|
|
res.redirect('/guestbook');
|
|
|
|
} else {
|
2023-06-06 03:25:43 +02:00
|
|
|
return send_error(req, res, 'You don\'t have permission to delete this record.');
|
2023-02-20 03:43:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) { next(err); }
|
|
|
|
}
|
|
|
|
|
2023-02-27 02:04:47 +01:00
|
|
|
async function rss(req, res) {
|
|
|
|
const data = (await Sequelize.Guestbook.findAndCountAll({where: {hidden: false}})).rows;
|
|
|
|
|
|
|
|
let rss = [{
|
|
|
|
rss: [{
|
|
|
|
_attr: {version: '2.0'}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
channel: [
|
|
|
|
{title: 'Guestbook'},
|
2023-02-27 02:17:40 +01:00
|
|
|
{link: req.protocol + '://' + req.get('host') + '/guestbook'},
|
2023-02-27 02:04:47 +01:00
|
|
|
{description: 'Alice\'s guestbook'},
|
|
|
|
]
|
|
|
|
}]
|
|
|
|
}]
|
|
|
|
|
|
|
|
for (const record of data) {
|
2023-03-18 08:02:58 +01:00
|
|
|
if (record.email == null || record.email == undefined) {
|
|
|
|
record.email = 'no@email.com';
|
|
|
|
}
|
2023-02-27 02:04:47 +01:00
|
|
|
if (record.hidemail)
|
|
|
|
record.email = ('?'.repeat(record.email.split('@')[0].length)) + '@?.?';
|
|
|
|
|
|
|
|
rss[0].rss[1].channel.push({
|
|
|
|
item: [
|
|
|
|
{description: record.text},
|
|
|
|
{author: `"${record.name}"${record.email ? (' at ' + record.email) : ''}`},
|
|
|
|
{link: req.protocol + '://' + req.get('host') + '/guestbook#gb_entry_' + record.id}
|
|
|
|
]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-02-27 08:19:29 +01:00
|
|
|
let ident = 0;
|
2023-02-27 02:04:47 +01:00
|
|
|
if (req.query.ident) ident = req.query.ident;
|
|
|
|
|
2023-02-27 07:34:44 +01:00
|
|
|
res.header('Content-Type', 'application/rss+xml');
|
2023-02-27 02:04:47 +01:00
|
|
|
res.send(xml(rss, {indent: ' '.repeat(ident)}));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-19 06:30:02 +01:00
|
|
|
module.exports = (router) => {
|
2023-03-12 03:28:05 +01:00
|
|
|
router.get('/guestbook', handler(guestbook));
|
|
|
|
router.post('/guestbook/submit', handler(submit));
|
|
|
|
router.get('/guestbook/del/:id', handler(del));
|
|
|
|
router.get('/guestbook.rss', handler(rss));
|
2023-02-19 06:30:02 +01:00
|
|
|
}
|