@mherod/get-cookie 1.0.5 → 1.1.1

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 +116 -96
  2. package/package.json +3 -4
package/index.js CHANGED
@@ -46,51 +46,28 @@ async function getFirefoxCookie({name, domain}) {
46
46
  if (domain && typeof domain !== 'string') {
47
47
  throw new Error('domain must be a string');
48
48
  }
49
- 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")
50
50
  if (!fs.existsSync(file)) {
51
51
  throw new Error(`File ${file} does not exist`);
52
52
  }
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: 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,34 +77,62 @@ 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;
108
- }
109
- if (process.env.VERBOSE) {
110
- console.log(`Trying Chrome cookie ${name} for domain ${domain}`);
111
- }
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 `;
120
- }
121
- }
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}'`;
122
93
  if (typeof domain === 'string') {
123
- sql += `host_key LIKE '${domain}';`;
94
+ sql += ` AND `;
124
95
  }
125
96
  }
126
- const command = `sqlite3 "${file}" "${sql}"`;
127
- if (process.env.VERBOSE) {
128
- console.log(command);
97
+ if (typeof domain === 'string') {
98
+ sql += `host_key LIKE '${domain}';`;
129
99
  }
130
- 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) => {
131
136
  if (error) {
132
137
  reject(error);
133
138
  return;
@@ -166,45 +171,58 @@ async function decrypt(password, encryptedData) {
166
171
  }
167
172
  return await new Promise((resolve, reject) => {
168
173
  crypto.pbkdf2(password, 'saltysalt', 1003, 16, 'sha1', (error, buffer) => {
169
- if (error) {
170
- if (process.env.VERBOSE) {
171
- 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;
172
182
  }
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);
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;
179
189
  }
180
- reject(new Error('Buffer length is not 16'));
181
- return;
182
- }
183
190
 
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);
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);
188
195
 
189
- let decoded = decipher.update(encryptedData, 'binary', 'utf8');
190
- // let decoded = decipher.update(encryptedData);
191
- try {
192
- decipher.final('utf-8');
193
- } catch (e) {
194
- if (process.env.VERBOSE) {
195
- 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;
196
214
  }
197
- reject(e);
198
- return;
199
- }
200
215
 
201
- let padding = decoded[decoded.length - 1];
202
- if (padding) {
203
- 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);
204
225
  }
205
- // noinspection JSCheckFunctionSignatures
206
- decoded = decoded.toString('utf8');
207
- resolve(decoded)
208
226
  });
209
227
  });
210
228
  }
@@ -264,11 +282,13 @@ function printStringValue(r) {
264
282
  if (process.env.VERBOSE) {
265
283
  console.log("Printing value", r);
266
284
  }
267
- if (typeof r === 'string') {
268
- console.log(r);
269
- } else {
270
- // noinspection JSCheckFunctionSignatures
271
- 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
+ }
272
292
  }
273
293
  }
274
294
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mherod/get-cookie",
3
- "version": "1.0.5",
3
+ "version": "1.1.1",
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": "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
  }