UNPKG

8.1 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.9.3
2var EventEmitter, File, Zip, _extend, basename, bhttp, createWriteStream, dirname, execFile, extname, join, mime, minimatch, mkdirp, normalize, parse, path, ref, sanitize, stat, url;
3
4mime = require('mime');
5
6url = require('url');
7
8parse = url.parse;
9
10path = require('path');
11
12normalize = path.normalize, dirname = path.dirname, basename = path.basename, extname = path.extname, join = path.join;
13
14_extend = require('util')._extend;
15
16ref = require('fs'), createWriteStream = ref.createWriteStream, stat = ref.stat;
17
18sanitize = require('sanitize-filename');
19
20mkdirp = require('mkdirp');
21
22execFile = require('child_process').execFile;
23
24Zip = require('adm-zip');
25
26minimatch = require('minimatch');
27
28bhttp = require('bhttp');
29
30EventEmitter = require('events').EventEmitter;
31
32File = (function() {
33 function File(_url, _pageUrl) {
34 this._url = _url;
35 this._pageUrl = _pageUrl;
36 this._ee = new EventEmitter();
37 }
38
39 File.prototype._bindCallback = function(response, callback, data) {
40 if (typeof callback === 'function') {
41 return response.on('end', function() {
42 return callback(data);
43 });
44 }
45 };
46
47 File.prototype._getDefaultDownloadOptions = function() {
48 return {
49 headers: {},
50 pageUrlAsReferrer: false,
51 filenameMode: {
52 contentDisposition: false,
53 urlBasename: false,
54 contentType: false,
55 predefined: false,
56 redirect: false
57 },
58 directory: ''
59 };
60 };
61
62 File.prototype._getExtension = function(contentType) {
63 var extension;
64 if (contentType != null) {
65 extension = mime.extension(contentType);
66 if (extension != null) {
67 extension = "." + extension;
68 }
69 }
70 return extension;
71 };
72
73 File.prototype._getFilename = function(initialUrl, options, response) {
74 var filename;
75 if (typeof options.filenameMode.predefined === 'string') {
76 filename = sanitize(options.filenameMode.predefined);
77 } else if (options.filenameMode.urlBasename === true) {
78 if (options.filenameMode.redirect === true) {
79 filename = basename(parse(response.request.url).pathname);
80 } else {
81 filename = basename(parse(initialUrl).pathname);
82 }
83 filename = decodeURIComponent(filename);
84 }
85 return filename;
86 };
87
88 File.prototype.download = function(options, callback) {
89 var domain, downloadCallback, downloadUrl, requestOptions, thisClass, type;
90 thisClass = this;
91 downloadUrl = this._url;
92 type = typeof options;
93 if (type === 'string') {
94 options = {
95 filenameMode: {
96 predefined: options
97 }
98 };
99 } else if (type === 'object' && Object.keys(options).length === 0) {
100 options = {
101 filenameMode: {
102 urlBasename: true
103 }
104 };
105 }
106 options = _extend(this._getDefaultDownloadOptions(), options);
107 requestOptions = {
108 headers: options.headers,
109 stream: true,
110 noDecode: true
111 };
112 if (downloadUrl[0] === '/' && this._pageUrl.length > 0) {
113 domain = url.resolve(this._pageUrl, '/').replace(/\/$/, '');
114 downloadUrl = domain + downloadUrl;
115 }
116 if (options.pageUrlAsReferrer === true) {
117 requestOptions.headers.referer = this._pageUrl ? this._pageUrl : downloadUrl;
118 }
119 downloadCallback = function(err, response) {
120 var callbackData, cdFilename, contentDisposition, contentType, extension, filename, startDownload;
121 if (err) {
122 throw err;
123 }
124 contentType = response.headers['content-type'];
125 extension = thisClass._getExtension(contentType);
126 filename = thisClass._getFilename(downloadUrl, options, response);
127 if (options.filenameMode.urlBasename === true && options.filenameMode.contentType === true && (extension != null) && extension !== extname(filename)) {
128 filename += extension;
129 }
130 contentDisposition = response.headers['content-disposition'];
131 if (options.filenameMode.contentDisposition === true && (contentDisposition != null)) {
132 cdFilename = contentDisposition.split('filename=')[1].replace(/"/g, '');
133 if (cdFilename.length > 0) {
134 filename = sanitize(cdFilename);
135 }
136 }
137 if (filename == null) {
138 throw new Error('File name is not defined');
139 }
140 options.directory = path.resolve(options.directory);
141 thisClass._file = join(options.directory, filename);
142 callbackData = {
143 url: downloadUrl,
144 file: thisClass._file
145 };
146 startDownload = function() {
147 thisClass._stream = createWriteStream(thisClass._file);
148 thisClass._ee.emit('create');
149 File.prototype._bindCallback(response, callback, callbackData);
150 return response.pipe(thisClass._stream);
151 };
152 return stat(options.directory, function(err, stats) {
153 if (err && err.code === 'ENOENT') {
154 return mkdirp(options.directory, function() {
155 return startDownload();
156 });
157 } else if (!err) {
158 return startDownload();
159 } else {
160 throw err;
161 }
162 });
163 };
164 this._req = bhttp.get(downloadUrl, requestOptions, downloadCallback);
165 return this;
166 };
167
168 File.prototype._getDefaultExtractOptions = function() {
169 return {
170 to: '',
171 cd: false,
172 cdRegex: false,
173 fileGlob: false,
174 maintainEntryPath: true,
175 overwrite: true
176 };
177 };
178
179 File.prototype._extractOnFinish = function(options, callback) {
180 var cdRegex, cdRegexSuffix, entries, extracted, zip;
181 zip = new Zip(this._file);
182 entries = zip.getEntries();
183 options = _extend(this._getDefaultExtractOptions(), options);
184 cdRegexSuffix = '([^\\\/\\\\]*(\\\/|\\\\))';
185 cdRegex = null;
186 if (typeof options.cd === 'string' || typeof options.cdRegex === 'string') {
187 if (typeof options.cd === 'string') {
188 cdRegex = new RegExp("^" + options.cd + cdRegexSuffix);
189 } else if (typeof options.cdRegex === 'string') {
190 cdRegex = new RegExp("" + options.cdRegex + cdRegexSuffix);
191 }
192 entries = entries.filter(function(entry) {
193 if (cdRegex != null) {
194 return cdRegex.test(entry.entryName);
195 } else {
196 return true;
197 }
198 });
199 }
200 if (typeof options.fileGlob === 'string') {
201 entries = entries.filter(function(entry) {
202 return minimatch(entry.name, options.fileGlob);
203 });
204 }
205 extracted = [];
206 entries.forEach(function(entry) {
207 var fromPath, targetDirname, toPath;
208 fromPath = entry.entryName;
209 if (options.maintainEntryPath) {
210 targetDirname = dirname(entry.entryName);
211 if (cdRegex !== null) {
212 targetDirname = targetDirname.replace(cdRegex, '');
213 }
214 toPath = join(options.to, targetDirname);
215 } else {
216 toPath = options.to;
217 }
218 extracted.push({
219 from: fromPath,
220 to: toPath
221 });
222 return zip.extractEntryTo(fromPath, toPath, false, options.overwrite);
223 });
224 if (typeof callback === 'function') {
225 return callback(extracted);
226 }
227 };
228
229 File.prototype.extract = function(options, callback) {
230 var thisClass;
231 thisClass = this;
232 return thisClass._ee.on('create', function() {
233 return thisClass._stream.on('finish', thisClass._extractOnFinish.bind(thisClass, options, callback));
234 });
235 };
236
237 File.prototype._executeOnFinish = function(options) {
238 var args;
239 if (options instanceof Array) {
240 args = options;
241 options = {};
242 } else if (typeof options === 'object') {
243 if (options.hasOwnProperty('args')) {
244 args = options.args;
245 }
246 } else {
247 options = options != null ? options : {};
248 }
249 delete options.args;
250 return execFile(this._file, args, options);
251 };
252
253 File.prototype.execute = function(options) {
254 var thisClass;
255 thisClass = this;
256 return thisClass._ee.on('create', function() {
257 return thisClass._stream.on('finish', thisClass._executeOnFinish.bind(thisClass, options));
258 });
259 };
260
261 return File;
262
263})();
264
265module.exports = File;