@mherod/get-cookie 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/cli.js +89 -0
  2. package/index.js +49 -185
  3. package/package.json +2 -2
  4. package/utils.js +76 -0
package/cli.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+
3
+ const {getFirefoxCookie, getChromeCookie} = require("./index");
4
+ const {printStringValue} = require("./utils");
5
+
6
+ if (process.argv) {
7
+ if (process.argv.length > 2) {
8
+ const name = process.argv[2];
9
+ const domain = process.argv[3] ?? '%';
10
+
11
+ if (process.argv.includes('--verbose')) {
12
+ process.env.VERBOSE = "true";
13
+ }
14
+ if (process.argv.includes("--chrome-only")) {
15
+ process.env.CHROME_ONLY = "true";
16
+ }
17
+ if (process.argv.includes("--firefox-only")) {
18
+ process.env.FIREFOX_ONLY = "true";
19
+ }
20
+ if (process.argv.includes("--ignore-expired")) {
21
+ process.env.IGNORE_EXPIRED = "true";
22
+ }
23
+
24
+ if (process.env.VERBOSE) {
25
+ console.log("Verbose mode", process.argv);
26
+ }
27
+
28
+ if (process.env.CHROME_ONLY) {
29
+ if (process.env.VERBOSE) {
30
+ console.log('chrome only');
31
+ }
32
+ getChromeCookie({name, domain})
33
+ .then(cookie => {
34
+ if (cookie && cookie.length > 0) {
35
+ printStringValue(cookie);
36
+ } else {
37
+ console.log('No cookie found');
38
+ }
39
+ })
40
+ .catch(err => {
41
+ if (process.env.VERBOSE) {
42
+ console.error(err);
43
+ }
44
+ });
45
+ } else if (process.env.FIREFOX_ONLY) {
46
+ if (process.env.VERBOSE) {
47
+ console.log('firefox only');
48
+ }
49
+ getFirefoxCookie({name, domain})
50
+ .then(cookie => {
51
+ if (cookie && cookie.length > 0) {
52
+ printStringValue(cookie);
53
+ } else {
54
+ console.log('No cookie found');
55
+ }
56
+ })
57
+ .catch(err => {
58
+ if (process.env.VERBOSE) {
59
+ console.error("Error getting Firefox cookie", err);
60
+ }
61
+ });
62
+ } else {
63
+ getChromeCookie({name, domain})
64
+ .catch(err => {
65
+ if (process.env.VERBOSE) {
66
+ console.error("Error getting Chrome cookie", err);
67
+ }
68
+ })
69
+ .then(r => {
70
+ if (typeof r === 'string' && r.trim().length > 0) {
71
+ return r;
72
+ } else {
73
+ return getFirefoxCookie({name, domain})
74
+ .catch(err => {
75
+ if (process.env.VERBOSE) {
76
+ console.error("Error getting Firefox cookie", err);
77
+ }
78
+ });
79
+ }
80
+ })
81
+ .catch((e) => {
82
+ if (process.env.VERBOSE) {
83
+ console.error("Error getting Chrome or Firefox cookie", e);
84
+ }
85
+ })
86
+ .then(printStringValue);
87
+ }
88
+ }
89
+ }
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const crypto = require('crypto');
4
- const {exec} = require("child_process");
5
4
  const fs = require("fs");
5
+ const {execSimple} = require("./utils");
6
6
 
7
7
  if (process.platform !== 'darwin') {
8
8
  throw new Error('This script only works on macOS');
@@ -13,20 +13,7 @@ if (process.platform !== 'darwin') {
13
13
  * @returns {Promise<string>}
14
14
  */
15
15
  async function getChromePassword() {
16
- return await new Promise((resolve, reject) => {
17
- exec("security find-generic-password -w -s \"Chrome Safe Storage\"", (error, stdout, stderr) => {
18
- if (error) {
19
- reject(error);
20
- return;
21
- }
22
- if (stderr) {
23
- reject(error);
24
- return;
25
- }
26
- let s = stdout.toString().trim();
27
- resolve(s);
28
- });
29
- });
16
+ return await execSimple("security find-generic-password -w -s \"Chrome Safe Storage\"");
30
17
  }
31
18
 
32
19
  async function getCookie(name, domain) {
@@ -46,8 +33,11 @@ async function getFirefoxCookie({name, domain}) {
46
33
  if (domain && typeof domain !== 'string') {
47
34
  throw new Error('domain must be a string');
48
35
  }
49
- const file = await findFile(`${process.env.HOME}/Library/Application Support/Firefox/Profiles`, "cookies.sqlite")
50
- if (!fs.existsSync(file)) {
36
+ const [file] = await findAllFiles({
37
+ path: `${process.env.HOME}/Library/Application Support/Firefox/Profiles`,
38
+ name: "cookies.sqlite"
39
+ })
40
+ if (file && !fs.existsSync(file)) {
51
41
  throw new Error(`File ${file} does not exist`);
52
42
  }
53
43
  if (process.env.VERBOSE) {
@@ -134,33 +124,6 @@ async function doSqliteQuery1(file, sql) {
134
124
  });
135
125
  }
136
126
 
137
- async function doSqliteQuery(file, sql) {
138
- const command = `sqlite3 "${file}" "${sql}"`;
139
- if (process.env.VERBOSE) {
140
- console.log(command);
141
- }
142
- return await new Promise((resolve, reject) => {
143
- exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
144
- if (error) {
145
- reject(error);
146
- return;
147
- }
148
- if (stderr) {
149
- reject(error);
150
- return;
151
- }
152
- let stdoutAsBuffer = stdout;
153
- if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
154
- // noinspection JSCheckFunctionSignatures
155
- stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
156
- }
157
- if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
158
- resolve(stdoutAsBuffer);
159
- }
160
- });
161
- });
162
- }
163
-
164
127
  /**
165
128
  *
166
129
  * @param {string} password
@@ -213,8 +176,8 @@ async function decrypt(password, encryptedData) {
213
176
  return;
214
177
  }
215
178
 
216
- let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
217
- // let decoded = decipher.update(encryptedData);
179
+ // let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
180
+ let decoded = decipher.update(encryptedData);
218
181
  try {
219
182
  decipher.final('utf-8');
220
183
  } catch (e) {
@@ -242,28 +205,38 @@ async function decrypt(password, encryptedData) {
242
205
  /**
243
206
  *
244
207
  * @param {string|undefined} name
245
- * @param {string|undefined} domain
208
+ * @param {string} domain
246
209
  * @returns {Promise<string>}
247
210
  */
248
- async function getChromeCookie({name, domain}) {
211
+ async function getChromeCookie({name, domain = '%'}) {
249
212
  if (name && typeof name !== 'string') {
250
213
  throw new Error('name must be a string');
251
214
  }
252
- if (domain && typeof domain !== 'string') {
215
+ if (typeof domain !== 'string') {
253
216
  throw new Error('domain must be a string');
254
217
  }
255
218
  const chromePasswordPromise = getChromePassword();
256
- const [encryptedData] = await findAllFiles({
219
+ const encryptedDataItems = await findAllFiles({
257
220
  path: defaultChromeRoot,
258
221
  name: 'Cookies'
259
222
  }).then(files => {
260
- const promise = Promise.all(files.map(file => {
223
+ const promises = files.map(file => {
261
224
  return getEncryptedChromeCookie({
262
225
  name: name,
263
226
  domain: domain,
264
227
  file: file
228
+ }).catch(e => {
229
+ if (process.env.VERBOSE) {
230
+ console.log("Error getting encrypted cookie", e);
231
+ }
232
+ return null;
233
+ });
234
+ });
235
+ const promise = Promise.all(promises).then(results => {
236
+ return results.filter(result => {
237
+ return result;
265
238
  });
266
- }));
239
+ });
267
240
  if (process.env.VERBOSE) {
268
241
  console.log('promise', promise);
269
242
  }
@@ -275,22 +248,32 @@ async function getChromeCookie({name, domain}) {
275
248
  return [];
276
249
  });
277
250
  const password = await chromePasswordPromise;
278
- if (process.env.VERBOSE) {
279
- console.log("Received encrypted", encryptedData);
280
- }
281
- let s;
282
- try {
283
- s = await decrypt(password, encryptedData);
284
- } catch (e) {
251
+ const decrypted = encryptedDataItems.filter(encryptedData => {
252
+ return encryptedData != null && encryptedData.length > 0;
253
+ }).map(async encryptedData => {
285
254
  if (process.env.VERBOSE) {
286
- console.error("Error decrypting", e);
255
+ console.log("Received encrypted", encryptedData);
287
256
  }
288
- throw new Error('Failed to decrypt');
289
- }
290
- if (process.env.VERBOSE) {
291
- console.log("Decrypted", s);
292
- }
293
- return s;
257
+ let decrypted;
258
+ try {
259
+ decrypted = await decrypt(password, encryptedData);
260
+ } catch (e) {
261
+ if (process.env.VERBOSE) {
262
+ console.log("Error decrypting cookie", e);
263
+ }
264
+ return null;
265
+ }
266
+ if (decrypted) {
267
+ if (process.env.VERBOSE) {
268
+ console.log("Decrypted", decrypted);
269
+ }
270
+ return decrypted;
271
+ }
272
+ return null;
273
+ });
274
+ return await Promise.all(decrypted).then(results => {
275
+ return results.find(result => typeof result === 'string' && result.length > 0);
276
+ });
294
277
  }
295
278
 
296
279
  /**
@@ -361,40 +344,6 @@ async function findAllFiles({path, name, rootSegments = path.split('/').length,
361
344
  return files;
362
345
  }
363
346
 
364
- /**
365
- *
366
- * @param path
367
- * @param name
368
- * @returns {Promise<string>}
369
- */
370
- async function findFile(path, name) {
371
- return await new Promise((resolve, reject) => {
372
- for (const file of fs.readdirSync(path)) {
373
- const filePath = path + '/' + file;
374
- const stat = fs.statSync(filePath);
375
- if (stat.isDirectory()) {
376
- findFile(filePath, name).then(resolve).catch(reject);
377
- } else if (file === name) {
378
- resolve(filePath);
379
- }
380
- }
381
- });
382
- }
383
-
384
- function printStringValue(r) {
385
- if (process.env.VERBOSE) {
386
- console.log("Printing value", r);
387
- }
388
- if (r) {
389
- if (typeof r === 'string') {
390
- console.log(r);
391
- } else if (r.toString) {
392
- // noinspection JSCheckFunctionSignatures
393
- console.log(r.toString('utf8'));
394
- }
395
- }
396
- }
397
-
398
347
  // noinspection JSUnusedGlobalSymbols
399
348
  module.exports = {
400
349
  getDecryptedCookie: getChromeCookie,
@@ -402,88 +351,3 @@ module.exports = {
402
351
  getFirefoxCookie,
403
352
  getCookie
404
353
  };
405
-
406
- if (process.argv) {
407
- if (process.argv.length > 2) {
408
- const name = process.argv[2];
409
- const domain = process.argv[3] ?? '%';
410
-
411
- if (process.argv.includes('--verbose')) {
412
- process.env.VERBOSE = "true";
413
- }
414
- if (process.argv.includes("--chrome-only")) {
415
- process.env.CHROME_ONLY = "true";
416
- }
417
- if (process.argv.includes("--firefox-only")) {
418
- process.env.FIREFOX_ONLY = "true";
419
- }
420
- if (process.argv.includes("--ignore-expired")) {
421
- process.env.IGNORE_EXPIRED = "true";
422
- }
423
-
424
- if (process.env.VERBOSE) {
425
- console.log("Verbose mode", process.argv);
426
- }
427
-
428
- if (process.env.CHROME_ONLY) {
429
- if (process.env.VERBOSE) {
430
- console.log('chrome only');
431
- }
432
- getChromeCookie({name, domain})
433
- .then(cookie => {
434
- if (cookie && cookie.length > 0) {
435
- printStringValue(cookie);
436
- } else {
437
- console.log('No cookie found');
438
- }
439
- })
440
- .catch(err => {
441
- if (process.env.VERBOSE) {
442
- console.error(err);
443
- }
444
- });
445
- } else if (process.env.FIREFOX_ONLY) {
446
- if (process.env.VERBOSE) {
447
- console.log('firefox only');
448
- }
449
- getFirefoxCookie({name, domain})
450
- .then(cookie => {
451
- if (cookie && cookie.length > 0) {
452
- printStringValue(cookie);
453
- } else {
454
- console.log('No cookie found');
455
- }
456
- })
457
- .catch(err => {
458
- if (process.env.VERBOSE) {
459
- console.error("Error getting Firefox cookie", err);
460
- }
461
- });
462
- } else {
463
- getChromeCookie({name, domain})
464
- .catch(err => {
465
- if (process.env.VERBOSE) {
466
- console.error("Error getting Chrome cookie", err);
467
- }
468
- })
469
- .then(r => {
470
- if (typeof r === 'string' && r.trim().length > 0) {
471
- return r;
472
- } else {
473
- return getFirefoxCookie({name, domain})
474
- .catch(err => {
475
- if (process.env.VERBOSE) {
476
- console.error("Error getting Firefox cookie", err);
477
- }
478
- });
479
- }
480
- })
481
- .catch((e) => {
482
- if (process.env.VERBOSE) {
483
- console.error("Error getting Chrome or Firefox cookie", e);
484
- }
485
- })
486
- .then(printStringValue);
487
- }
488
- }
489
- }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "Node.js module for querying a local user's Chrome cookie",
5
5
  "main": "index.js",
6
- "bin": "index.js",
6
+ "bin": "cli.js",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
package/utils.js ADDED
@@ -0,0 +1,76 @@
1
+ // noinspection JSUnusedGlobalSymbols
2
+
3
+ const {exec} = require('child_process');
4
+
5
+ async function execSimple(command) {
6
+ if (typeof command !== 'string') {
7
+ throw new TypeError('execSimple: command must be a string');
8
+ }
9
+ if (process.env.VERBOSE) {
10
+ console.log(command);
11
+ }
12
+ return await new Promise((resolve, reject) => {
13
+ exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
14
+ if (error) {
15
+ reject(error);
16
+ return;
17
+ }
18
+ if (stderr) {
19
+ reject(error);
20
+ return;
21
+ }
22
+ if (stdout) {
23
+ resolve(stdout.toString('utf8').trim());
24
+ }
25
+ });
26
+ });
27
+ }
28
+
29
+ async function execAsBuffer(command) {
30
+ if (typeof command !== 'string') {
31
+ throw new TypeError('execAsBuffer: command must be a string');
32
+ }
33
+ if (process.env.VERBOSE) {
34
+ console.log(command);
35
+ }
36
+ return await new Promise((resolve, reject) => {
37
+ exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
38
+ if (error) {
39
+ reject(error);
40
+ return;
41
+ }
42
+ if (stderr) {
43
+ reject(error);
44
+ return;
45
+ }
46
+ let stdoutAsBuffer = stdout;
47
+ if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
48
+ // noinspection JSCheckFunctionSignatures
49
+ stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
50
+ }
51
+ if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
52
+ resolve(stdoutAsBuffer);
53
+ }
54
+ });
55
+ });
56
+ }
57
+
58
+ function printStringValue(r) {
59
+ if (process.env.VERBOSE) {
60
+ console.log("Printing value", r);
61
+ }
62
+ if (r) {
63
+ if (typeof r === 'string') {
64
+ console.log(r);
65
+ } else if (r.toString) {
66
+ // noinspection JSCheckFunctionSignatures
67
+ console.log(r.toString('utf8'));
68
+ }
69
+ }
70
+ }
71
+
72
+ module.exports = {
73
+ execSimple: execSimple,
74
+ execAsBuffer: execAsBuffer,
75
+ printStringValue: printStringValue
76
+ };