forked from nrhirani/node-qpdf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
171 lines (140 loc) · 4.48 KB
/
index.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
var spawn = require('child_process').spawn;
var stream = require('stream');
var Qpdf = {};
Qpdf.encrypt = function(input, options, callback) {
if (!input) return handleError(new Error('Specify input file'));
if(options && options.outputFile) {
if(typeof options.outputFile != 'string' || options.outputFile === input) {
return handleError(new Error('Invlaid output file'));
}
}
// Defaults encryption to AES 256
options.keyLength = options.keyLength || '256';
var args = [Qpdf.command, '--encrypt'];
// Set user-password and owner-password
if(typeof options.password === 'object') {
if(options.password.user === undefined || options.password.owner === undefined) {
return handleError(new Error('Specify owner and user password'));
}
args.push(options.password.user);
args.push(options.password.owner);
} else {
// Push twice for user-password and owner-password
args.push(options.password);
args.push(options.password);
}
// Specifying the key length
args.push(options.keyLength);
// Add Resctrictions for encryption
if (options.restrictions) {
if (typeof options.restrictions !== 'object') return handleError(new Error('Invalid Restrictions'));
var restrictions = options.restrictions;
for(var restriction in restrictions) {
var value = (restrictions[restriction] !== '') ? '=' + restrictions[restriction] : '';
args.push('--' + hyphenate(restriction) + value);
}
}
// Marks end of --encrypt options
args.push('--');
// Input file path
args.push(input);
if (options.outputFile) {
args.push(options.outputFile);
} else {
// Print PDF on stdout
args.push('-');
}
// Execute command and return stdout for pipe
if (!options.outputFile) {
var outputStream = executeCommand(args);
if (outputStream) {
if (callback) {
return callback(null, outputStream);
} else {
return outputStream;
}
}
} else {
if (callback) {
executeCommand(args, callback);
} else {
return new Promise(function(resolve, reject) {
executeCommand(args, function(err, filePath) {
if (err) {
reject(err);
} else {
resolve(filePath);
}
});
});
}
}
};
Qpdf.decrypt = function(input, password, callback) {
if (!input) return handleError(new Error('Specify input file'), callback);
if (!password) return handleError(new Error('Password missing'), callback);
var args = [Qpdf.command, '--decrypt'];
// Password
args.push('--password=' + password);
// Input file path
args.push(input);
// Print PDf on stdout
args.push('-');
// Execute command and return stdout for pipe
var outputStream = executeCommand(args, callback);
if (outputStream) {
return outputStream;
}
};
function executeCommand(args, callback) {
var child;
var output = args[args.length - 1];
// if on windows or not piping to stdout
if (process.platform === 'win32' || output !== '-') {
child = spawn(args[0], args.slice(1));
} else {
// this nasty business prevents piping problems on linux
child = spawn('/bin/sh', ['-c', args.join(' ') + ' | cat']);
}
// call the callback with null error when the process exits successfully
if (callback) {
child.on('exit', function() { callback(null, output); });
}
var outputStream = child.stdout;
child.once('error', function (err) {
handleError(err, child, outputStream, callback);
});
child.stderr.once('data', function(err) {
handleError(new Error(err || ''), child, outputStream, callback);
});
// return stdout stream so we can pipe
return outputStream;
}
function handleError(err, child, outputStream, callback) {
if (child) {
child.removeAllListeners('exit');
child.kill();
} else if (typeof child === 'function') {
callback = child;
}
// call the callback if there is one
if (callback) {
callback(err);
}
// set a default output stream if not present
if (typeof outputStream === 'function') {
callback = outputStream;
outputStream = new stream.Readable();
} else if (typeof outputStream === 'undefined') {
outputStream = new stream.Readable();
}
// if not, or there are listeners for errors, emit the error event
if (!callback || outputStream.listeners('error').length > 0) {
outputStream.emit('error', err);
}
}
function hyphenate(variable) {
return variable.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
Qpdf.command = 'qpdf';
module.exports = Qpdf;