@mherod/get-cookie 2.1.3 → 4.0.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.
- package/.husky/commit-msg +2 -0
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/README.md +163 -18
- package/commitlint.config.js +12 -0
- package/dist/chunk-56Z35D5R.js +2 -0
- package/dist/chunk-56Z35D5R.js.map +1 -0
- package/dist/chunk-5FUMK7M3.js +4 -0
- package/dist/chunk-5FUMK7M3.js.map +1 -0
- package/dist/chunk-5ZT2G45S.js +2 -0
- package/dist/chunk-5ZT2G45S.js.map +1 -0
- package/dist/chunk-FR2MKDHT.js +2 -0
- package/dist/chunk-FR2MKDHT.js.map +1 -0
- package/dist/chunk-HMKSQBDC.js +2 -0
- package/dist/chunk-HMKSQBDC.js.map +1 -0
- package/dist/chunk-VMBA4NVU.js +2 -0
- package/dist/chunk-VMBA4NVU.js.map +1 -0
- package/dist/chunk-W3JALMAX.js +2 -0
- package/dist/chunk-W3JALMAX.js.map +1 -0
- package/dist/cli.cjs +19 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/getChromeCookie-4ZWACG6M.js +2 -0
- package/dist/getChromeCookie-4ZWACG6M.js.map +1 -0
- package/dist/getChromePassword-GTIXL733.js +2 -0
- package/dist/getChromePassword-GTIXL733.js.map +1 -0
- package/dist/getCookie-43FKMQEZ.js +2 -0
- package/dist/getCookie-43FKMQEZ.js.map +1 -0
- package/dist/getFirefoxCookie-OJYYZFZP.js +2 -0
- package/dist/getFirefoxCookie-OJYYZFZP.js.map +1 -0
- package/dist/getGroupedRenderedCookies-P5VZXZUC.js +2 -0
- package/dist/getGroupedRenderedCookies-P5VZXZUC.js.map +1 -0
- package/dist/getMergedRenderedCookies-C6TXK2I4.js +2 -0
- package/dist/getMergedRenderedCookies-C6TXK2I4.js.map +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +252 -0
- package/dist/index.d.ts +252 -0
- package/dist/index.js +2 -24712
- package/dist/index.js.map +1 -0
- package/eslint.config.js +243 -0
- package/jest.setup.js +11 -0
- package/package.json +87 -36
- package/tsconfig.build.json +9 -0
- package/tsup.cli.ts +27 -0
- package/tsup.config.ts +27 -0
- package/tsup.lib.ts +27 -0
- package/typedoc.json +22 -0
- package/.parcelrc +0 -7
- package/.prettierignore +0 -5
- package/.prettierrc +0 -12
- package/.terserrc +0 -26
- package/build-indexes.ts +0 -108
- package/bun.lockb +0 -0
- package/dist/cli.js +0 -18319
- package/dist/types.d.ts +0 -361
- package/jest.config.ts +0 -14
- package/package-lock.json +0 -5608
- package/src/CookieRow.ts +0 -43
- package/src/CookieSpec.ts +0 -42
- package/src/ExportedCookie.ts +0 -19
- package/src/FetchResponse.ts +0 -13
- package/src/SpecialCases.ts +0 -15
- package/src/StringToRegex.ts +0 -16
- package/src/argv.ts +0 -30
- package/src/browsers/CompositeCookieQueryStrategy.ts +0 -76
- package/src/browsers/CookieQueryStrategy.ts +0 -7
- package/src/browsers/CookieStoreQueryStrategy.ts +0 -115
- package/src/browsers/QuerySqliteThenTransform.ts +0 -48
- package/src/browsers/chrome/ChromeApplicationSupport.ts +0 -14
- package/src/browsers/chrome/ChromeCookieQueryStrategy.ts +0 -158
- package/src/browsers/chrome/decrypt.ts +0 -154
- package/src/browsers/chrome/getChromePassword.ts +0 -28
- package/src/browsers/firefox/FirefoxCookieQueryStrategy.ts +0 -109
- package/src/browsers/getEncryptedChromeCookie.ts +0 -122
- package/src/browsers/index.ts +0 -12
- package/src/browsers/mock/MockCookieQueryStrategy.ts +0 -22
- package/src/browsers/safari/SafariCookieQueryStrategy.ts +0 -42
- package/src/cli.ts +0 -94
- package/src/cliQueryCookies.ts +0 -65
- package/src/comboQueryCookieSpec.test.ts +0 -92
- package/src/comboQueryCookieSpec.ts +0 -26
- package/src/cookieQueryOptions.ts +0 -27
- package/src/cookieSpecsFromUrl.test.ts +0 -65
- package/src/cookieSpecsFromUrl.ts +0 -73
- package/src/decodeBinaryCookies.ts +0 -72
- package/src/execSimple.ts +0 -12
- package/src/fetchWithCookies.test.ts +0 -32
- package/src/fetchWithCookies.ts +0 -217
- package/src/findAllFiles.ts +0 -48
- package/src/getChromeCookie.ts +0 -19
- package/src/getCookie.ts +0 -22
- package/src/getFirefoxCookie.ts +0 -25
- package/src/getGroupedRenderedCookies.ts +0 -42
- package/src/getMergedRenderedCookies.test.ts +0 -43
- package/src/getMergedRenderedCookies.ts +0 -19
- package/src/global.ts +0 -8
- package/src/index.ts +0 -16
- package/src/isValidJwt.ts +0 -26
- package/src/listChromeProfiles.ts +0 -53
- package/src/logger.ts +0 -12
- package/src/processBeforeReturn.ts +0 -29
- package/src/queryCookies.ts +0 -41
- package/src/resultsRendered.ts +0 -24
- package/src/unpackHeaders.ts +0 -18
- package/src/util/flatMapAsync.test.ts +0 -55
- package/src/util/flatMapAsync.ts +0 -41
- package/src/util/index.ts +0 -1
- package/tsconfig.json +0 -26
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { createDecipheriv, pbkdf2 } from "crypto";
|
|
2
|
-
import { parsedArgs } from "../../argv";
|
|
3
|
-
import consola from "../../logger";
|
|
4
|
-
|
|
5
|
-
interface Decryptor {
|
|
6
|
-
decrypt(password: string, encryptedData: Buffer): Promise<string>;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
class BufferDecryptor implements Decryptor {
|
|
10
|
-
async decrypt(password: string, encryptedData: Buffer): Promise<string> {
|
|
11
|
-
this.validatePassword(password);
|
|
12
|
-
const preparedData: Buffer =
|
|
13
|
-
this.validateAndPrepareEncryptedData(encryptedData);
|
|
14
|
-
|
|
15
|
-
if (parsedArgs.verbose) {
|
|
16
|
-
consola.start(`Trying to decrypt with password: ${password}`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const decryptedData: string = await this.performDecryption(
|
|
20
|
-
password,
|
|
21
|
-
preparedData,
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
if (parsedArgs.verbose) {
|
|
25
|
-
consola.success(`Decryption successful: ${decryptedData}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return decryptedData;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
private validatePassword(password: string): void {
|
|
32
|
-
if (typeof password !== "string") {
|
|
33
|
-
throw new Error("password must be a string: " + password);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private validateAndPrepareEncryptedData(encryptedData: Buffer): Buffer {
|
|
38
|
-
if (
|
|
39
|
-
encryptedData == null ||
|
|
40
|
-
!(
|
|
41
|
-
encryptedData instanceof Buffer ||
|
|
42
|
-
(Array.isArray(encryptedData) && Buffer.isBuffer(encryptedData[0]))
|
|
43
|
-
)
|
|
44
|
-
) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
"encryptedData must be a Buffer or an array of Buffers: " +
|
|
47
|
-
encryptedData,
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (Array.isArray(encryptedData) && Buffer.isBuffer(encryptedData[0])) {
|
|
52
|
-
encryptedData = encryptedData[0];
|
|
53
|
-
if (parsedArgs.verbose) {
|
|
54
|
-
consola.info(
|
|
55
|
-
`encryptedData is an array of buffers, selected first: ${encryptedData}`,
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return Buffer.from(encryptedData);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private performDecryption(
|
|
64
|
-
password: string,
|
|
65
|
-
encryptedData: Buffer,
|
|
66
|
-
): Promise<string> {
|
|
67
|
-
return new Promise((resolve, reject) => {
|
|
68
|
-
this.deriveKey(password)
|
|
69
|
-
.then((key) => this.decryptData(key, encryptedData))
|
|
70
|
-
.then((decrypted) => resolve(decrypted))
|
|
71
|
-
.catch((error) => reject(error));
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private deriveKey(password: string): Promise<Buffer> {
|
|
76
|
-
return new Promise((resolve, reject) => {
|
|
77
|
-
pbkdf2(
|
|
78
|
-
password,
|
|
79
|
-
"saltysalt",
|
|
80
|
-
1003,
|
|
81
|
-
16,
|
|
82
|
-
"sha1",
|
|
83
|
-
(error: Error | null, buffer: Buffer) => {
|
|
84
|
-
if (error) {
|
|
85
|
-
this.logError("Error doing pbkdf2", error);
|
|
86
|
-
reject(error);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (buffer.length !== 16) {
|
|
91
|
-
this.logError(
|
|
92
|
-
"Error doing pbkdf2, buffer length is not 16",
|
|
93
|
-
buffer.length,
|
|
94
|
-
);
|
|
95
|
-
reject(new Error("Buffer length is not 16"));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
resolve(buffer);
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
private decryptData(key: Buffer, encryptedData: Buffer): Promise<string> {
|
|
106
|
-
return new Promise((resolve, reject) => {
|
|
107
|
-
const iv: Buffer = Buffer.from(new Array(17).join(" "), "binary");
|
|
108
|
-
const decipher = createDecipheriv("aes-128-cbc", key, iv);
|
|
109
|
-
decipher.setAutoPadding(false);
|
|
110
|
-
|
|
111
|
-
const slicedData: Buffer = encryptedData.slice(3);
|
|
112
|
-
|
|
113
|
-
if (slicedData.length % 16 !== 0) {
|
|
114
|
-
this.logError(
|
|
115
|
-
"Error, encryptedData length is not a multiple of 16",
|
|
116
|
-
slicedData.length,
|
|
117
|
-
);
|
|
118
|
-
reject(new Error("encryptedData length is not a multiple of 16"));
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
let decoded: Buffer = decipher.update(slicedData);
|
|
123
|
-
try {
|
|
124
|
-
decipher.final("utf-8");
|
|
125
|
-
} catch (e) {
|
|
126
|
-
this.logError("Error doing decipher.final()", e);
|
|
127
|
-
reject(e);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const padding: number = decoded[decoded.length - 1];
|
|
132
|
-
if (padding) {
|
|
133
|
-
decoded = decoded.slice(0, 0 - padding);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
resolve(decoded.toString("utf8"));
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private logError(message: string, error: any): void {
|
|
141
|
-
if (parsedArgs.verbose) {
|
|
142
|
-
consola.error(message, error);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export const decryptor: Decryptor = new BufferDecryptor();
|
|
148
|
-
|
|
149
|
-
export async function decrypt(
|
|
150
|
-
password: string,
|
|
151
|
-
encryptedData: Buffer,
|
|
152
|
-
): Promise<string> {
|
|
153
|
-
return decryptor.decrypt(password, encryptedData);
|
|
154
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { execSimple } from "../../execSimple";
|
|
2
|
-
|
|
3
|
-
interface PasswordRetriever {
|
|
4
|
-
retrievePassword(): Promise<string>;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
class MacOSPasswordRetriever implements PasswordRetriever {
|
|
8
|
-
async retrievePassword(): Promise<string> {
|
|
9
|
-
return execSimple(
|
|
10
|
-
'security find-generic-password -w -s "Chrome Safe Storage"',
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
class UnsupportedPlatformPasswordRetriever implements PasswordRetriever {
|
|
16
|
-
async retrievePassword(): Promise<string> {
|
|
17
|
-
return Promise.reject(new Error("This only works on macOS"));
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const passwordRetriever: PasswordRetriever =
|
|
22
|
-
process.platform == "darwin"
|
|
23
|
-
? new MacOSPasswordRetriever()
|
|
24
|
-
: new UnsupportedPlatformPasswordRetriever();
|
|
25
|
-
|
|
26
|
-
export async function getChromePassword(): Promise<string> {
|
|
27
|
-
return await passwordRetriever.retrievePassword();
|
|
28
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as path from "path";
|
|
2
|
-
import CookieQueryStrategy from "../CookieQueryStrategy";
|
|
3
|
-
import { HOME } from "../../global";
|
|
4
|
-
import { existsSync } from "fs";
|
|
5
|
-
import { findAllFiles } from "../../findAllFiles";
|
|
6
|
-
import ExportedCookie from "../../ExportedCookie";
|
|
7
|
-
import CookieRow from "../../CookieRow";
|
|
8
|
-
import CookieSpec from "../../CookieSpec";
|
|
9
|
-
import { specialCases } from "../../SpecialCases";
|
|
10
|
-
import { parsedArgs } from "../../argv";
|
|
11
|
-
import { querySqliteThenTransform } from "../QuerySqliteThenTransform";
|
|
12
|
-
|
|
13
|
-
export default class FirefoxCookieQueryStrategy implements CookieQueryStrategy {
|
|
14
|
-
browserName: string = "Firefox";
|
|
15
|
-
|
|
16
|
-
async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
|
|
17
|
-
if (process.platform !== "darwin") {
|
|
18
|
-
// TODO: implement
|
|
19
|
-
return [];
|
|
20
|
-
}
|
|
21
|
-
if (parsedArgs.browser !== "firefox") {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
const cookies: CookieRow[] = await this.getFirefoxCookie({ name, domain });
|
|
25
|
-
if (Array.isArray(cookies)) {
|
|
26
|
-
return cookies.map((cookie: CookieRow) => {
|
|
27
|
-
return {
|
|
28
|
-
domain: cookie.domain,
|
|
29
|
-
name: cookie.name,
|
|
30
|
-
value: Buffer.isBuffer(cookie.value)
|
|
31
|
-
? cookie.value.toString("utf8")
|
|
32
|
-
: Buffer.from(cookie.value).toString("utf8"),
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
} else {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private async getFirefoxCookie(
|
|
41
|
-
{ name, domain }: CookieSpec, //
|
|
42
|
-
): Promise<CookieRow[]> {
|
|
43
|
-
if (!HOME) {
|
|
44
|
-
throw new Error("HOME environment variable is not set");
|
|
45
|
-
}
|
|
46
|
-
const files: string[] = findAllFiles({
|
|
47
|
-
path: path.join(
|
|
48
|
-
HOME,
|
|
49
|
-
"Library",
|
|
50
|
-
"Application Support",
|
|
51
|
-
"Firefox",
|
|
52
|
-
"Profiles",
|
|
53
|
-
),
|
|
54
|
-
name: "cookies.sqlite",
|
|
55
|
-
});
|
|
56
|
-
const all: CookieRow[][] = await Promise.all(
|
|
57
|
-
files.map(async (file: string) => {
|
|
58
|
-
return await this.queryCookiesDb(file, name, domain);
|
|
59
|
-
}),
|
|
60
|
-
);
|
|
61
|
-
// flatten
|
|
62
|
-
return all.flat();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private async queryCookiesDb(
|
|
66
|
-
file: string,
|
|
67
|
-
name: string,
|
|
68
|
-
domain: string,
|
|
69
|
-
): Promise<CookieRow[]> {
|
|
70
|
-
if (!existsSync(file)) {
|
|
71
|
-
throw new Error(`File ${file} does not exist`);
|
|
72
|
-
}
|
|
73
|
-
let sql: string;
|
|
74
|
-
//language=SQL
|
|
75
|
-
sql = "SELECT value, name, host FROM moz_cookies";
|
|
76
|
-
const { specifiedName, specifiedDomain } = specialCases({ name, domain });
|
|
77
|
-
if (specifiedName || specifiedDomain) {
|
|
78
|
-
sql += ` WHERE `;
|
|
79
|
-
if (specifiedName) {
|
|
80
|
-
sql += `name = '${name}'`;
|
|
81
|
-
if (specifiedDomain) {
|
|
82
|
-
sql += ` AND `;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (specifiedDomain) {
|
|
86
|
-
sql += `host LIKE '${domain}';`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const rowTransform = (row: any): CookieRow => {
|
|
90
|
-
// row is object key by column name
|
|
91
|
-
const value = row.value as string;
|
|
92
|
-
return {
|
|
93
|
-
domain: row.domain as string,
|
|
94
|
-
name: row.name as string,
|
|
95
|
-
value: Buffer.from(value, "utf8"),
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
try {
|
|
99
|
-
return await querySqliteThenTransform({
|
|
100
|
-
file,
|
|
101
|
-
sql,
|
|
102
|
-
rowTransform,
|
|
103
|
-
});
|
|
104
|
-
} catch (e) {
|
|
105
|
-
console.error(`Error querying ${file}`, e);
|
|
106
|
-
return [];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { chromeApplicationSupport } from "./chrome/ChromeApplicationSupport";
|
|
2
|
-
import { querySqliteThenTransform } from "./QuerySqliteThenTransform";
|
|
3
|
-
import { existsSync } from "fs";
|
|
4
|
-
import { join } from "path";
|
|
5
|
-
import { parsedArgs } from "../argv";
|
|
6
|
-
import { stringToRegex } from "../StringToRegex";
|
|
7
|
-
import CookieRow from "../CookieRow";
|
|
8
|
-
import consola from "../logger";
|
|
9
|
-
|
|
10
|
-
interface GetEncryptedChromeCookieParams {
|
|
11
|
-
name: string;
|
|
12
|
-
domain: string;
|
|
13
|
-
file?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface SqlQueryBuilderInterface {
|
|
17
|
-
build(): string;
|
|
18
|
-
addCondition(field: string, value: string, operator?: string): void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
class SqlQueryBuilder implements SqlQueryBuilderInterface {
|
|
22
|
-
private baseQuery: string;
|
|
23
|
-
private conditions: string[];
|
|
24
|
-
|
|
25
|
-
constructor(
|
|
26
|
-
baseQuery: string = "SELECT encrypted_value, name, host_key, expires_utc FROM cookies",
|
|
27
|
-
) {
|
|
28
|
-
this.baseQuery = baseQuery;
|
|
29
|
-
this.conditions = [];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
addCondition(field: string, value: string, operator: string = "="): void {
|
|
33
|
-
const wildcardRegexp = /^([*%])$/i;
|
|
34
|
-
if (!wildcardRegexp.test(value)) {
|
|
35
|
-
const condition = `${field} ${operator} '${value}'`;
|
|
36
|
-
this.conditions.push(condition);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
build(): string {
|
|
41
|
-
let sql = this.baseQuery;
|
|
42
|
-
if (this.conditions.length > 0) {
|
|
43
|
-
sql += ` WHERE ${this.conditions.join(" AND ")}`;
|
|
44
|
-
}
|
|
45
|
-
return sql;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
interface LoggerInterface {
|
|
50
|
-
log(file: string, name: string, domain: string, sql: string): void;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
class VerboseLogger implements LoggerInterface {
|
|
54
|
-
log(file: string, name: string, domain: string, sql: string): void {
|
|
55
|
-
if (parsedArgs.verbose) {
|
|
56
|
-
const s = file.split("/").slice(-3).join("/");
|
|
57
|
-
consola.start(
|
|
58
|
-
`Trying Chrome (at ${s}) cookie ${name} for domain ${domain}`,
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface RowTransformerInterface {
|
|
65
|
-
transform(row: any): CookieRow;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
class RowTransformer implements RowTransformerInterface {
|
|
69
|
-
transform(row: any): CookieRow {
|
|
70
|
-
const cookieRow: CookieRow = {
|
|
71
|
-
expiry: (row["expires_utc"] / 1000000 - 11644473600) * 1000,
|
|
72
|
-
domain: row["host_key"],
|
|
73
|
-
name: row["name"],
|
|
74
|
-
value: row["encrypted_value"],
|
|
75
|
-
};
|
|
76
|
-
return cookieRow;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function getEncryptedChromeCookie({
|
|
81
|
-
name,
|
|
82
|
-
domain,
|
|
83
|
-
file = join(chromeApplicationSupport, "Default", "Cookies"),
|
|
84
|
-
}: GetEncryptedChromeCookieParams): Promise<CookieRow[]> {
|
|
85
|
-
if (!existsSync(file)) {
|
|
86
|
-
throw new Error(`File ${file} does not exist`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const sqlQueryBuilder: SqlQueryBuilderInterface = new SqlQueryBuilder();
|
|
90
|
-
sqlQueryBuilder.addCondition("name", name);
|
|
91
|
-
const wildcardDomain = /[%*]/.test(domain);
|
|
92
|
-
if (!wildcardDomain) {
|
|
93
|
-
const sqlEmbedDomain = domain.replace(/^[.%]?/, "%");
|
|
94
|
-
sqlQueryBuilder.addCondition("host_key", sqlEmbedDomain, "LIKE");
|
|
95
|
-
}
|
|
96
|
-
const sql: string = sqlQueryBuilder.build();
|
|
97
|
-
|
|
98
|
-
const verboseLogger: LoggerInterface = new VerboseLogger();
|
|
99
|
-
verboseLogger.log(file, name, domain, sql);
|
|
100
|
-
|
|
101
|
-
const domainRegexp: RegExp = stringToRegex(domain);
|
|
102
|
-
const rowTransformer: RowTransformerInterface = new RowTransformer();
|
|
103
|
-
let sqliteQuery1: CookieRow[];
|
|
104
|
-
try {
|
|
105
|
-
sqliteQuery1 = await querySqliteThenTransform({
|
|
106
|
-
file: file,
|
|
107
|
-
sql: sql,
|
|
108
|
-
rowFilter: (row) => {
|
|
109
|
-
return row["host_key"].match(domainRegexp) != null;
|
|
110
|
-
},
|
|
111
|
-
rowTransform: rowTransformer.transform.bind(rowTransformer),
|
|
112
|
-
});
|
|
113
|
-
} catch (error) {
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const filteredResults = sqliteQuery1.filter((row) => {
|
|
118
|
-
return row.domain.match(domainRegexp) != null;
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
return filteredResults;
|
|
122
|
-
}
|
package/src/browsers/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export * from "./chrome/ChromeApplicationSupport";
|
|
2
|
-
export * from "./chrome/ChromeCookieQueryStrategy";
|
|
3
|
-
export * from "./CompositeCookieQueryStrategy";
|
|
4
|
-
export * from "./CookieQueryStrategy";
|
|
5
|
-
export * from "./CookieStoreQueryStrategy";
|
|
6
|
-
export * from "./QuerySqliteThenTransform";
|
|
7
|
-
export * from "./firefox/FirefoxCookieQueryStrategy";
|
|
8
|
-
export * from "./mock/MockCookieQueryStrategy";
|
|
9
|
-
export * from "./safari/SafariCookieQueryStrategy";
|
|
10
|
-
export * from "./chrome/decrypt";
|
|
11
|
-
export * from "./chrome/getChromePassword";
|
|
12
|
-
export * from "./getEncryptedChromeCookie";
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import ExportedCookie from "../../ExportedCookie";
|
|
2
|
-
import CookieQueryStrategy from "../CookieQueryStrategy";
|
|
3
|
-
|
|
4
|
-
export default class MockCookieQueryStrategy implements CookieQueryStrategy {
|
|
5
|
-
browserName: string = "mock";
|
|
6
|
-
|
|
7
|
-
private cookies: ExportedCookie[];
|
|
8
|
-
|
|
9
|
-
constructor(cookies: ExportedCookie[]) {
|
|
10
|
-
this.cookies = cookies;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
|
|
14
|
-
const filteredCookies: ExportedCookie[] = [];
|
|
15
|
-
for (const cookie of this.cookies) {
|
|
16
|
-
if (cookie.name === name && cookie.domain === domain) {
|
|
17
|
-
filteredCookies.push(cookie);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return filteredCookies;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import CookieQueryStrategy from "../CookieQueryStrategy";
|
|
2
|
-
import ExportedCookie from "../../ExportedCookie";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { decodeBinaryCookies } from "../../decodeBinaryCookies"; // Assuming you have a module to decode binary cookies
|
|
5
|
-
import CookieRow from "../../CookieRow";
|
|
6
|
-
|
|
7
|
-
export default class SafariCookieQueryStrategy implements CookieQueryStrategy {
|
|
8
|
-
browserName: string = "Safari";
|
|
9
|
-
|
|
10
|
-
async queryCookies(name: string, domain: string): Promise<ExportedCookie[]> {
|
|
11
|
-
const homeDir: string | undefined = process.env.HOME;
|
|
12
|
-
if (!homeDir) {
|
|
13
|
-
throw new Error("HOME environment variable is not set");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const cookieDbPath: string = join(
|
|
17
|
-
homeDir,
|
|
18
|
-
"Library",
|
|
19
|
-
"Cookies",
|
|
20
|
-
"Cookies.binarycookies",
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const cookies: CookieRow[] = await decodeBinaryCookies(cookieDbPath);
|
|
25
|
-
|
|
26
|
-
const filteredCookies: CookieRow[] = cookies.filter(
|
|
27
|
-
(cookie: CookieRow) => cookie.name === name && cookie.domain.includes(domain)
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const exportedCookies: ExportedCookie[] = filteredCookies.map((cookie: CookieRow) => ({
|
|
31
|
-
domain: cookie.domain,
|
|
32
|
-
name: cookie.name,
|
|
33
|
-
value: cookie.value.toString("utf8"),
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
return exportedCookies;
|
|
37
|
-
} catch (e) {
|
|
38
|
-
console.error(`Error decoding ${cookieDbPath}`, e);
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
package/src/cli.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import { argv, parsedArgs } from "./argv";
|
|
4
|
-
import { fetchWithCookies } from "./fetchWithCookies";
|
|
5
|
-
import { unpackHeaders } from "./unpackHeaders";
|
|
6
|
-
import CookieSpec from "./CookieSpec";
|
|
7
|
-
import { cookieSpecsFromUrl } from "./cookieSpecsFromUrl";
|
|
8
|
-
import logger from "./logger";
|
|
9
|
-
import { cliQueryCookies } from "./cliQueryCookies";
|
|
10
|
-
|
|
11
|
-
async function main() {
|
|
12
|
-
if (parsedArgs["help"] || parsedArgs["h"]) {
|
|
13
|
-
logger.log(`Usage: ${argv[1]} [name] [domain] [options]`);
|
|
14
|
-
logger.log(`Options:`);
|
|
15
|
-
logger.log(` -h, --help: Show this help message`);
|
|
16
|
-
logger.log(` -v, --verbose: Enable verbose output`);
|
|
17
|
-
logger.log(` -d, --dump: Dump all results`);
|
|
18
|
-
logger.log(` -D, --dump-grouped: Dump all results, grouped by profile`);
|
|
19
|
-
logger.log(` -r, --render: Render all results`);
|
|
20
|
-
logger.log(` -F, --fetch <url>: Fetch data from the specified URL`);
|
|
21
|
-
logger.log(` -H <header>: Specify headers for the fetch request`);
|
|
22
|
-
logger.log(
|
|
23
|
-
` --dump-response-headers: Dump response headers from fetch request`,
|
|
24
|
-
);
|
|
25
|
-
logger.log(` --dump-response-body: Dump response body from fetch request`);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
parsedArgs["verbose"] = parsedArgs["verbose"] || parsedArgs["v"];
|
|
30
|
-
|
|
31
|
-
const fetchUrl: string = parsedArgs["fetch"] || parsedArgs["F"];
|
|
32
|
-
if (fetchUrl) {
|
|
33
|
-
let url: URL;
|
|
34
|
-
try {
|
|
35
|
-
url = new URL(fetchUrl);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
logger.error("Invalid URL", fetchUrl);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
logger.start("Fetching", url.href);
|
|
41
|
-
const headerArgs: string[] | string = parsedArgs["H"];
|
|
42
|
-
const headers = unpackHeaders(headerArgs);
|
|
43
|
-
const onfulfilled = async (res: Response) => {
|
|
44
|
-
if (parsedArgs["dump-response-headers"]) {
|
|
45
|
-
for (const [key, value] of Object.entries(res.headers)) {
|
|
46
|
-
logger.log(`${key}: ${value}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (parsedArgs["dump-response-body"]) {
|
|
50
|
-
const responseBody = await res.text();
|
|
51
|
-
logger.log(responseBody);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
try {
|
|
55
|
-
const res = await fetchWithCookies(url, { headers });
|
|
56
|
-
logger.debug("Response", res);
|
|
57
|
-
await onfulfilled(res);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
logger.error(error);
|
|
60
|
-
}
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const cookieSpecs: CookieSpec[] = [];
|
|
65
|
-
const argUrl: string = parsedArgs["url"] || parsedArgs["u"];
|
|
66
|
-
if (argUrl) {
|
|
67
|
-
for (const cookieSpec of cookieSpecsFromUrl(argUrl)) {
|
|
68
|
-
cookieSpecs.push(cookieSpec);
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
cookieSpecs.push({
|
|
72
|
-
name: parsedArgs["name"] || parsedArgs["_"][0] || "%",
|
|
73
|
-
domain: parsedArgs["domain"] || parsedArgs["_"][1] || "%",
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (parsedArgs.verbose) {
|
|
78
|
-
logger.log("cookieSpecs", cookieSpecs);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
await cliQueryCookies(cookieSpecs);
|
|
83
|
-
} catch (error) {
|
|
84
|
-
logger.error(error);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
main().then(
|
|
89
|
-
() => process.exit(0),
|
|
90
|
-
(error) => {
|
|
91
|
-
logger.error(error);
|
|
92
|
-
process.exit(1);
|
|
93
|
-
},
|
|
94
|
-
);
|
package/src/cliQueryCookies.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import CookieSpec from "./CookieSpec";
|
|
2
|
-
import ExportedCookie from "./ExportedCookie";
|
|
3
|
-
import { comboQueryCookieSpec } from "./comboQueryCookieSpec";
|
|
4
|
-
import { groupBy } from "lodash";
|
|
5
|
-
import logger from "./logger";
|
|
6
|
-
import { parsedArgs } from "./argv";
|
|
7
|
-
import { resultsRendered } from "./resultsRendered";
|
|
8
|
-
|
|
9
|
-
export async function cliQueryCookies(
|
|
10
|
-
cookieSpec: CookieSpec | CookieSpec[],
|
|
11
|
-
limit?: number,
|
|
12
|
-
removeExpired?: boolean,
|
|
13
|
-
) {
|
|
14
|
-
try {
|
|
15
|
-
const results: ExportedCookie[] = await comboQueryCookieSpec(cookieSpec, {
|
|
16
|
-
limit,
|
|
17
|
-
removeExpired,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (!results || results.length === 0) {
|
|
21
|
-
logger.error("No results");
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (parsedArgs["dump"] || parsedArgs["d"]) {
|
|
26
|
-
logger.log(results);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (parsedArgs["dump-grouped"] || parsedArgs["D"]) {
|
|
31
|
-
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
32
|
-
logger.log(JSON.stringify(groupedByFile, null, 2));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
parsedArgs["render"] ||
|
|
38
|
-
parsedArgs["render-merged"] ||
|
|
39
|
-
parsedArgs["r"]
|
|
40
|
-
) {
|
|
41
|
-
logger.log(resultsRendered(results));
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (parsedArgs["render-grouped"] || parsedArgs["R"]) {
|
|
46
|
-
const groupedByFile = groupBy(results, (r) => r.meta?.file);
|
|
47
|
-
for (const file of Object.keys(groupedByFile)) {
|
|
48
|
-
const fileResults = groupedByFile[file];
|
|
49
|
-
logger.log(`${file}: ${resultsRendered(fileResults)}`);
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (parsedArgs["output"] === "json") {
|
|
55
|
-
logger.log(JSON.stringify(results, null, 2));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
for (const result of results) {
|
|
60
|
-
logger.log(result.value);
|
|
61
|
-
}
|
|
62
|
-
} catch (e) {
|
|
63
|
-
logger.error(e);
|
|
64
|
-
}
|
|
65
|
-
}
|