mirror of
https://github.com/avwo/whistle.git
synced 2026-10-20 07:58:55 +08:00
163 lines
4.4 KiB
JavaScript
163 lines
4.4 KiB
JavaScript
require('../util/patch');
|
|
var express = require('express');
|
|
var bodyParser = require('body-parser');
|
|
var multer = require('multer2');
|
|
var fs = require('fs');
|
|
var path = require('path');
|
|
var Buffer = require('safe-buffer').Buffer;
|
|
var util = require('./util');
|
|
var extractSaz = require('./extract-saz');
|
|
var generateSaz = require('./generate-saz');
|
|
var getServer = require('hagent').getServer;
|
|
|
|
var SESSIONS_FILE_RE = /\.(txt|json|saz)$/i;
|
|
var TEMP_FILES_PATH;
|
|
var LIMIT_SIZE = 1024 * 1024 * 128;
|
|
var MAX_TEMP_SIZE = 1024 * 1024 * 10;
|
|
var TEMP_FILE_RE = /^[\da-f]{64}$/;
|
|
var storage = multer.memoryStorage();
|
|
var upload = multer({
|
|
storage: storage,
|
|
fieldSize: LIMIT_SIZE
|
|
});
|
|
|
|
function statRetry(filepath, callback, retry) {
|
|
fs.stat(filepath, function(e, stat) {
|
|
if (!e || retry) {
|
|
return callback(e, stat);
|
|
}
|
|
statRetry(filepath, callback, true);
|
|
});
|
|
}
|
|
|
|
function writeRetry(filepath, data, callback, retry) {
|
|
fs.writeFile(filepath, data, function(e) {
|
|
if (!e || retry) {
|
|
return callback(e);
|
|
}
|
|
writeRetry(filepath, data, callback, true);
|
|
});
|
|
}
|
|
|
|
function writeFile(filepath, data, callback) {
|
|
statRetry(filepath, function(e, stat) {
|
|
if (!stat || !stat.isFile()) {
|
|
return writeRetry(filepath, data, callback);
|
|
}
|
|
callback();
|
|
});
|
|
}
|
|
|
|
function getContent(options) {
|
|
var value = options.value;
|
|
if (value && typeof value === 'string') {
|
|
return value;
|
|
}
|
|
var base64 = options.base64;
|
|
if (base64) {
|
|
try {
|
|
return Buffer.from(base64, 'base64');
|
|
} catch(e) {}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function sessionsHandler() {
|
|
var app = express();
|
|
app.use(function (req, res, next) {
|
|
req.on('error', abort);
|
|
res.on('error', abort);
|
|
function abort() {
|
|
res.destroy();
|
|
}
|
|
next();
|
|
});
|
|
app.get('/cgi-bin/sessions/get-temp-file', function(req, res) {
|
|
var filename = req.query.filename;
|
|
if (!TEMP_FILE_RE.test(filename)) {
|
|
return res.json({ ec: 0 });
|
|
}
|
|
filename = path.join(TEMP_FILES_PATH, filename);
|
|
statRetry(filename, function(err, stat) {
|
|
if (err ? err.code === 'ENOENT' : !stat.isFile()) {
|
|
return res.json({ ec: 0 });
|
|
}
|
|
if (err) {
|
|
return res.json({ ec: 2, em: err.message || 'Error' });
|
|
}
|
|
if (stat.size > MAX_TEMP_SIZE) {
|
|
return res.json({ ec: 0, em: 'File is too large to load.' });
|
|
}
|
|
fs.readFile(filename, function(e, data) {
|
|
if (e) {
|
|
return res.json({ ec: 2, em: e.message || 'Error' });
|
|
}
|
|
res.json({ ec: 0, value: data + '' });
|
|
});
|
|
});
|
|
});
|
|
app.use('/cgi-bin/sessions/create-temp-file',
|
|
bodyParser.json({ limit: 1024 * 1024 * 72 }),
|
|
function(req, res) {
|
|
var value = getContent(req.body);
|
|
var filename = util.getHexHash(value);
|
|
writeFile(path.join(TEMP_FILES_PATH, filename), value, function(e) {
|
|
if (e) {
|
|
return res.json({ ec: 2, em: e.message });
|
|
}
|
|
res.json({ ec: 0, filepath: 'temp/' + filename });
|
|
});
|
|
}
|
|
);
|
|
app.use(
|
|
'/cgi-bin/sessions/import',
|
|
upload.single('importSessions'),
|
|
function (req, res) {
|
|
var file = req.file;
|
|
var suffix;
|
|
if (file && SESSIONS_FILE_RE.test(file.originalname)) {
|
|
suffix = RegExp.$1.toLowerCase();
|
|
}
|
|
if (!suffix || !Buffer.isBuffer(file.buffer)) {
|
|
return res.json([]);
|
|
}
|
|
if (suffix !== 'saz') {
|
|
var sessions = util.parseJSON(file.buffer + '');
|
|
return res.json(Array.isArray(sessions) ? sessions : []);
|
|
}
|
|
try {
|
|
extractSaz(file.buffer, res.json.bind(res));
|
|
} catch (e) {
|
|
res.status(500).send(e.stack);
|
|
}
|
|
}
|
|
);
|
|
app.use(bodyParser.urlencoded({ extended: true, limit: LIMIT_SIZE }));
|
|
app.use(bodyParser.json());
|
|
app.use('/cgi-bin/sessions/export', function (req, res) {
|
|
var body = req.body;
|
|
var type = body.exportFileType;
|
|
var download = function(content) {
|
|
res.attachment(util.getFilename(type, body.exportFilename)).send(content || body.sessions);
|
|
};
|
|
if (type !== 'Fiddler') {
|
|
return download();
|
|
}
|
|
generateSaz(body, function(e, body) {
|
|
if (e) {
|
|
return res.status(500).send(e.stack);
|
|
}
|
|
download(body);
|
|
});
|
|
});
|
|
return app;
|
|
}
|
|
|
|
module.exports = function (options, callback) {
|
|
TEMP_FILES_PATH = options.TEMP_FILES_PATH;
|
|
getServer(function (server, port) {
|
|
server.on('request', sessionsHandler());
|
|
callback(null, { port: port });
|
|
});
|
|
};
|