@mherod/get-cookie 1.0.6 → 1.1.2

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 +122 -101
  2. package/package.json +3 -4
package/index.js CHANGED
@@ -53,44 +53,21 @@ async function getFirefoxCookie({name, domain}) {
53
53
  if (process.env.VERBOSE) {
54
54
  console.log(`Trying Firefox cookie ${name} for domain ${domain}`);
55
55
  }
56
- return await new Promise((resolve, reject) => {
57
- let sql;
58
- sql = "SELECT value FROM moz_cookies";
59
- if (typeof name === 'string' || typeof domain === 'string') {
60
- sql += ` WHERE `;
61
- if (typeof name === 'string') {
62
- sql += `name = '${name}'`;
63
- if (typeof domain === 'string') {
64
- sql += ` AND `;
65
- }
66
- }
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}'`;
67
62
  if (typeof domain === 'string') {
68
- sql += `host LIKE '${domain}';`;
63
+ sql += ` AND `;
69
64
  }
70
65
  }
71
- const command = `sqlite3 "${file}" "${sql}"`;
72
- if (process.env.VERBOSE) {
73
- console.log(command);
66
+ if (typeof domain === 'string') {
67
+ sql += `host LIKE '${domain}';`;
74
68
  }
75
- exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
76
- if (error) {
77
- reject(error);
78
- return;
79
- }
80
- if (stderr) {
81
- reject(error);
82
- return;
83
- }
84
- let stdoutAsBuffer = stdout;
85
- if (typeof stdoutAsBuffer === 'string' && stdoutAsBuffer.length > 0) {
86
- // noinspection JSCheckFunctionSignatures
87
- stdoutAsBuffer = Buffer.from(stdoutAsBuffer, 'binary').slice(0, -1);
88
- }
89
- if (stdoutAsBuffer && stdoutAsBuffer.length > 0) {
90
- resolve(stdoutAsBuffer);
91
- }
92
- });
93
- });
69
+ }
70
+ return await doSqliteQuery1(file, sql);
94
71
  }
95
72
 
96
73
  async function getEncryptedChromeCookie(name, domain) {
@@ -100,33 +77,64 @@ async function getEncryptedChromeCookie(name, domain) {
100
77
  if (domain && typeof domain !== 'string') {
101
78
  throw new Error('domain must be a string');
102
79
  }
103
- return await new Promise((resolve, reject) => {
104
- const file = `${process.env.HOME}/Library/Application Support/Google/Chrome/Default/Cookies`;
105
- if (!fs.existsSync(file)) {
106
- reject(new Error(`File ${file} does not exist`));
107
- return;
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}'`;
93
+ if (typeof domain === 'string') {
94
+ sql += ` AND `;
95
+ }
108
96
  }
109
- if (process.env.VERBOSE) {
110
- console.log(`Trying Chrome cookie ${name} for domain ${domain}`);
97
+ if (typeof domain === 'string') {
98
+ sql += `host_key LIKE '${domain}';`;
111
99
  }
112
- let sql;
113
- sql = `SELECT encrypted_value FROM cookies`;
114
- if (typeof name === 'string' || typeof domain === 'string') {
115
- sql += ` WHERE `;
116
- if (typeof name === 'string') {
117
- sql += `name = '${name}'`;
118
- if (typeof domain === 'string') {
119
- sql += ` AND `;
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
+ if (process.env.VERBOSE) {
116
+ console.log(`No rows found`);
120
117
  }
118
+ resolve(null);
119
+ return;
121
120
  }
122
- if (typeof domain === 'string') {
123
- sql += `host_key LIKE '${domain}';`;
121
+ if (Array.isArray(rows1)) {
122
+ // noinspection JSCheckFunctionSignatures
123
+ const [value] = rows1.flatMap(row => Object.values(row));
124
+ resolve(Buffer.from(value));
125
+ return;
124
126
  }
125
- }
126
- const command = `sqlite3 "${file}" "${sql}"`;
127
- if (process.env.VERBOSE) {
128
- console.log(command);
129
- }
127
+ resolve(rows1);
128
+ });
129
+ });
130
+ }
131
+
132
+ async function doSqliteQuery(file, sql) {
133
+ const command = `sqlite3 "${file}" "${sql}"`;
134
+ if (process.env.VERBOSE) {
135
+ console.log(command);
136
+ }
137
+ return await new Promise((resolve, reject) => {
130
138
  exec(command, {encoding: 'binary', maxBuffer: 5 * 1024}, (error, stdout, stderr) => {
131
139
  if (error) {
132
140
  reject(error);
@@ -156,63 +164,72 @@ async function getEncryptedChromeCookie(name, domain) {
156
164
  */
157
165
  async function decrypt(password, encryptedData) {
158
166
  if (typeof password !== 'string') {
159
- throw new Error('password must be a string');
167
+ throw new Error('password must be a string: ' + password);
160
168
  }
161
- if (typeof encryptedData !== 'object') {
162
- throw new Error('encryptedData must be a object');
169
+ const encryptedData1 = encryptedData;
170
+ if (encryptedData1 == null || typeof encryptedData1 !== 'object') {
171
+ throw new Error('encryptedData must be a object: ' + encryptedData1);
163
172
  }
164
173
  if (process.env.VERBOSE) {
165
174
  console.log(`Trying to decrypt with password ${password}`);
166
175
  }
167
176
  return await new Promise((resolve, reject) => {
168
177
  crypto.pbkdf2(password, 'saltysalt', 1003, 16, 'sha1', (error, buffer) => {
169
- if (error) {
170
- if (process.env.VERBOSE) {
171
- console.log("Error doing pbkdf2", error);
178
+ try {
179
+ if (error) {
180
+ if (process.env.VERBOSE) {
181
+ console.log("Error doing pbkdf2", error);
182
+ }
183
+ reject(error);
184
+ return;
172
185
  }
173
- reject(error);
174
- return;
175
- }
176
- if (buffer.length !== 16) {
177
- if (process.env.VERBOSE) {
178
- console.log("Error doing pbkdf2, buffer length is not 16", buffer.length);
186
+
187
+ if (buffer.length !== 16) {
188
+ if (process.env.VERBOSE) {
189
+ console.log("Error doing pbkdf2, buffer length is not 16", buffer.length);
190
+ }
191
+ reject(new Error('Buffer length is not 16'));
192
+ return;
179
193
  }
180
- reject(new Error('Buffer length is not 16'));
181
- return;
182
- }
183
194
 
184
- const iv = new Buffer.from(new Array(17).join(' '), 'binary');
185
- const decipher = crypto.createDecipheriv('aes-128-cbc', buffer, iv);
186
- decipher.setAutoPadding(false);
187
- encryptedData = encryptedData.slice(3);
195
+ const iv = new Buffer.from(new Array(17).join(' '), 'binary');
196
+ const decipher = crypto.createDecipheriv('aes-128-cbc', buffer, iv);
197
+ decipher.setAutoPadding(false);
188
198
 
189
- if (encryptedData.length % 16 !== 0) {
190
- if (process.env.VERBOSE) {
191
- console.log("Error doing pbkdf2, encryptedData length is not a multiple of 16", encryptedData.length);
199
+ if (encryptedData1 && encryptedData1.slice) {
200
+ encryptedData = encryptedData1.slice(3);
192
201
  }
193
- reject(new Error('encryptedData length is not a multiple of 16'));
194
- return;
195
- }
196
202
 
197
- let decoded = decipher.update(encryptedData, 'binary', 'utf8');
198
- // let decoded = decipher.update(encryptedData);
199
- try {
200
- decipher.final('utf-8');
201
- } catch (e) {
202
- if (process.env.VERBOSE) {
203
- console.log("Error doing decipher.final()", e);
203
+ if (encryptedData1.length % 16 !== 0) {
204
+ if (process.env.VERBOSE) {
205
+ console.log("Error doing pbkdf2, encryptedData length is not a multiple of 16", encryptedData1.length);
206
+ }
207
+ reject(new Error('encryptedData length is not a multiple of 16'));
208
+ return;
204
209
  }
205
- reject(e);
206
- return;
207
- }
208
210
 
209
- let padding = decoded[decoded.length - 1];
210
- if (padding) {
211
- decoded = decoded.slice(0, decoded.length - padding);
211
+ let decoded = decipher.update(encryptedData1, 'binary', 'utf8');
212
+ // let decoded = decipher.update(encryptedData);
213
+ try {
214
+ decipher.final('utf-8');
215
+ } catch (e) {
216
+ if (process.env.VERBOSE) {
217
+ console.log("Error doing decipher.final()", e);
218
+ }
219
+ reject(e);
220
+ return;
221
+ }
222
+
223
+ let padding = decoded[decoded.length - 1];
224
+ if (padding) {
225
+ decoded = decoded.slice(0, 0 - padding);
226
+ }
227
+ // noinspection JSCheckFunctionSignatures
228
+ decoded = decoded.toString('utf8');
229
+ resolve(decoded);
230
+ } catch (e) {
231
+ reject(e);
212
232
  }
213
- // noinspection JSCheckFunctionSignatures
214
- decoded = decoded.toString('utf8');
215
- resolve(decoded)
216
233
  });
217
234
  });
218
235
  }
@@ -230,8 +247,10 @@ async function getChromeCookie({name, domain}) {
230
247
  if (domain && typeof domain !== 'string') {
231
248
  throw new Error('domain must be a string');
232
249
  }
233
- const password = await getChromePassword();
234
- const encryptedData = await getEncryptedChromeCookie(name, domain);
250
+ const chromePasswordPromise = getChromePassword();
251
+ const encryptedChromeCookiePromise = getEncryptedChromeCookie(name, domain);
252
+ const password = await chromePasswordPromise;
253
+ const encryptedData = await encryptedChromeCookiePromise;
235
254
  if (process.env.VERBOSE) {
236
255
  console.log("Received encrypted", encryptedData);
237
256
  }
@@ -239,7 +258,9 @@ async function getChromeCookie({name, domain}) {
239
258
  try {
240
259
  s = await decrypt(password, encryptedData);
241
260
  } catch (e) {
242
- console.error(e);
261
+ if (process.env.VERBOSE) {
262
+ console.error("Error decrypting", e);
263
+ }
243
264
  throw new Error('Failed to decrypt');
244
265
  }
245
266
  if (process.env.VERBOSE) {
@@ -293,7 +314,7 @@ module.exports = {
293
314
  if (process.argv) {
294
315
  if (process.argv.length > 2) {
295
316
  const name = process.argv[2];
296
- const domain = process.argv[3];
317
+ const domain = process.argv[3] ?? '%';
297
318
 
298
319
  if (process.argv.includes('--verbose')) {
299
320
  process.env.VERBOSE = "true";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "1.0.6",
3
+ "version": "1.1.2",
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
+ "installGlobal": "rm -rf /usr/local/bin/get-cookie ; 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
  }