Implement attachment downloading

master
Vitaliy Filippov 2019-05-19 15:25:14 +03:00
parent 006e180553
commit b8634a9269
4 changed files with 46 additions and 4 deletions

View File

@ -431,7 +431,7 @@ class Syncer
{
byid[a.contentId||''] = a;
}
msg.html = msg.html.replace(/(<img[^<>]*src=["']?)cid:([^'"\s]{1,256})/g, (m, m1, m2) =>
msg.html = (msg.html||'').replace(/(<img[^<>]*src=["']?)cid:([^'"\s]{1,256})/g, (m, m1, m2) =>
{
if (!byid[m2])
{
@ -618,12 +618,12 @@ class Syncer
body_html: obj.html,
body_html_text: obj.html.replace(/<style[^>]*>.*<\/style\s*>|<\/?[^>]*>/g, ''),
};
/*await SQL.update(
await SQL.update(
this.pg, 'messages m', {
...upd,
'props = props || ?': [ { attachments: obj.attachments } ]
}, { folder_id: boxId, uid: msg[0].uid }
);*/
);
if (messages.length == 1)
{
upd.props = { attachments: obj.attachments };

View File

@ -6,6 +6,7 @@ const express_session = require('express-session');
const morgan = require('morgan');
const bodyparser = require('body-parser');
const multer = require('multer');
const rawurlencode = require('rawurlencode');
const SQL = require('./select-builder-pgsql.js');
@ -35,6 +36,7 @@ class SyncerWeb
this.app.get('/groups', wrapAsync(this, 'get_groups'));
this.app.get('/messages', wrapAsync(this, 'get_messages'));
this.app.get('/message', wrapAsync(this, 'get_message'));
this.app.get('/attachment', wrapAsync(this, 'get_attachment'));
this.app.post('/sync', wrapAsync(this, 'post_sync'));
this.syncer.events.on('sync', (params) => this.syncer_sync(params));
}
@ -256,6 +258,45 @@ class SyncerWeb
return res.send({ msg: msg });
}
async get_attachment(req, res)
{
if (this.cfg.login && (!req.session || !req.session.auth))
{
return res.sendStatus(401);
}
let msgId = req.query.msgId;
let sha1 = (req.query.sha1||'').replace(/[^0-9a-fA-F]+/g, '').toLowerCase();
if (!msgId || !sha1)
{
return res.sendStatus(404);
}
let msg = await SQL.select(
this.pg, 'messages', '*', { id: msgId }, null, SQL.MS_ROW
);
let a = ((msg.props||{}).attachments||[]).filter(a => a.sha1 == sha1)[0];
if (!a)
{
return res.sendStatus(404);
}
if (new RegExp(
// HTML may contain cookie-stealing JavaScript and web bugs
'^text/(html|(x-)?javascript)$|^application/x-shellscript$'+
// PHP/Perl/Bash/etc scripts may execute arbitrary code on the server
'|php|perl|python|bash|x-c?sh(e|$)'+
// Client-side hazards on Internet Explorer
'|^text/scriptlet$|^application/x-msdownload$'+
// Windows metafile, client-side vulnerability on some systems
'|^application/x-msmetafile$', 'is'
).exec(a.mimetype))
{
a.mimetype = 'application/octet-stream';
}
res.set('Content-Type', a.mimetype);
res.set('Content-Disposition', 'attachment; filename*=UTF-8\'\''+rawurlencode(a.name));
await new Promise((r, j) => res.sendFile(this.syncer.files_path+'/'+sha1.substr(0, 2)+'/'+sha1.substr(2, 2)+'/'+sha1+'.bin', r));
res.end();
}
syncer_sync(params)
{
this.io.emit('sync', params);

View File

@ -1,8 +1,8 @@
/**
* TODO:
* + скачивание вложений
* - пометка прочитанным, просмотренным (seen)
* - фоновая индексация всех текстов сообщений в ящике
* - скачивание вложений
* - написание сообщений
* - ответ, пересылка
* - подсказка адресов

View File

@ -21,6 +21,7 @@
"nodemailer": "latest",
"pg": "^7.10.0",
"pg-escape": "^0.2.0",
"rawurlencode": "^1.0.2",
"socket.io": "latest"
},
"peerDependencies": {},