@mherod/get-cookie 1.0.4 → 1.1.0

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 (2) hide show
  1. package/index.js +141 -99
  2. package/package.json +3 -4
package/index.js CHANGED
@@ -29,6 +29,10 @@ async function getChromePassword() {
29
29
  });
30
30
  }
31
31
 
32
+ async function getCookie() {
33
+ throw new Error('Not implemented');
34
+ }
35
+
32
36
  /**
33
37
  *
34
38
  * @param name
@@ -42,51 +46,28 @@ async function getFirefoxCookie({name, domain}) {
42
46
  if (domain && typeof domain !== 'string') {
43
47
  throw new Error('domain must be a string');
44
48
  }
45
- const file = await findFile(`${process.env.HOME}/Library/Application Support/Firefox/Profiles/`, "cookies.sqlite")
49
+ const file = await findFile(`${process.env.HOME}/Library/Application Support/Firefox/Profiles`, "cookies.sqlite")
46
50
  if (!fs.existsSync(file)) {
47
51
  throw new Error(`File ${file} does not exist`);
48
52
  }
49
53
  if (process.env.VERBOSE) {
50
54
  console.log(`Trying Firefox cookie ${name} for domain ${domain}`);
51
55
  }
52
- return await new Promise((resolve, reject) => {
53
- let sql;
54
- sql = `SELECT value FROM moz_cookies`;
55
- if (typeof name === 'string' || typeof domain === 'string') {
56
- sql += ` WHERE `;
57
- if (typeof name === 'string') {
58
- sql += `name = '${name}'`;
59
- if (typeof domain === 'string') {
60
- sql += ` AND `;
61
- }
62
- }
56
+ let sql;
57
+ sql = "SELECT value FROM moz_cookies";
58
+ if (typeof name === 'string' || typeof domain === 'string') {
59
+ sql += ` WHERE `;
60
+ if (typeof name === 'string') {
61
+ sql += `name = '${name}'`;
63
62
  if (typeof domain === 'string') {
64
- sql += `host LIKE '${domain}';`;
63
+ sql += ` AND `;
65
64
  }
66
65
  }
67
- const command = `sqlite3 "${file}" "${sql}"`;
68
- if (process.env.VERBOSE) {
69
- console.log(command);
66
+ if (typeof domain === 'string') {
67
+ sql += `host LIKE '${domain}';`;
70
68
  }
71
- exec(command, {encoding: 'binary', maxBuffer: 1024}, (error, stdout, stderr) => {
72
- if (error) {
73
- reject(error);
74
- return;
75
- }
76
- if (stderr) {
77
- reject(error);
78
- return;
79
- }
80
- let stdoutAsBuffer = stdout;
81
- if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
82
- // noinspection JSCheckFunctionSignatures
83
- stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
84
- }
85
- if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
86
- resolve(stdoutAsBuffer);
87
- }
88
- });
89
- });
69
+ }
70
+ return await doSqliteQuery1(file, sql);
90
71
  }
91
72
 
92
73
  async function getEncryptedChromeCookie(name, domain) {
@@ -96,34 +77,62 @@ async function getEncryptedChromeCookie(name, domain) {
96
77
  if (domain && typeof domain !== 'string') {
97
78
  throw new Error('domain must be a string');
98
79
  }
99
- return await new Promise((resolve, reject) => {
100
- const file = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default/Cookies`;
101
- if (!fs.existsSync(file)) {
102
- reject(new Error(`File ${file} does not exist`));
103
- return;
104
- }
105
- if (process.env.VERBOSE) {
106
- console.log(`Trying Chrome cookie ${name} for domain ${domain}`);
107
- }
108
- let sql;
109
- sql = `SELECT encrypted_value FROM cookies`;
110
- if (typeof name === 'string' || typeof domain === 'string') {
111
- sql += ` WHERE `;
112
- if (typeof name === 'string') {
113
- sql += `name = '${name}'`;
114
- if (typeof domain === 'string') {
115
- sql += ` AND `;
116
- }
117
- }
80
+ const file = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default/Cookies`;
81
+ if (!fs.existsSync(file)) {
82
+ throw new Error(`File ${file} does not exist`);
83
+ }
84
+ if (process.env.VERBOSE) {
85
+ console.log(`Trying Chrome cookie ${name} for domain ${domain}`);
86
+ }
87
+ let sql;
88
+ sql = `SELECT encrypted_value FROM cookies`;
89
+ if (typeof name === 'string' || typeof domain === 'string') {
90
+ sql += ` WHERE `;
91
+ if (typeof name === 'string') {
92
+ sql += `name = '${name}'`;
118
93
  if (typeof domain === 'string') {
119
- sql += `host_key LIKE '${domain}';`;
94
+ sql += ` AND `;
120
95
  }
121
96
  }
122
- const command = `sqlite3 "${file}" "${sql}"`;
123
- if (process.env.VERBOSE) {
124
- console.log(command);
97
+ if (typeof domain === 'string') {
98
+ sql += `host_key LIKE '${domain}';`;
125
99
  }
126
- exec(command, {encoding: 'binary', maxBuffer: 1024}, (error, stdout, stderr) => {
100
+ }
101
+ return await doSqliteQuery1(file, sql);
102
+ }
103
+
104
+ async function doSqliteQuery1(file, sql) {
105
+ const sqlite3 = require('sqlite3');
106
+ const db = new sqlite3.Database(file);
107
+ return new Promise((resolve, reject) => {
108
+ db.all(sql, (err, rows) => {
109
+ if (err) {
110
+ reject(err);
111
+ return;
112
+ }
113
+ const rows1 = rows;
114
+ if (rows1.length === 0) {
115
+ resolve(null);
116
+ return;
117
+ }
118
+ if (Array.isArray(rows1)) {
119
+ // noinspection JSCheckFunctionSignatures
120
+ const [value] = rows1.flatMap(row => Object.values(row));
121
+ resolve(value);
122
+ return;
123
+ }
124
+ resolve(rows1);
125
+ });
126
+ });
127
+ }
128
+
129
+ async function doSqliteQuery(file, sql) {
130
+ const command = `sqlite3 "${file}" "${sql}"`;
131
+ if (process.env.VERBOSE) {
132
+ console.log(command);
133
+ }
134
+ return await new Promise((resolve, reject) => {
135
+ exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
127
136
  if (error) {
128
137
  reject(error);
129
138
  return;
@@ -162,45 +171,58 @@ async function decrypt(password, encryptedData) {
162
171
  }
163
172
  return await new Promise((resolve, reject) => {
164
173
  crypto.pbkdf2(password, 'saltysalt', 1003, 16, 'sha1', (error, buffer) => {
165
- if (error) {
166
- if (process.env.VERBOSE) {
167
- console.log("Error doing pbkdf2", error);
174
+ try {
175
+
176
+ if (error) {
177
+ if (process.env.VERBOSE) {
178
+ console.log("Error doing pbkdf2", error);
179
+ }
180
+ reject(error);
181
+ return;
168
182
  }
169
- reject(error);
170
- return;
171
- }
172
- if (buffer.length !== 16) {
173
- if (process.env.VERBOSE) {
174
- console.log("Error doing pbkdf2, buffer length is not 16", buffer.length);
183
+ if (buffer.length !== 16) {
184
+ if (process.env.VERBOSE) {
185
+ console.log("Error doing pbkdf2, buffer length is not 16", buffer.length);
186
+ }
187
+ reject(new Error('Buffer length is not 16'));
188
+ return;
175
189
  }
176
- reject(new Error('Buffer length is not 16'));
177
- return;
178
- }
179
190
 
180
- const iv = new Buffer.from(new Array(17).join(' '), 'binary');
181
- const decipher = crypto.createDecipheriv('aes-128-cbc', buffer, iv);
182
- decipher.setAutoPadding(false);
183
- encryptedData = encryptedData.slice(3);
191
+ const iv = new Buffer.from(new Array(17).join(' '), 'binary');
192
+ const decipher = crypto.createDecipheriv('aes-128-cbc', buffer, iv);
193
+ decipher.setAutoPadding(false);
194
+ encryptedData = encryptedData.slice(3);
184
195
 
185
- let decoded = decipher.update(encryptedData, 'binary', 'utf8');
186
- // let decoded = decipher.update(encryptedData);
187
- try {
188
- decipher.final('utf-8');
189
- } catch (e) {
190
- if (process.env.VERBOSE) {
191
- console.log("Error doing decipher.final()", e);
196
+ if (encryptedData.length % 16 !== 0) {
197
+ if (process.env.VERBOSE) {
198
+ console.log("Error doing pbkdf2, encryptedData length is not a multiple of 16", encryptedData.length);
199
+ }
200
+ reject(new Error('encryptedData length is not a multiple of 16'));
201
+ return;
202
+ }
203
+
204
+ let decoded = decipher.update(encryptedData, 'binary', 'utf8');
205
+ // let decoded = decipher.update(encryptedData);
206
+ try {
207
+ decipher.final('utf-8');
208
+ } catch (e) {
209
+ if (process.env.VERBOSE) {
210
+ console.log("Error doing decipher.final()", e);
211
+ }
212
+ reject(e);
213
+ return;
192
214
  }
193
- reject(e);
194
- return;
195
- }
196
215
 
197
- let padding = decoded[decoded.length - 1];
198
- if (padding) {
199
- decoded = decoded.slice(0, decoded.length - padding);
216
+ let padding = decoded[decoded.length - 1];
217
+ if (padding) {
218
+ decoded = decoded.slice(0, 0 - padding);
219
+ }
220
+ // noinspection JSCheckFunctionSignatures
221
+ decoded = decoded.toString('utf8');
222
+ resolve(decoded);
223
+ } catch (e) {
224
+ reject(e);
200
225
  }
201
- // noinspection JSCheckFunctionSignatures
202
- decoded = decoded.toString('utf8');
203
- resolve(decoded)
204
226
  });
205
227
  });
206
228
  }
@@ -260,18 +282,22 @@ function printStringValue(r) {
260
282
  if (process.env.VERBOSE) {
261
283
  console.log("Printing value", r);
262
284
  }
263
- if (typeof r === 'string') {
264
- console.log(r);
265
- } else {
266
- // noinspection JSCheckFunctionSignatures
267
- console.log(r.toString('utf8'));
285
+ if (r) {
286
+ if (typeof r === 'string') {
287
+ console.log(r);
288
+ } else if (r.toString) {
289
+ // noinspection JSCheckFunctionSignatures
290
+ console.log(r.toString('utf8'));
291
+ }
268
292
  }
269
293
  }
270
294
 
271
295
  // noinspection JSUnusedGlobalSymbols
272
296
  module.exports = {
273
297
  getDecryptedCookie: getChromeCookie,
274
- getChromeCookie
298
+ getChromeCookie,
299
+ getFirefoxCookie,
300
+ getCookie
275
301
  };
276
302
 
277
303
  if (process.argv) {
@@ -292,12 +318,22 @@ if (process.argv) {
292
318
  process.env.IGNORE_EXPIRED = "true";
293
319
  }
294
320
 
321
+ if (process.env.VERBOSE) {
322
+ console.log("Verbose mode", process.argv);
323
+ }
324
+
295
325
  if (process.env.CHROME_ONLY) {
296
326
  if (process.env.VERBOSE) {
297
327
  console.log('chrome only');
298
328
  }
299
329
  getChromeCookie({name, domain})
300
- .then(printStringValue)
330
+ .then(cookie => {
331
+ if (cookie && cookie.length > 0) {
332
+ printStringValue(cookie);
333
+ } else {
334
+ console.log('No cookie found');
335
+ }
336
+ })
301
337
  .catch(err => {
302
338
  if (process.env.VERBOSE) {
303
339
  console.error(err);
@@ -308,7 +344,13 @@ if (process.argv) {
308
344
  console.log('firefox only');
309
345
  }
310
346
  getFirefoxCookie({name, domain})
311
- .then(printStringValue)
347
+ .then(cookie => {
348
+ if (cookie && cookie.length > 0) {
349
+ printStringValue(cookie);
350
+ } else {
351
+ console.log('No cookie found');
352
+ }
353
+ })
312
354
  .catch(err => {
313
355
  if (process.env.VERBOSE) {
314
356
  console.error("Error getting Firefox cookie", err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Node.js module for querying a local user's Chrome cookie",
5
5
  "main": "index.js",
6
6
  "bin": "index.js",
@@ -9,13 +9,12 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "echo \"Error: no test specified\" && exit 1",
12
- "installForHomebrew": "pkg . --target host --out-path $HOMEBREW_FORMULA_PREFIX/bin/ --debug",
13
- "installForMac": "pkg . --target node17-macos-x64 --out-path /usr/local/bin/ --debug",
14
- "installForHost": "pkg . --target host --out-path /usr/local/bin/ --debug"
12
+ "install": "npm install --force --global ."
15
13
  },
16
14
  "keywords": [],
17
15
  "author": "Matthew Herod",
18
16
  "license": "ISC",
19
17
  "dependencies": {
18
+ "sqlite3": "^5.0.8"
20
19
  }
21
20
  }