-
Notifications
You must be signed in to change notification settings - Fork 59
/
adapter-edit.js
113 lines (88 loc) · 3.14 KB
/
adapter-edit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
const errors = require('./util-http-error');
const exec = require('child_process').exec;
const fs = require('fs');
const md5 = require('md5-file');
const mime = require('mime-types');
const path = require('path');
const shellwords = require('shellwords');
const tmp = require('tmp');
module.exports = function(config, req, cmd, callback) {
// tokenize the input string
const tokenized = shellwords.split(cmd);
const src = tokenized[1] || '';
// Generate a temporary file with an extension that mathces the source file.
// The matching extension is important to allow editors to choose the
// appropriate syntax-highlighting automatically.
const dst = tmp.fileSync({ postfix: path.extname(src) }).name;
// assert that src was provided
if (! src) {
// assemble an error message
var err = [
'Specify a file to edit.',
'Usage: edit <remote-filename>'
].join('\n');
return callback(new Error(err));
}
// initialize the POST body
const body = {
cmd : 'payload_download',
args : {
file : src,
},
};
// POST to the trojan
req.post({ body : body }, function(err, obj, response) {
if (err) {
return callback(err);
}
if (obj.statusCode !== 200) {
return callback(errors(config, obj.statusCode));
}
// convert the base64-encoded response to binary
const data = new Buffer(response.stdout, 'base64');
// write the downloaded file to the local filesystem
fs.writeFile(dst, data, function(err) {
if (err) {
response.stderr.push(err);
}
// calculate the md5 hash of the downloaded file
const hashBefore = md5.sync(dst);
// determine the appropriate application for editing the file
const mimetype = mime.lookup(path.extname(dst));
const editor = config.global.editors[mimetype] || config.global.editors.default;
// open the application
exec(editor + ' ' + dst, function(err, stdout, stderr) {
if (err) {
return callback(err);
}
// calculate the md5 hash of the file after editing
const hashAfter = md5.sync(dst);
// If the "before" and "after" hashes match, the file wasn't changed.
// Thus, we won't bother to upload it to the remote server.
if (hashBefore === hashAfter) {
response.stdout = [ 'File unchanged. Edit cancelled.' ];
return callback(null, response);
}
// Otherwise, the file *has* been edited, so we want to update the file
// on the remote server as well.
// read the file data
const data = new Buffer(fs.readFileSync(dst)).toString('base64');
// initialize the POST body
const uploadBody = {
cmd : 'payload_upload',
args : {
dst : src,
data : data,
},
};
// POST to the trojan
req.post({ body : uploadBody }, function(err, obj, response) {
if (obj.statusCode !== 200) {
return callback(errors(config, obj.statusCode));
}
callback(err, response);
});
});
});
});
};