Implement attachment downloading
parent
006e180553
commit
b8634a9269
|
@ -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 };
|
||||
|
|
41
SyncerWeb.js
41
SyncerWeb.js
|
@ -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);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* TODO:
|
||||
* + скачивание вложений
|
||||
* - пометка прочитанным, просмотренным (seen)
|
||||
* - фоновая индексация всех текстов сообщений в ящике
|
||||
* - скачивание вложений
|
||||
* - написание сообщений
|
||||
* - ответ, пересылка
|
||||
* - подсказка адресов
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"nodemailer": "latest",
|
||||
"pg": "^7.10.0",
|
||||
"pg-escape": "^0.2.0",
|
||||
"rawurlencode": "^1.0.2",
|
||||
"socket.io": "latest"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
|
|
Loading…
Reference in New Issue