@mherod/get-cookie 4.2.2 → 4.3.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.
- package/.husky/commit-msg +14 -0
- package/.husky/pre-commit +14 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.nvmrc +1 -0
- package/README.md +65 -83
- package/biome.json +94 -0
- package/dist/cli.cjs +2 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +269 -75
- package/dist/index.d.ts +269 -75
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/eslint.config.js +1 -1
- package/jest.setup.js +24 -1
- package/package.json +41 -40
- package/tsup.lib.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import * as consola from 'consola';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Schema for cookie specification parameters
|
|
@@ -209,7 +210,7 @@ type BrowserName = z.infer<typeof BrowserNameSchema>;
|
|
|
209
210
|
*/
|
|
210
211
|
declare const CookieQueryStrategySchema: z.ZodObject<{
|
|
211
212
|
browserName: z.ZodEnum<["Chrome", "Firefox", "Safari", "internal", "unknown"]>;
|
|
212
|
-
queryCookies: z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodOptional<z.ZodString>], z.ZodUnknown>, z.ZodPromise<z.ZodArray<z.ZodObject<{
|
|
213
|
+
queryCookies: z.ZodFunction<z.ZodTuple<[z.ZodString, z.ZodString, z.ZodOptional<z.ZodString>, z.ZodOptional<z.ZodBoolean>], z.ZodUnknown>, z.ZodPromise<z.ZodArray<z.ZodObject<{
|
|
213
214
|
domain: z.ZodEffects<z.ZodString, string, string>;
|
|
214
215
|
name: z.ZodEffects<z.ZodString, string, string>;
|
|
215
216
|
value: z.ZodPipeline<z.ZodEffects<z.ZodString, unknown, string>, z.ZodAny>;
|
|
@@ -265,7 +266,7 @@ declare const CookieQueryStrategySchema: z.ZodObject<{
|
|
|
265
266
|
}>, "many">>>;
|
|
266
267
|
}, "strict", z.ZodTypeAny, {
|
|
267
268
|
browserName: "unknown" | "Chrome" | "Firefox" | "Safari" | "internal";
|
|
268
|
-
queryCookies: (args_0: string, args_1: string, args_2: string | undefined, ...args: unknown[]) => Promise<{
|
|
269
|
+
queryCookies: (args_0: string, args_1: string, args_2: string | undefined, args_3: boolean | undefined, ...args: unknown[]) => Promise<{
|
|
269
270
|
name: string;
|
|
270
271
|
domain: string;
|
|
271
272
|
value?: any;
|
|
@@ -281,7 +282,7 @@ declare const CookieQueryStrategySchema: z.ZodObject<{
|
|
|
281
282
|
}[]>;
|
|
282
283
|
}, {
|
|
283
284
|
browserName: "unknown" | "Chrome" | "Firefox" | "Safari" | "internal";
|
|
284
|
-
queryCookies: (args_0: string, args_1: string, args_2: string | undefined, ...args: unknown[]) => Promise<{
|
|
285
|
+
queryCookies: (args_0: string, args_1: string, args_2: string | undefined, args_3: boolean | undefined, ...args: unknown[]) => Promise<{
|
|
285
286
|
name: string;
|
|
286
287
|
value: string;
|
|
287
288
|
domain: string;
|
|
@@ -348,96 +349,289 @@ type MultiCookieSpec = CookieSpec | CookieSpec[];
|
|
|
348
349
|
declare function getCookie(cookieSpec: CookieSpec): Promise<ExportedCookie[]>;
|
|
349
350
|
|
|
350
351
|
/**
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
* @
|
|
354
|
-
* @
|
|
355
|
-
* @returns An array of ExportedCookie objects that match the specification
|
|
356
|
-
* @throws Will catch and handle any errors during cookie querying, logging a warning
|
|
357
|
-
* to the console without throwing to the caller
|
|
358
|
-
* @example
|
|
359
|
-
* ```typescript
|
|
360
|
-
* import { getChromeCookie } from "@mherod/get-cookie";
|
|
361
|
-
*
|
|
362
|
-
* // Get all cookies named "sessionId" from Chrome
|
|
363
|
-
* const cookies = await getChromeCookie({ name: "sessionId" });
|
|
364
|
-
*
|
|
365
|
-
* // Get cookies named "userPref" from specific domain in Chrome
|
|
366
|
-
* const domainCookies = await getChromeCookie({
|
|
367
|
-
* name: "userPref",
|
|
368
|
-
* domain: "example.com"
|
|
369
|
-
* });
|
|
370
|
-
* ```
|
|
352
|
+
* Base class for cookie query strategies.
|
|
353
|
+
* Provides common functionality and standardized error handling for browser-specific implementations.
|
|
354
|
+
* @implements {CookieQueryStrategy}
|
|
355
|
+
* @abstract
|
|
371
356
|
*/
|
|
372
|
-
declare
|
|
357
|
+
declare abstract class BaseCookieQueryStrategy implements CookieQueryStrategy {
|
|
358
|
+
readonly browserName: BrowserName;
|
|
359
|
+
/**
|
|
360
|
+
* Logger instance for this strategy
|
|
361
|
+
* @protected
|
|
362
|
+
*/
|
|
363
|
+
protected readonly logger: consola.ConsolaInstance;
|
|
364
|
+
/**
|
|
365
|
+
* Creates a new instance of BaseCookieQueryStrategy
|
|
366
|
+
* @param strategyName - The name of the strategy for logging purposes
|
|
367
|
+
* @param browserName - The name of the browser this strategy is for
|
|
368
|
+
*/
|
|
369
|
+
constructor(strategyName: string, browserName: BrowserName);
|
|
370
|
+
/**
|
|
371
|
+
* Queries cookies from the browser's cookie store
|
|
372
|
+
* @param name - The name pattern to match cookies against
|
|
373
|
+
* @param domain - The domain pattern to match cookies against
|
|
374
|
+
* @param store - Optional path to a specific cookie store file
|
|
375
|
+
* @param force - Whether to force operations despite warnings (e.g., locked databases)
|
|
376
|
+
* @returns A promise that resolves to an array of exported cookies
|
|
377
|
+
*/
|
|
378
|
+
queryCookies(name: string, domain: string, store?: string, force?: boolean): Promise<ExportedCookie[]>;
|
|
379
|
+
/**
|
|
380
|
+
* Executes the browser-specific query logic
|
|
381
|
+
* @abstract
|
|
382
|
+
* @param name - The name pattern to match cookies against
|
|
383
|
+
* @param domain - The domain pattern to match cookies against
|
|
384
|
+
* @param store - Optional path to a specific cookie store file
|
|
385
|
+
* @param force - Whether to force operations despite warnings (e.g., locked databases)
|
|
386
|
+
* @returns A promise that resolves to an array of exported cookies
|
|
387
|
+
* @protected
|
|
388
|
+
*/
|
|
389
|
+
protected abstract executeQuery(name: string, domain: string, store?: string, force?: boolean): Promise<ExportedCookie[]>;
|
|
390
|
+
}
|
|
373
391
|
|
|
374
392
|
/**
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* @param cookieSpec.domain - (optional) The domain to filter cookies by
|
|
379
|
-
* @returns An array of ExportedCookie objects that match the specification
|
|
380
|
-
* @throws Will catch and handle any errors during cookie querying, logging a warning
|
|
381
|
-
* to the console without throwing to the caller
|
|
393
|
+
* Strategy for querying cookies from Chrome browser.
|
|
394
|
+
* This class extends the BaseCookieQueryStrategy and implements Chrome-specific
|
|
395
|
+
* cookie extraction logic.
|
|
382
396
|
* @example
|
|
383
397
|
* ```typescript
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* // Get all cookies named "sessionId" from Firefox
|
|
387
|
-
* const cookies = await getFirefoxCookie({ name: "sessionId" });
|
|
388
|
-
*
|
|
389
|
-
* // Get cookies named "userPref" from specific domain in Firefox
|
|
390
|
-
* const domainCookies = await getFirefoxCookie({
|
|
391
|
-
* name: "userPref",
|
|
392
|
-
* domain: "example.com"
|
|
393
|
-
* });
|
|
398
|
+
* const strategy = new ChromeCookieQueryStrategy();
|
|
399
|
+
* const cookies = await strategy.queryCookies('session', 'example.com');
|
|
394
400
|
* ```
|
|
395
401
|
*/
|
|
396
|
-
declare
|
|
402
|
+
declare class ChromeCookieQueryStrategy extends BaseCookieQueryStrategy {
|
|
403
|
+
/**
|
|
404
|
+
* Creates a new instance of ChromeCookieQueryStrategy
|
|
405
|
+
*/
|
|
406
|
+
constructor();
|
|
407
|
+
/**
|
|
408
|
+
* Executes the Chrome-specific query logic
|
|
409
|
+
* @param name - The name pattern to match cookies against
|
|
410
|
+
* @param domain - The domain pattern to match cookies against
|
|
411
|
+
* @param store - Optional path to a specific cookie store file
|
|
412
|
+
* @param _force - Whether to force operations despite warnings (e.g., locked databases)
|
|
413
|
+
* @returns A promise that resolves to an array of exported cookies
|
|
414
|
+
* @protected
|
|
415
|
+
* @example
|
|
416
|
+
* ```typescript
|
|
417
|
+
* // This method is called internally by queryCookies
|
|
418
|
+
* const cookies = await strategy.queryCookies('session', 'example.com');
|
|
419
|
+
* console.log(cookies);
|
|
420
|
+
* ```
|
|
421
|
+
*/
|
|
422
|
+
protected executeQuery(name: string, domain: string, store?: string, _force?: boolean): Promise<ExportedCookie[]>;
|
|
423
|
+
private processFile;
|
|
424
|
+
private processCookie;
|
|
425
|
+
}
|
|
397
426
|
|
|
398
427
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
*
|
|
405
|
-
|
|
406
|
-
|
|
428
|
+
* Chromium browser configuration and path management
|
|
429
|
+
* Supports Chrome, Chromium, Brave, Edge, Opera, Vivaldi, and Whale browsers
|
|
430
|
+
* across Windows, macOS, and Linux platforms
|
|
431
|
+
*/
|
|
432
|
+
/**
|
|
433
|
+
* Supported Chromium-based browsers
|
|
434
|
+
*/
|
|
435
|
+
declare const CHROMIUM_BASED_BROWSERS: readonly ["chrome", "chromium", "brave", "edge", "opera", "vivaldi", "whale"];
|
|
436
|
+
type ChromiumBrowser = (typeof CHROMIUM_BASED_BROWSERS)[number];
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Strategy for querying cookies from Chromium-based browsers (Chrome, Brave, Edge, etc.)
|
|
440
|
+
* This class extends the BaseCookieQueryStrategy and implements Chromium-specific
|
|
441
|
+
* cookie extraction logic that works across multiple browsers.
|
|
442
|
+
*/
|
|
443
|
+
declare class ChromiumCookieQueryStrategy extends BaseCookieQueryStrategy {
|
|
444
|
+
private browser;
|
|
445
|
+
/**
|
|
446
|
+
* Creates a new instance of ChromiumCookieQueryStrategy
|
|
447
|
+
* @param browser - The Chromium-based browser to query (chrome, brave, edge, etc.)
|
|
448
|
+
*/
|
|
449
|
+
constructor(browser?: ChromiumBrowser);
|
|
450
|
+
/**
|
|
451
|
+
* Lists all cookie file paths for the specified browser
|
|
452
|
+
*/
|
|
453
|
+
private listBrowserCookiePaths;
|
|
454
|
+
/**
|
|
455
|
+
* Executes the Chromium-specific query logic
|
|
456
|
+
*/
|
|
457
|
+
protected executeQuery(name: string, domain: string, store?: string, _force?: boolean): Promise<ExportedCookie[]>;
|
|
458
|
+
private processFile;
|
|
459
|
+
private processCookie;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Strategy for querying cookies from Firefox browser.
|
|
464
|
+
* This class extends the BaseCookieQueryStrategy and implements Firefox-specific
|
|
465
|
+
* cookie extraction logic. It searches for cookie databases in standard Firefox
|
|
466
|
+
* profile locations and extracts cookies matching the specified name and domain.
|
|
407
467
|
* @example
|
|
408
468
|
* ```typescript
|
|
409
|
-
*
|
|
410
|
-
* const cookies = await getGroupedRenderedCookies({ name: "sessionId" });
|
|
469
|
+
* import { FirefoxCookieQueryStrategy } from './FirefoxCookieQueryStrategy';
|
|
411
470
|
*
|
|
412
|
-
*
|
|
413
|
-
* const
|
|
414
|
-
*
|
|
415
|
-
* name: "userPref",
|
|
416
|
-
* domain: "example.com"
|
|
417
|
-
* },
|
|
418
|
-
* {
|
|
419
|
-
* showFilePaths: true,
|
|
420
|
-
* separator: " | "
|
|
421
|
-
* }
|
|
422
|
-
* );
|
|
471
|
+
* const strategy = new FirefoxCookieQueryStrategy();
|
|
472
|
+
* const cookies = await strategy.queryCookies('sessionid', 'example.com');
|
|
473
|
+
* console.log(cookies);
|
|
423
474
|
* ```
|
|
424
475
|
*/
|
|
425
|
-
declare
|
|
476
|
+
declare class FirefoxCookieQueryStrategy extends BaseCookieQueryStrategy {
|
|
477
|
+
/**
|
|
478
|
+
* Creates a new instance of FirefoxCookieQueryStrategy
|
|
479
|
+
*/
|
|
480
|
+
constructor();
|
|
481
|
+
/**
|
|
482
|
+
* Check if an error indicates a database lock and provide helpful advice
|
|
483
|
+
* @param error - The error to check
|
|
484
|
+
* @param file - The database file that was locked
|
|
485
|
+
* @returns Promise that resolves after providing advice
|
|
486
|
+
* @private
|
|
487
|
+
*/
|
|
488
|
+
private handleDatabaseLockError;
|
|
489
|
+
/**
|
|
490
|
+
* Executes the Firefox-specific query logic
|
|
491
|
+
* @param name - The name pattern to match cookies against
|
|
492
|
+
* @param domain - The domain pattern to match cookies against
|
|
493
|
+
* @param store - Optional path to a specific cookie store file
|
|
494
|
+
* @param _force - Whether to force operations despite warnings (e.g., locked databases)
|
|
495
|
+
* @returns A promise that resolves to an array of exported cookies
|
|
496
|
+
* @protected
|
|
497
|
+
*/
|
|
498
|
+
protected executeQuery(name: string, domain: string, store?: string, _force?: boolean): Promise<ExportedCookie[]>;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Strategy for querying cookies from Safari browser.
|
|
503
|
+
* This class extends the BaseCookieQueryStrategy and implements Safari-specific
|
|
504
|
+
* cookie extraction logic.
|
|
505
|
+
*/
|
|
506
|
+
declare class SafariCookieQueryStrategy extends BaseCookieQueryStrategy {
|
|
507
|
+
/**
|
|
508
|
+
* Creates a new instance of SafariCookieQueryStrategy
|
|
509
|
+
*/
|
|
510
|
+
constructor();
|
|
511
|
+
/**
|
|
512
|
+
* Gets the path to Safari's cookie database
|
|
513
|
+
* @param home - The user's home directory
|
|
514
|
+
* @returns Path to the cookie database
|
|
515
|
+
*/
|
|
516
|
+
private getCookieDbPath;
|
|
517
|
+
/**
|
|
518
|
+
* Formats the domain by removing leading dot if present
|
|
519
|
+
* @param domain - Domain to format
|
|
520
|
+
* @returns Formatted domain
|
|
521
|
+
*/
|
|
522
|
+
private formatDomain;
|
|
523
|
+
/**
|
|
524
|
+
* Formats the expiry date
|
|
525
|
+
* @param expiry - Expiry timestamp (Unix epoch seconds)
|
|
526
|
+
* @returns Formatted expiry date or "Infinity"
|
|
527
|
+
*/
|
|
528
|
+
private formatExpiry;
|
|
529
|
+
/**
|
|
530
|
+
* Checks if a flag bit is set
|
|
531
|
+
* @param flags - The flags value
|
|
532
|
+
* @param bit - The bit to check
|
|
533
|
+
* @returns True if the bit is set, false otherwise
|
|
534
|
+
*/
|
|
535
|
+
private isFlagSet;
|
|
536
|
+
/**
|
|
537
|
+
* Formats the creation timestamp
|
|
538
|
+
* @param creation - Creation timestamp (Unix epoch seconds)
|
|
539
|
+
* @returns Formatted creation timestamp in milliseconds or undefined
|
|
540
|
+
*/
|
|
541
|
+
private formatCreation;
|
|
542
|
+
/**
|
|
543
|
+
* Processes a cookie value to ensure it's a string
|
|
544
|
+
* @param value - The cookie value to process
|
|
545
|
+
* @returns The processed value as a string
|
|
546
|
+
*/
|
|
547
|
+
private processValue;
|
|
548
|
+
/**
|
|
549
|
+
* Decodes cookies from Safari's binary cookie file
|
|
550
|
+
* @param cookieDbPath - Path to the cookie database
|
|
551
|
+
* @param name - Name of the cookie to find
|
|
552
|
+
* @param domain - Domain to filter cookies by
|
|
553
|
+
* @returns Array of exported cookies
|
|
554
|
+
*/
|
|
555
|
+
private decodeCookies;
|
|
556
|
+
/**
|
|
557
|
+
* Executes the Safari-specific query logic
|
|
558
|
+
* @param name - Name of the cookie to find
|
|
559
|
+
* @param domain - Domain to filter cookies by
|
|
560
|
+
* @param store - Optional store path
|
|
561
|
+
* @param _force - Whether to force operations despite warnings (e.g., locked databases)
|
|
562
|
+
* @returns Array of matching cookies, or empty array if none found
|
|
563
|
+
* @protected
|
|
564
|
+
*/
|
|
565
|
+
protected executeQuery(name: string, domain: string, store?: string, _force?: boolean): Promise<ExportedCookie[]>;
|
|
566
|
+
}
|
|
426
567
|
|
|
427
568
|
/**
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
* @returns Promise resolving to rendered cookie string
|
|
569
|
+
* A composite strategy that combines multiple cookie query strategies.
|
|
570
|
+
* This class implements the CookieQueryStrategy interface and allows querying cookies
|
|
571
|
+
* from multiple browser-specific strategies simultaneously.
|
|
432
572
|
* @example
|
|
433
573
|
* ```typescript
|
|
434
|
-
* const
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
* )
|
|
438
|
-
*
|
|
574
|
+
* const strategy = new CompositeCookieQueryStrategy([
|
|
575
|
+
* new ChromeCookieQueryStrategy(),
|
|
576
|
+
* new FirefoxCookieQueryStrategy(),
|
|
577
|
+
* new SafariCookieQueryStrategy()
|
|
578
|
+
* ]);
|
|
579
|
+
* const cookies = await strategy.queryCookies('sessionId', 'example.com');
|
|
439
580
|
* ```
|
|
440
581
|
*/
|
|
441
|
-
declare
|
|
582
|
+
declare class CompositeCookieQueryStrategy implements CookieQueryStrategy {
|
|
583
|
+
private strategies;
|
|
584
|
+
private readonly logger;
|
|
585
|
+
/**
|
|
586
|
+
* The browser name identifier for this strategy
|
|
587
|
+
* @remarks Always returns 'internal' as this is a composite strategy
|
|
588
|
+
*/
|
|
589
|
+
readonly browserName: BrowserName;
|
|
590
|
+
/**
|
|
591
|
+
* Creates a new instance of CompositeCookieQueryStrategy
|
|
592
|
+
* @param strategies - Array of browser-specific strategies to use for querying cookies
|
|
593
|
+
* @remarks
|
|
594
|
+
* - Each strategy in the array should implement the CookieQueryStrategy interface
|
|
595
|
+
* - The order of strategies determines the order of cookie querying
|
|
596
|
+
* - Failed strategies will be gracefully handled and skipped
|
|
597
|
+
* @example
|
|
598
|
+
* ```typescript
|
|
599
|
+
* const strategy = new CompositeCookieQueryStrategy([
|
|
600
|
+
* new ChromeCookieQueryStrategy(),
|
|
601
|
+
* new FirefoxCookieQueryStrategy()
|
|
602
|
+
* ]);
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
605
|
+
constructor(strategies: CookieQueryStrategy[]);
|
|
606
|
+
/**
|
|
607
|
+
* Handles strategy-specific errors and logs them appropriately
|
|
608
|
+
* @internal
|
|
609
|
+
* @param error - The error that occurred during strategy execution
|
|
610
|
+
* @param strategy - The strategy that failed
|
|
611
|
+
*/
|
|
612
|
+
private handleStrategyError;
|
|
613
|
+
/**
|
|
614
|
+
* Queries cookies using all available strategies in parallel
|
|
615
|
+
* @param name - The name pattern to match cookies against
|
|
616
|
+
* @param domain - The domain pattern to match cookies against
|
|
617
|
+
* @param store - The store pattern to match cookies against
|
|
618
|
+
* @param force - Whether to force operations despite warnings (e.g., locked databases)
|
|
619
|
+
* @returns Promise resolving to combined array of cookies from all strategies
|
|
620
|
+
* @remarks
|
|
621
|
+
* - Failures in individual strategies are logged but don't affect other strategies
|
|
622
|
+
* - Results are combined from all successful strategy queries
|
|
623
|
+
* - Empty arrays are returned for failed strategy queries
|
|
624
|
+
* @example
|
|
625
|
+
* ```typescript
|
|
626
|
+
* const strategy = new CompositeCookieQueryStrategy([
|
|
627
|
+
* new ChromeCookieQueryStrategy(),
|
|
628
|
+
* new FirefoxCookieQueryStrategy()
|
|
629
|
+
* ]);
|
|
630
|
+
* const cookies = await strategy.queryCookies('sessionId', 'example.com');
|
|
631
|
+
* console.log(cookies); // Combined results from all browsers
|
|
632
|
+
* ```
|
|
633
|
+
*/
|
|
634
|
+
queryCookies(name: string, domain: string, store?: string, force?: boolean): Promise<ExportedCookie[]>;
|
|
635
|
+
}
|
|
442
636
|
|
|
443
|
-
export { type BrowserName, type CookieQueryStrategy, type CookieSpec, type ExportedCookie, type MultiCookieSpec, type RenderOptions,
|
|
637
|
+
export { type BrowserName, ChromeCookieQueryStrategy, ChromiumCookieQueryStrategy, CompositeCookieQueryStrategy, type CookieQueryStrategy, type CookieSpec, type ExportedCookie, FirefoxCookieQueryStrategy, type MultiCookieSpec, type RenderOptions, SafariCookieQueryStrategy, getCookie };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import{createConsola as ue}from"consola";import{homedir as fe}from"os";import{config as ce}from"dotenv";import{z as F}from"zod";ce();var me=F.object({LOG_LEVEL:F.enum(["debug","info","warn","error"]).default("info"),HOME:F.string().optional().transform(r=>r??process.env.USERPROFILE??"").pipe(F.string().min(1))}),q=me.parse({LOG_LEVEL:process.env.LOG_LEVEL,HOME:fe()});var pe=ue({fancy:!0,formatOptions:{showLogLevel:!1,colors:!0,date:!1,compact:!0,columns:typeof process.stdout.columns=="number"?process.stdout.columns:80},level:q.LOG_LEVEL==="debug"?5:2}),ro=q.LOG_LEVEL==="debug",le=pe,u=le;function M(r,e,o){e?u.success(`${r} succeeded`,o):u.error(`${r} failed`,o)}function p(r,e,o){let t=e instanceof Error?e.message:String(e);u.error(r,{...o,error:t})}function y(r,e,o){u.warn(`[${r}] ${e}`,o)}function g(r){return u.withTag(r)}import{existsSync as ke}from"fs";import{join as A}from"path";import be from"fast-glob";import{homedir as ge}from"os";import{join as de}from"path";var x=(()=>{let r=ge();if(!r)throw new Error("Unable to determine user home directory");return de(r,"Library","Application Support","Google","Chrome")})();import ye from"better-sqlite3";function he(r){try{return new ye(r,{readonly:!0,fileMustExist:!0})}catch(e){throw p("Database open failed",e,{file:r}),e}}function Ce(r){try{return r.close(),Promise.resolve()}catch(e){return p("Database close failed",e),Promise.reject(e instanceof Error?e:new Error("Failed to close database: Unknown error"))}}async function L({file:r,sql:e,params:o,rowFilter:t,rowTransform:s}){let i;try{i=he(r);let c=i.prepare(e).all(o),f=t?c.filter(t):c;return s?f.map(s):f}catch(n){throw p("Database query failed",n,{file:r,sql:e}),n}finally{i&&await Ce(i)}}var B=g("getEncryptedChromeCookie");function we(r){if(typeof r!="string")return!1;let e=r.trim();return e.length===0?!1:ke(e)}async function xe(){let r=[A(x,"Default/Cookies"),A(x,"Profile */Cookies"),A(x,"Profile Default/Cookies")],e=[];for(let o of r){let t=await be(o);e.push(...t)}return B.debug("ChromeCookies","Found cookie files",{count:e.length,files:e}),e}function Ee(r,e){let o=r==="%",t=o?"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE host_key LIKE ?":"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE name = ? AND host_key LIKE ?",s=o?[`%${e}%`]:[r,`%${e}%`];return{sql:t,params:s}}async function Se(r,e,o){try{let{sql:t,params:s}=Ee(e,o);B.debug("ChromeCookies","Executing query",{sql:t,params:s});let i=await L({file:r,sql:t,params:s,rowTransform:n=>({name:n.name,domain:n.host_key,value:n.encrypted_value,expiry:n.expires_utc})});return M("QueryCookies",!0,{file:r,count:i.length}),i}catch(t){return p("Failed to read cookie file",t,{file:r}),[]}}async function j({name:r,domain:e,file:o}){let t=typeof o=="string"&&o.length>0?[o]:await xe();if(t.length===0)return B.debug("ChromeCookies","No cookie files found"),[];let s=[];for(let i of t){if(!we(i)){B.debug("ChromeCookies","Cookie file missing or invalid",{file:i});continue}let n=await Se(i,r,e);s.push(...n)}return B.debug("ChromeCookies","Query complete",{totalCookies:s.length}),s}import{readFileSync as Eo}from"fs";import{join as vo}from"path";import ve from"fast-glob";var Re=g("listChromeProfiles");function V(){let r=ve.sync("./**/Cookies",{cwd:x,absolute:!0});return Re.debug("Found cookie files:",r),r}import{createDecipheriv as Be,pbkdf2 as Oe}from"crypto";import{memoize as H}from"lodash-es";var Pe=H(r=>r.length>=3&&r[0]===118&&r[1]===49&&r[2]===48?r.slice(3):r,r=>r.toString("hex")),Fe=H(r=>{let e=r[r.length-1];return e&&e<=16?r.slice(0,-e):r},r=>r.toString("hex"));function Le(r){let e=[/.*?0t(.+)$/,/.*?1e`(.+)$/,/.*?[`'](.+)$/,/[^\x20-\x7E]*([\x20-\x7E].+)$/];for(let o of e){let s=r.match(o)?.[1]??"";if(s.length>0)return s}return r}async function G(r,e){if(typeof e!="string")throw new Error("password must be a string");if(!Buffer.isBuffer(r))throw new Error("encryptedData must be a Buffer");return new Promise((o,t)=>{Oe(e,"saltysalt",1003,16,"sha1",(s,i)=>{try{if(s){t(new Error("Failed to derive key: "+s.message));return}let n=Pe(r);if(n.length%16!==0){t(new Error("Encrypted data length is not a multiple of 16"));return}let c=Buffer.alloc(16," "),f=Be("aes-128-cbc",i,c);f.setAutoPadding(!1);let m=f.update(n);try{f.final()}catch(d){t(new Error("Failed to finalize decryption: "+d.message));return}m=Fe(m);let l=m.toString("utf8");o(Le(l))}catch(n){t(new Error("Decryption failed: "+n.message))}})})}import{platform as J}from"os";import{exec as Te}from"child_process";import{promisify as Ie}from"util";var De=Ie(Te),$=class extends Error{constructor(o,t,s){super(o);this.command=t;this.originalError=s;this.name="CommandExecutionError"}};async function W(r,e){try{let o=await De(r,{...e,encoding:"utf8"});return{stdout:o.stdout.toString(),stderr:o.stderr.toString()}}catch(o){throw p("Command execution failed",o,{command:r}),new $(o instanceof Error?o.message:String(o),r,o instanceof Error?o:void 0)}}async function Z(){return(await W('security find-generic-password -w -s "Chrome Safe Storage"')).stdout.trim()}async function K(){switch(J()){case"darwin":return Z();default:throw new Error(`Platform ${J()} is not supported`)}}function Ue(r){return typeof r!="number"||r<=0?"Infinity":new Date(r)}function X(r,e,o,t,s,i){return{domain:r,name:e,value:o,expiry:Ue(t),meta:{file:s,browser:"Chrome",decrypted:i}}}var E=class{constructor(){this.logger=g("ChromeCookieQueryStrategy");this.browserName="Chrome"}async queryCookies(e,o,t){try{if(this.logger.info("Querying cookies",{name:e,domain:o,store:t}),process.platform!=="darwin")return this.logger.warn("Platform not supported",{platform:process.platform}),[];let s=t??V(),i=Array.isArray(s)?s:[s];if(i.length===0)return this.logger.warn("No Chrome cookie files found"),[];let n=await K();return(await Promise.all(i.map(f=>this.processFile(f,e,o,n)))).flat()}catch(s){return s instanceof Error?p("Failed to query cookies",s,{name:e,domain:o}):p("Failed to query cookies",new Error(String(s)),{name:e,domain:o}),[]}}async processFile(e,o,t,s){try{let i=await j({name:o,domain:t,file:e}),n={file:e,password:s};return(await Promise.allSettled(i.map(f=>this.processCookie(f,n)))).map(f=>f.status==="fulfilled"?f.value:null).filter(f=>f!==null)}catch(i){return i instanceof Error?this.logger.error("Failed to process cookie file",{error:i,file:e}):this.logger.error("Failed to process cookie file",{error:String(i),file:e}),[]}}async processCookie(e,o){try{let t=Buffer.isBuffer(e.value)?e.value:Buffer.from(String(e.value)),s=await G(t,o.password);return X(e.domain,e.name,s,e.expiry,o.file,!0)}catch(t){return t instanceof Error?this.logger.warn("Failed to decrypt cookie",{error:t}):this.logger.warn("Failed to decrypt cookie",{error:String(t)}),X(e.domain,e.name,e.value.toString("utf-8"),e.expiry,o.file,!1)}}};import{homedir as _e}from"os";import{join as Y}from"path";import ze from"fast-glob";var qe=g("FirefoxCookieQueryStrategy");function Ae(){let r=_e();if(!r)return y("FirefoxCookieQuery","Failed to get home directory"),[];let e=[Y(r,"Library/Application Support/Firefox/Profiles/*/cookies.sqlite"),Y(r,".mozilla/firefox/*/cookies.sqlite")],o=[];for(let t of e){let s=ze.sync(t);o.push(...s)}return qe.debug("Found Firefox cookie files",{files:o}),o}var S=class{constructor(){this.browserName="Firefox"}async queryCookies(e,o,t){let s=t??Ae(),i=Array.isArray(s)?s:[s],n=[];for(let c of i)try{let f=await L({file:c,sql:"SELECT name, value, host as domain, expiry FROM moz_cookies WHERE name = ? AND host LIKE ?",params:[e,`%${o}%`],rowTransform:m=>({name:m.name,value:m.value,domain:m.domain,expiry:m.expiry>0?new Date(m.expiry*1e3):"Infinity",meta:{file:c,browser:"Firefox",decrypted:!1}})});n.push(...f)}catch(f){f instanceof Error?y("FirefoxCookieQuery",`Error reading Firefox cookie file ${c}`,{error:f.message}):y("FirefoxCookieQuery",`Error reading Firefox cookie file ${c}`)}return n}};import{homedir as Ge}from"os";import{join as We}from"path";import{Buffer as Me}from"buffer";import{readFileSync as je}from"fs";import{homedir as Ve}from"os";import{join as He}from"path";import{Buffer as Q}from"buffer";import $e from"destr";import{z as a}from"zod";var T=a.string().trim().min(1,"Domain cannot be empty").refine(r=>/^\.?[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(r),"Invalid domain format"),I=a.string().trim().min(1,"Cookie name cannot be empty").refine(r=>r==="%"||/^[!#$%&'()*+\-.:0-9A-Z \^_`a-z|~]+$/.test(r),"Invalid cookie name format - must contain only valid characters (letters, numbers, and certain symbols) or be '%' for wildcard"),ee=a.string().trim().min(1,"Path cannot be empty").refine(r=>r.startsWith("/"),"Path must start with /").refine(r=>/^\/[!#$%&'()*+,\-./:=@\w~]*$/.test(r),"Invalid path format - must contain only valid URL path characters").default("/"),oe=a.string().trim().transform(r=>$e(r)).pipe(a.any()),re=a.object({name:I,value:oe,domain:T,path:ee,expiry:a.number().int(),creation:a.number().int(),flags:a.number().optional(),version:a.number().int().optional(),port:a.number().int().optional(),comment:a.string().optional(),commentURL:a.string().optional()}),tr=a.object({name:I,domain:T}).strict(),Qe=a.object({file:a.string().trim().min(1,"File path cannot be empty").optional(),browser:a.string().trim().optional(),decrypted:a.boolean().optional(),secure:a.boolean().optional(),httpOnly:a.boolean().optional(),path:ee.optional()}).catchall(a.unknown()).strict(),O=a.object({domain:T,name:I,value:oe,expiry:a.union([a.literal("Infinity"),a.date(),a.number().int().positive("Expiry must be a positive number")]).optional(),meta:Qe.optional()}).strict(),ir=a.object({expiry:a.number().int().optional(),domain:T,name:I,value:a.union([a.string(),a.instanceof(Buffer)])}).strict(),sr=a.object({format:a.enum(["merged","grouped"]).optional(),separator:a.string().optional(),showFilePaths:a.boolean().optional()}).strict(),Ne=a.enum(["Chrome","Firefox","Safari","internal","unknown"]),nr=a.object({browserName:Ne,queryCookies:a.function().args(a.string(),a.string(),a.string().optional()).returns(a.promise(a.array(O)))}).strict();var k=g("BinaryCodableCookie"),D=class{constructor(e){this.version=0;this.url="";this.name="";this.path="";this.value="";this.flags={isSecure:!1,isHTTPOnly:!1,unknown1:!1,unknown2:!1};this.expiration=0;this.creation=0;let o={offset:0,buffer:e};this.decode(o)}decodeUrlValue(e){let o=e,t;do{t=o;try{o=decodeURIComponent(o)}catch{return t}}while(o!==t&&o.includes("%"));return o}decodeJwtPayload(e){let o=e.split(".");if(o.length!==3)return null;try{let t=Q.from(o[1],"base64").toString("utf8"),s=JSON.parse(t);return JSON.stringify(s)}catch{return null}}parseJsonValue(e){try{let o=JSON.parse(e);return JSON.stringify(o)}catch{return null}}processValue(e){let o=this.decodeUrlValue(e);if(o.match(/^ey[A-Za-z0-9_-]+\.ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/)){let t=this.decodeJwtPayload(o);if(typeof t=="string"&&t.length>0)return t}if(o.startsWith("{")||o.startsWith("[")){let t=this.parseJsonValue(o);if(typeof t=="string"&&t.length>0)return t}return o}toCookieRow(){try{let e=this.convertFlags(),o=this.url.replace(/^https?:\/\//,"").replace(/\/.*$/,"")||"uk",t=978307200,s=this.expiration>0?this.expiration+t:this.expiration,i=this.creation>0?this.creation+t:this.creation;return re.parse({name:this.name.replace(/^: /,""),value:this.processValue(this.value)||"",domain:o,path:this.path||"/",expiry:s,creation:i,flags:e,version:this.version,port:this.port,comment:this.comment,commentURL:this.commentURL})}catch{return null}}readNullTerminatedString(e,o){let t=o;for(;t<e.buffer.length&&e.buffer[t]!==0;)t++;return e.buffer.toString("utf8",o,t)||""}readHeader(e){let o=e.buffer.readUInt32LE(e.offset);k.debug("Cookie size:",o),e.offset+=4;let t=e.buffer.readUInt32LE(e.offset);k.debug("Cookie version:",t),e.offset+=4;let s=e.buffer.readUInt32LE(e.offset);k.debug("Cookie flags:",s.toString(2).padStart(8,"0")),e.offset+=4,this.flags={isSecure:(s&1)!==0,isHTTPOnly:(s&4)!==0,unknown1:(s&8)!==0,unknown2:(s&16)!==0};let i=e.buffer.readUInt32LE(e.offset);k.debug("Has port:",i),e.offset+=4;let n={urlOffset:e.buffer.readUInt32LE(e.offset),nameOffset:e.buffer.readUInt32LE(e.offset+4),pathOffset:e.buffer.readUInt32LE(e.offset+8),valueOffset:e.buffer.readUInt32LE(e.offset+12),commentOffset:e.buffer.readUInt32LE(e.offset+16),commentURLOffset:e.buffer.readUInt32LE(e.offset+20)};return k.debug("String offsets:",n),{size:o,hasPort:i,offsets:n}}readTimestamps(e){let o=Q.alloc(8);for(let n=0;n<8;n++)o[n]=e.buffer[e.offset+n];let t=o.readDoubleLE(0);e.offset+=8;let s=Q.alloc(8);for(let n=0;n<8;n++)s[n]=e.buffer[e.offset+n];let i=s.readDoubleLE(0);e.offset+=8,this.expiration=t,this.creation=i}readStrings(e,o,t){k.debug("Reading strings from cookie buffer of size:",o);let i=[{field:"url",offset:t.urlOffset},{field:"name",offset:t.nameOffset},{field:"path",offset:t.pathOffset},{field:"value",offset:t.valueOffset},{field:"comment",offset:t.commentOffset}].filter(n=>n.offset>0).sort((n,c)=>n.offset-c.offset);k.debug("Reading strings in order:",i.map(n=>n.field));for(let n=0;n<i.length;n++){let{field:c,offset:f}=i[n],l=(n<i.length-1?i[n+1].offset:o)-f,d=0+f;for(;d<0+f+l&&e.buffer[d]!==0;)d++;let w=e.buffer.toString("utf8",0+f,d);switch(k.debug(`Read ${c}:`,w),c){case"url":this.url=w;break;case"name":this.name=w;break;case"path":this.path=w;break;case"value":this.value=w;break;case"comment":this.comment=w;break}}}decode(e){let{size:o,hasPort:t,offsets:s}=this.readHeader(e),i=e.offset;e.offset=i+24,this.readTimestamps(e),t>0&&(this.port=e.buffer.readUInt16LE(e.offset),e.offset+=2),e.offset=i,this.readStrings(e,o,s)}convertFlags(){return(this.flags.isSecure?1:0)|(this.flags.isHTTPOnly?4:0)|(this.flags.unknown1?8:0)|(this.flags.unknown2?16:0)}};var h=g("BinaryCodablePage"),v=class v{constructor(e){this.cookies=[];let o={offset:0,buffer:e};this.decode(o)}toCookieRows(){let e=[];for(let o of this.cookies)try{let t=o.toCookieRow();t!==null&&e.push(t)}catch(t){let s=t instanceof Error?t.message:String(t);y("BinaryCookies","Error converting cookie",{error:s})}return e}decode(e){let o=e.buffer.readUInt32BE(e.offset);if(h.debug("Page header:",o.toString(16)),e.offset+=4,o!==v.HEADER)throw new Error("Invalid page header");let t=e.buffer.readUInt32LE(e.offset);h.debug("Cookie count:",t),e.offset+=4;let s=e.offset-8;h.debug("Page start offset:",s);let i=[];for(let c=0;c<t;c++){let f=e.buffer.readUInt32LE(e.offset);i.push(f),h.debug(`Cookie ${c} offset:`,f),e.offset+=4}let n=e.buffer.readUInt32BE(e.offset);if(h.debug("Page footer:",n.toString(16)),e.offset+=4,n!==v.FOOTER)throw new Error("Invalid page footer");for(let c=0;c<t;c++)try{let f=i[c];h.debug(`Reading cookie ${c} at offset:`,f);let m=e.buffer.readUInt32LE(f);if(h.debug(`Cookie ${c} size:`,m),m<48){h.warn(`Invalid cookie size ${m} at index ${c}`);continue}if(f+m>e.buffer.length){h.warn(`Cookie size ${m} at index ${c} would exceed buffer length ${e.buffer.length}`);continue}let l=e.buffer.subarray(f,f+m),d=new D(l);this.cookies.push(d)}catch(f){h.warn("Invalid cookie data",{error:f instanceof Error?f.message:String(f)})}}};v.HEADER=256,v.FOOTER=0;var U=v;var b=g("BinaryCodableCookies"),C=class C{constructor(e){let o={offset:0,buffer:e};this.pages=[],this.metadata={},this.decode(o)}static fromFile(e){let o=je(e);return new C(o)}static fromDefaultPath(){return C.fromFile(C.DEFAULT_COOKIE_PATH)}toCookieRows(){let e=[];for(let o of this.pages)try{let t=o.toCookieRows();Array.isArray(t)&&e.push(...t)}catch(t){let s=t instanceof Error?t.message:String(t);y("BinaryCookies","Error converting page cookies",{error:s})}return e}decode(e){try{let o=e.buffer.subarray(e.offset,e.offset+4);if(e.offset+=4,b.debug("Magic bytes:",o.toString()),!o.equals(C.MAGIC))throw new Error("Missing magic value");let t=e.buffer.readUInt32BE(e.offset);b.debug("Page count:",t),e.offset+=4;let s=[];for(let m=0;m<t;m++){let l=e.buffer.readUInt32BE(e.offset);s.push(l),b.debug(`Page ${m} size:`,l),e.offset+=4}let i=e.offset;b.debug("Starting page data at offset:",i);for(let m of s)try{b.debug("Reading page at offset:",i,"with size:",m);let l=e.buffer.subarray(i,i+m),d=new U(l);this.pages.push(d),i+=m}catch(l){let d=l instanceof Error?l.message:String(l);b.warn("Error decoding page:",{error:d}),i+=m}e.offset=i;let n=e.buffer.readUInt32BE(e.offset);b.debug("Checksum:",n.toString(16)),e.offset+=4;let c=e.buffer.readBigUInt64BE(e.offset);b.debug("Footer:",c.toString(16)),e.offset+=8,c!==C.FOOTER&&y("BinaryCookies","Invalid cookie file format: wrong footer");let f=e.buffer.subarray(e.offset);this.metadata={}}catch(o){let t=o instanceof Error?o.message:String(o);throw y("BinaryCookies","Error decoding binary cookies file",{error:t}),o}}};C.MAGIC=Me.from("cook","utf8"),C.FOOTER=BigInt("0x071720050000004b"),C.DEFAULT_COOKIE_PATH=He(Ve(),"Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookies");var _=C;function te(r){return _.fromFile(r).toCookieRows()}var z=class{constructor(){this.browserName="Safari"}getCookieDbPath(e){return We(e,"Library","Containers","com.apple.Safari","Data","Library","Cookies","Cookies.binarycookies")}formatDomain(e){return e.startsWith(".")?e.slice(1):e}formatExpiry(e){return e<=0?"Infinity":new Date(e*1e3)}isFlagSet(e,o){return typeof e!="number"||isNaN(e)||e<=0?!1:(e&o)===o}formatCreation(e){if(!(typeof e!="number"||isNaN(e)||e<=0))return e*1e3}decodeCookies(e,o,t){try{return te(e).filter(i=>(o==="%"||i.name===o)&&(t==="%"||this.formatDomain(i.domain).includes(t))).map(i=>({domain:this.formatDomain(i.domain),name:i.name,value:Buffer.isBuffer(i.value)?i.value.toString():String(i.value),expiry:this.formatExpiry(i.expiry),meta:{file:e,browser:"Safari",decrypted:!1,secure:this.isFlagSet(i.flags,1),httpOnly:this.isFlagSet(i.flags,4),path:i.path,version:i.version,comment:i.comment,commentURL:i.commentURL,port:i.port,creation:this.formatCreation(i.creation)}}))}catch(s){return s instanceof Error?p("SafariCookieQueryStrategy",`Error decoding ${e}`,{error:s,name:o,domain:t}):p("SafariCookieQueryStrategy",`Error decoding ${e}`,{error:"Unknown error",name:o,domain:t}),[]}}async queryCookies(e,o,t){let s=Ge();if(typeof s!="string"||s.length===0)return p("SafariCookieQueryStrategy","Failed to get home directory"),Promise.resolve([]);let i=t??this.getCookieDbPath(s);return Promise.resolve(this.decodeCookies(i,e||"%",o||"%"))}};async function N(r){if(!r.name||!r.domain)return[];let{name:e,domain:o}=r;if(typeof e!="string"||typeof o!="string")return[];let t=[new E,new S,new z];return(await Promise.allSettled(t.map(i=>i.queryCookies(e,o)))).filter(i=>i.status==="fulfilled").flatMap(i=>i.value)}async function R(r){try{return await N(r)}catch(e){return u.warn("Error querying cookies:",e instanceof Error?e.message:String(e)),[]}}async function ie(r){try{return await new E().queryCookies(r.name,r.domain)}catch(e){return u.warn("Error querying Chrome cookies:",e),[]}}async function se(r){try{return await new S().queryCookies(r.name,r.domain)}catch(e){return u.warn("Error querying Firefox cookies:",e instanceof Error?e.message:String(e)),[]}}import{groupBy as Ze}from"lodash-es";function P(r,e={}){let{format:o="merged",showFilePaths:t=!0,separator:s="; "}=e;if(r.length===0)return o==="merged"?"":[];if(o==="merged")return r.map(n=>n.value).join(s);let i=Ze(r,n=>n.meta?.file??"unknown");return Object.entries(i).map(([n,c])=>{let f=c.map(m=>m.value).join(s);return t?`${n}: ${f}`:f})}async function ne(r,e={}){try{let o=await R(r);if(!Array.isArray(o))return[];let t=o.filter(s=>{let i=O.safeParse(s);return i.success?!0:(u.warn("Invalid cookie format:",i.error.format()),!1)});return P(t,{...e,format:"grouped"})}catch(o){return u.warn("Error getting grouped rendered cookies:",o instanceof Error?o.message:String(o)),[]}}async function ae(r,e){try{let o=await R(r);if(!Array.isArray(o))return"";let t=o.filter(i=>{let n=O.safeParse(i);return n.success?!0:(u.warn("Invalid cookie format:",n.error.format()),!1)}),s=P(t,{...e,format:"merged"});return typeof s=="string"?s:""}catch(o){return u.warn("Error getting merged rendered cookies:",o instanceof Error?o.message:String(o)),""}}export{ie as getChromeCookie,R as getCookie,se as getFirefoxCookie,ne as getGroupedRenderedCookies,ae as getMergedRenderedCookies};
|
|
1
|
+
import{createConsola as Ee}from"consola";import{homedir as ke}from"os";import{config as xe}from"dotenv";import{z as O}from"zod";xe();var Se=O.object({LOG_LEVEL:O.enum(["debug","info","warn","error"]).default("info"),HOME:O.string().optional().transform(t=>t??process.env.USERPROFILE??"").pipe(O.string().min(1))}),M=Se.parse({LOG_LEVEL:process.env.LOG_LEVEL,HOME:ke()});var ve=Ee({fancy:!0,formatOptions:{showLogLevel:!1,colors:!0,date:!1,compact:!0,columns:typeof process.stdout.columns=="number"?process.stdout.columns:80},level:M.LOG_LEVEL==="debug"?5:2}),Pr=M.LOG_LEVEL==="debug",Be=ve,w=Be;function Z(t,e,r){e?w.success(`${t} succeeded`,r):w.error(`${t} failed`,r)}function C(t,e,r){let o=e instanceof Error?e.message:String(e);w.error(t,{...r,error:o})}function v(t,e,r){w.warn(`[${t}] ${e}`,r)}function m(t){return w.withTag(t)}var Pe={info:()=>{},warn:()=>{},error:()=>{},debug:()=>{},success:()=>{},fatal:()=>{},log:()=>{}},d=class{constructor(e,r){this.browserName=r;let o=m(e);this.logger=o||Pe}async queryCookies(e,r,o,i){try{return this.logger.info("Querying cookies",{name:e,domain:r,store:o,force:i}),await this.executeQuery(e,r,o,i)}catch(s){return s instanceof Error?this.logger.error("Failed to query cookies",{error:s.message,browser:this.browserName,strategy:this.constructor.name,name:e,domain:r,store:o,force:i}):this.logger.error("Failed to query cookies",{error:String(s),browser:this.browserName,strategy:this.constructor.name,name:e,domain:r,store:o,force:i}),[]}}};import{existsSync as Ae}from"fs";import{join as W}from"path";import _e from"fast-glob";import Re from"better-sqlite3";var T=m("QuerySqliteThenTransform");function Le(t){return new Promise(e=>setTimeout(e,t))}function Fe(t){if(t instanceof Error){let e=t.message.toLowerCase();return e.includes("database is locked")||e.includes("database locked")||e.includes("sqlite_busy")}return!1}function Oe(t){try{let e=new Re(t,{readonly:!0,fileMustExist:!0});try{e.pragma("journal_mode = WAL"),T.debug("Set WAL mode for database",{file:t})}catch(r){T.warn("Failed to set WAL mode, continuing with default",{file:t,error:r instanceof Error?r.message:String(r)})}return e}catch(e){throw C("Database open failed",e,{file:t}),e}}function Te(t){try{return t.close(),Promise.resolve()}catch(e){return C("Database close failed",e),Promise.reject(e instanceof Error?e:new Error("Failed to close database: Unknown error"))}}async function De(t){let{file:e,sql:r,params:o,rowFilter:i,rowTransform:s}=t,n;try{n=Oe(e);let a=n.prepare(r).all(o),c=i?a.filter(i):a;return s?c.map(s):c}finally{n&&await Te(n)}}async function D(t){let{file:e,sql:r,retryAttempts:o=3}=t,i=[100,500,1e3],s;for(let n=0;n<o;n++)try{let f=await De(t);return n>0&&T.info("Database query succeeded after retry",{file:e,attempt:n+1,totalAttempts:o}),f}catch(f){if(s=f,Fe(f)&&n<o-1){let a=i[n]||1e3;T.warn("Database locked, retrying after delay",{file:e,attempt:n+1,totalAttempts:o,delay:a,error:f instanceof Error?f.message:String(f)}),await Le(a);continue}throw C("Database query failed",f,{file:e,sql:r,attempt:n+1}),f}throw s}import{homedir as Ie,platform as J}from"os";import{join as V}from"path";var b=(()=>{let t=Ie();if(!t)throw new Error("Unable to determine user home directory");switch(J()){case"darwin":return V(t,"Library","Application Support","Google","Chrome");case"win32":return V(t,"AppData","Local","Google","Chrome","User Data");case"linux":return V(t,".config","google-chrome");default:throw new Error(`Platform ${J()} is not supported`)}})();var P=m("getEncryptedChromeCookie");function Ne(t){if(typeof t!="string")return!1;let e=t.trim();return e.length===0?!1:Ae(e)}async function Ue(){let t=[W(b,"Default/Cookies"),W(b,"Profile */Cookies"),W(b,"Profile Default/Cookies")],e=[];for(let r of t){let o=await _e(r);e.push(...o)}return P.debug("ChromeCookies","Found cookie files",{count:e.length,files:e}),e}function $e(t,e){let r=t==="%",o=r?"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE host_key LIKE ?":"SELECT name, encrypted_value, host_key, expires_utc FROM cookies WHERE name = ? AND host_key LIKE ?",i=r?[`%${e}%`]:[t,`%${e}%`];return{sql:o,params:i}}async function qe(t,e,r){try{let{sql:o,params:i}=$e(e,r);P.debug("ChromeCookies","Executing query",{sql:o,params:i});let s=await D({file:t,sql:o,params:i,rowTransform:n=>({name:n.name,domain:n.host_key,value:n.encrypted_value,expiry:n.expires_utc})});return Z("QueryCookies",!0,{file:t,count:s.length}),s}catch(o){return C("Failed to read cookie file",o,{file:t}),[]}}async function I({name:t,domain:e,file:r}){let o=typeof r=="string"&&r.length>0?[r]:await Ue();if(o.length===0)return P.debug("ChromeCookies","No cookie files found"),[];let i=[];for(let s of o){if(!Ne(s)){P.debug("ChromeCookies","Cookie file missing or invalid",{file:s});continue}let n=await qe(s,t,e);i.push(...n)}return P.debug("ChromeCookies","Query complete",{totalCookies:i.length}),i}import{readFileSync as Gr}from"fs";import{join as Jr}from"path";import Qe from"fast-glob";var ze=m("listChromeProfiles");function K(){let t=Qe.sync("./**/Cookies",{cwd:b,absolute:!0});return ze.debug("Found cookie files:",t),t}import{createDecipheriv as Ve,pbkdf2 as We}from"crypto";import{platform as ee}from"os";import{createDecipheriv as Me}from"crypto";function X(t,e){let r=Buffer.from("v10");if(!t.subarray(0,3).equals(r))throw new Error("Not a v10 encrypted cookie");let o=t.subarray(3),i=12,s=16;if(o.length<i+s)throw new Error("Invalid v10 cookie: too short");let n=o.subarray(0,i),f=o.subarray(i,o.length-s),a=o.subarray(o.length-s),c=Me("aes-256-gcm",e,n);return c.setAuthTag(a),Buffer.concat([c.update(f),c.final()]).toString("utf8")}function Y(t){let e=Buffer.from("v10");return t.length>=3&&t.subarray(0,3).equals(e)}function re(t,e){let r=new Map;return o=>{let i=e?e(o):o.toString("hex");if(r.has(i)){let n=r.get(i);if(n!==void 0)return n}let s=t(o);return r.set(i,s),s}}var He=re(t=>t.length>=3&&t[0]===118&&t[1]===49&&t[2]===48?t.slice(3):t,t=>t.toString("hex")),je=re(t=>{let e=t[t.length-1];return e&&e<=16?t.slice(0,-e):t},t=>t.toString("hex"));function Ge(t){let e=t.match(/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/i);if(e)return e[1];let r=[/([A-Z]{3})$/,/([a-z]{2}_[A-Z]{2})$/,/(\d{3}-\d{7}-\d{7})$/];for(let i of r){let s=t.match(i);if(s)return s[1]}let o=[/.*?0t(.+)$/,/.*?1e`(.+)$/,/.*?[`'](.+)$/,/[^\x20-\x7E]*([\x20-\x7E]+)$/,/.*?([a-zA-Z0-9_\-\.]+)$/];for(let i of o){let n=t.match(i)?.[1]??"";if(n.length>0)return n}return t}async function A(t,e,r){if(ee()==="win32"&&Y(t)&&t.length>=31&&Buffer.isBuffer(e))return X(t,e);if(ee()==="darwin"&&!t.slice(0,3).toString().match(/^v\d\d$/))return Promise.resolve(t.toString("utf8"));if(typeof e!="string")throw new Error("password must be a string");if(!Buffer.isBuffer(t))throw new Error("encryptedData must be a Buffer");return new Promise((o,i)=>{We(e,"saltysalt",1003,16,"sha1",(s,n)=>{try{if(s){i(new Error(`Failed to derive key: ${s.message}`));return}let f=He(t);if(f.length%16!==0){i(new Error("Encrypted data length is not a multiple of 16"));return}let a=Buffer.alloc(16," "),c=Ve("aes-128-cbc",n,a);c.setAutoPadding(!1);let l=c.update(f);try{c.final()}catch(be){i(new Error(`Failed to finalize decryption: ${be.message}`));return}l=je(l);let Ce=((r||0)>=24&&l.length>32?l.slice(32):l).toString("utf8");o(Ge(Ce))}catch(f){i(new Error(`Decryption failed: ${f.message}`))}})})}import{platform as ie}from"os";import{exec as Ze}from"child_process";import{promisify as Je}from"util";var Ke=Je(Ze),H=class extends Error{constructor(r,o,i){super(r);this.command=o;this.originalError=i;this.name="CommandExecutionError"}};async function k(t,e){try{let r=await Ke(t,{...e,encoding:"utf8"});return{stdout:r.stdout.toString(),stderr:r.stderr.toString()}}catch(r){throw C("Command execution failed",r,{command:t}),new H(r instanceof Error?r.message:String(r),t,r instanceof Error?r:void 0)}}async function oe(){try{let r=(await k("secret-tool lookup application chrome-libsecret-password-v2 || secret-tool lookup application chrome")).stdout.trim();if(r)return r}catch{}try{let r=(await k(`python3 -c "import keyring; print(keyring.get_password('Chrome Safe Storage', 'Chrome'))"`)).stdout.trim();if(r&&r!=="None")return r}catch{}try{let r=(await k('kwallet-query kdewallet -f "Chrome Safe Storage" -r Chrome')).stdout.trim();if(r)return r}catch{}return"peanuts"}async function te(){return(await k('security find-generic-password -w -s "Chrome Safe Storage"')).stdout.trim()}import{readFileSync as Xe}from"fs";import{join as Ye}from"path";async function er(t){let e=Buffer.from("DPAPI");if(!t.subarray(0,5).equals(e))throw new Error("Invalid DPAPI key prefix");let r=t.subarray(5);if(process.platform==="win32")try{let o=await import("@primno/dpapi").then(i=>i).catch(()=>null);if(o)return o.unprotectData(r)}catch(o){console.warn("DPAPI module not available, using fallback:",o)}throw new Error("Windows DPAPI decryption requires native bindings. Install @primno/dpapi package for Windows support.")}async function se(){try{let t=Ye(b,"Local State"),e=Xe(t,"utf8"),r=JSON.parse(e);if(!r.os_crypt?.encrypted_key)throw new Error("No encrypted key found in Chrome Local State");let o=Buffer.from(r.os_crypt.encrypted_key,"base64");return(await er(o)).toString("latin1")}catch(t){throw new Error(`Failed to retrieve Chrome password on Windows: ${t instanceof Error?t.message:String(t)}`)}}async function _(){switch(ie()){case"darwin":return await te();case"win32":return await se();case"linux":return await oe();default:throw new Error(`Platform ${ie()} is not supported`)}}function rr(t){return typeof t!="number"||t<=0?"Infinity":new Date(t)}function ne(t,e,r,o,i,s){return{domain:t,name:e,value:r,expiry:rr(o),meta:{file:i,browser:"Chrome",decrypted:s}}}var R=class extends d{constructor(){super("ChromeCookieQueryStrategy","Chrome")}async executeQuery(e,r,o,i){let s=["darwin","win32","linux"];if(!s.includes(process.platform))return this.logger.warn("Platform not supported",{platform:process.platform,supportedPlatforms:s}),[];let n=o??K(),f=Array.isArray(n)?n:[n];if(f.length===0)return this.logger.warn("No Chrome cookie files found"),[];let a=await _();return(await Promise.all(f.map(l=>this.processFile(l,e,r,a)))).flat()}async processFile(e,r,o,i){try{let s=await I({name:r,domain:o,file:e}),n=0;try{let c=await import("better-sqlite3"),l=new c.default(e,{readonly:!0});try{let g=l.prepare("SELECT value FROM meta WHERE key = ?").get("version");n=g?Number.parseInt(g.value,10):0}finally{l.close()}}catch(c){this.logger.debug("Could not retrieve meta version, defaulting to 0",{error:c})}let f={file:e,password:i,metaVersion:n};return(await Promise.allSettled(s.map(c=>this.processCookie(c,f)))).map(c=>c.status==="fulfilled"?c.value:null).filter(c=>c!==null)}catch(s){return s instanceof Error?this.logger.error("Failed to process cookie file",{error:s.message,file:e,name:r,domain:o}):this.logger.error("Failed to process cookie file",{error:String(s),file:e,name:r,domain:o}),[]}}async processCookie(e,r){try{let o=Buffer.isBuffer(e.value)?e.value:Buffer.from(String(e.value)),i=await A(o,r.password,r.metaVersion);return ne(e.domain,e.name,i,e.expiry,r.file,!0)}catch(o){return o instanceof Error?this.logger.warn("Failed to decrypt cookie",{error:o}):this.logger.warn("Failed to decrypt cookie",{error:String(o)}),ne(e.domain,e.name,e.value.toString("utf-8"),e.expiry,r.file,!1)}}};import{homedir as tr}from"os";import{join as ue}from"path";import sr from"fast-glob";var ae=m("ProcessDetector");function or(t,e){let r=t.trim().split(/\s+/);if(r.length<2)return null;let o=Number.parseInt(r[1],10);return Number.isNaN(o)?null:{pid:o,command:r.slice(10).join(" ")||e,details:t.trim()}}async function fe(){try{let t="ps aux | grep -i firefox | grep -v grep",{stdout:e}=await k(t);if(!e||e.trim()==="")return[];let r=[],o=e.split(`
|
|
2
|
+
`).filter(i=>i.trim()!=="");for(let i of o){let s=or(i,"firefox");s&&r.push(s)}return ae.debug("Firefox process detection completed",{processCount:r.length,processes:r.map(i=>({pid:i.pid,command:i.command}))}),r}catch(t){return ae.warn("Failed to detect Firefox processes",{error:t instanceof Error?t.message:String(t)}),[]}}function ce(t,e){if(e.length===0)return"";let r=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);return`${o} is currently running (${r} process${r>1?"es":""} detected). For reliable cookie access, consider closing ${o} and trying again. Alternatively, use the --force flag to attempt access despite the lock.`}function ir(t){let e=tr();if(!e)return t.warn("Failed to get home directory"),[];let r=[ue(e,"Library/Application Support/Firefox/Profiles/*/cookies.sqlite"),ue(e,".mozilla/firefox/*/cookies.sqlite")],o=[];for(let i of r){let s=sr.sync(i);o.push(...s)}return t.debug("Found Firefox cookie files",{files:o}),o}var L=class extends d{constructor(){super("FirefoxCookieQueryStrategy","Firefox")}async handleDatabaseLockError(e,r){if(e instanceof Error&&e.message.toLowerCase().includes("database is locked"))try{let o=await fe();if(o.length>0){let i=ce("firefox",o);this.logger.warn("Firefox process conflict detected",{file:r,processCount:o.length,advice:i})}else this.logger.warn("Database locked but no Firefox processes detected",{file:r,suggestion:"Another process may be accessing the database"})}catch(o){this.logger.debug("Failed to check Firefox processes",{error:o instanceof Error?o.message:String(o)})}}async executeQuery(e,r,o,i){let s=o??ir(this.logger),n=Array.isArray(s)?s:[s],f=[];for(let a of n)try{let c=await D({file:a,sql:"SELECT name, value, host as domain, expiry FROM moz_cookies WHERE name = ? AND host LIKE ?",params:[e,`%${r}%`],rowTransform:l=>({name:l.name,value:l.value,domain:l.domain,expiry:l.expiry>0?new Date(l.expiry*1e3):"Infinity",meta:{file:a,browser:"Firefox",decrypted:!1}})});f.push(...c)}catch(c){await this.handleDatabaseLockError(c,a),c instanceof Error?this.logger.warn(`Error reading Firefox cookie file ${a}`,{error:c.message,file:a,name:e,domain:r}):this.logger.warn(`Error reading Firefox cookie file ${a}`,{error:String(c),file:a,name:e,domain:r})}return f}};import{homedir as gr}from"os";import{join as dr}from"path";import{Buffer as ur}from"buffer";import{readFileSync as lr}from"fs";import{homedir as pr}from"os";import{join as mr}from"path";import{Buffer as $}from"buffer";import nr from"destr";import{z as u}from"zod";var N=u.string().trim().min(1,"Domain cannot be empty").refine(t=>/^\.?[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(t),"Invalid domain format"),U=u.string().trim().min(1,"Cookie name cannot be empty").refine(t=>t==="%"||/^[!#$%&'()*+\-.:0-9A-Z \^_`a-z|~]+$/.test(t),"Invalid cookie name format - must contain only valid characters (letters, numbers, and certain symbols) or be '%' for wildcard"),le=u.string().trim().min(1,"Path cannot be empty").refine(t=>t.startsWith("/"),"Path must start with /").refine(t=>/^\/[!#$%&'()*+,\-./:=@\w~]*$/.test(t),"Invalid path format - must contain only valid URL path characters").default("/"),pe=u.string().trim().transform(t=>nr(t)).pipe(u.any()),me=u.object({name:U,value:pe,domain:N,path:le,expiry:u.number().int(),creation:u.number().int(),flags:u.number().optional(),version:u.number().int().optional(),port:u.number().int().optional(),comment:u.string().optional(),commentURL:u.string().optional()}),Mo=u.object({name:U,domain:N}).strict(),ar=u.object({file:u.string().trim().min(1,"File path cannot be empty").optional(),browser:u.string().trim().optional(),decrypted:u.boolean().optional(),secure:u.boolean().optional(),httpOnly:u.boolean().optional(),path:le.optional()}).catchall(u.unknown()).strict(),fr=u.object({domain:N,name:U,value:pe,expiry:u.union([u.literal("Infinity"),u.date(),u.number().int().positive("Expiry must be a positive number")]).optional(),meta:ar.optional()}).strict(),Vo=u.object({expiry:u.number().int().optional(),domain:N,name:U,value:u.union([u.string(),u.instanceof(Buffer)])}).strict(),Wo=u.object({format:u.enum(["merged","grouped"]).optional(),separator:u.string().optional(),showFilePaths:u.boolean().optional()}).strict(),cr=u.enum(["Chrome","Firefox","Safari","internal","unknown"]),Ho=u.object({browserName:cr,queryCookies:u.function().args(u.string(),u.string(),u.string().optional(),u.boolean().optional()).returns(u.promise(u.array(fr)))}).strict();var x=m("BinaryCodableCookie"),q=class{constructor(e){this.version=0;this.url="";this.name="";this.path="";this.value="";this.flags={isSecure:!1,isHTTPOnly:!1,unknown1:!1,unknown2:!1};this.expiration=0;this.creation=0;let r={offset:0,buffer:e};this.decode(r)}decodeUrlValue(e){let r=e,o;do{o=r;try{r=decodeURIComponent(r)}catch{return o}}while(r!==o&&r.includes("%"));return r}decodeJwtPayload(e){let r=e.split(".");if(r.length!==3)return null;try{let o=$.from(r[1],"base64").toString("utf8"),i=JSON.parse(o);return JSON.stringify(i)}catch{return null}}parseJsonValue(e){try{let r=JSON.parse(e);return JSON.stringify(r)}catch{return null}}processValue(e){if(e===null)return"null";if(e===void 0)return"undefined";if($.isBuffer(e))return e.toString();if(typeof e!="string")return String(e);let r=this.decodeUrlValue(e);if(r.match(/^ey[A-Za-z0-9_-]+\.ey[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/)){let o=this.decodeJwtPayload(r);if(typeof o=="string"&&o.length>0)return o}if(r.startsWith("{")||r.startsWith("[")){let o=this.parseJsonValue(r);if(typeof o=="string"&&o.length>0)return o}return r}convertMacTimestamp(e){return e<=0?e:e>=0&&e<=1e9&&Number.isFinite(e)?e+978307200:0}toCookieRow(){try{let e=this.convertFlags(),r=this.url.replace(/^https?:\/\//,"").replace(/\/.*$/,"")||"uk",o=this.convertMacTimestamp(this.expiration),i=this.convertMacTimestamp(this.creation);return me.parse({name:this.name.replace(/^: /,""),value:this.processValue(this.value)||"",domain:r,path:this.path||"/",expiry:o,creation:i,flags:e,version:this.version,port:this.port,comment:this.comment,commentURL:this.commentURL})}catch{return null}}readNullTerminatedString(e,r){let o=r;for(;o<e.buffer.length&&e.buffer[o]!==0;)o++;return e.buffer.toString("utf8",r,o)||""}readHeader(e){let r=e.buffer.readUInt32LE(e.offset);x.debug("Cookie size:",r),e.offset+=4;let o=e.buffer.readUInt32LE(e.offset);x.debug("Cookie version:",o),e.offset+=4;let i=e.buffer.readUInt32LE(e.offset);x.debug("Cookie flags:",i.toString(2).padStart(8,"0")),e.offset+=4,this.flags={isSecure:(i&1)!==0,isHTTPOnly:(i&4)!==0,unknown1:(i&8)!==0,unknown2:(i&16)!==0};let s=e.buffer.readUInt32LE(e.offset);x.debug("Has port:",s),e.offset+=4;let n={urlOffset:e.buffer.readUInt32LE(e.offset),nameOffset:e.buffer.readUInt32LE(e.offset+4),pathOffset:e.buffer.readUInt32LE(e.offset+8),valueOffset:e.buffer.readUInt32LE(e.offset+12),commentOffset:e.buffer.readUInt32LE(e.offset+16),commentURLOffset:e.buffer.readUInt32LE(e.offset+20)};return x.debug("String offsets:",n),{size:r,hasPort:s,offsets:n}}readTimestamps(e){let r=$.alloc(8);for(let n=0;n<8;n++)r[n]=e.buffer[e.offset+n];let o=r.readDoubleLE(0);e.offset+=8;let i=$.alloc(8);for(let n=0;n<8;n++)i[n]=e.buffer[e.offset+n];let s=i.readDoubleLE(0);e.offset+=8,this.expiration=o,this.creation=s}readStrings(e,r,o){x.debug("Reading strings from cookie buffer of size:",r);let s=[{field:"url",offset:o.urlOffset},{field:"name",offset:o.nameOffset},{field:"path",offset:o.pathOffset},{field:"value",offset:o.valueOffset},{field:"comment",offset:o.commentOffset}].filter(n=>n.offset>0).sort((n,f)=>n.offset-f.offset);x.debug("Reading strings in order:",s.map(n=>n.field));for(let n=0;n<s.length;n++){let{field:f,offset:a}=s[n],l=(n<s.length-1?s[n+1].offset:r)-a,g=0+a;for(;g<0+a+l&&e.buffer[g]!==0;)g++;let E=e.buffer.toString("utf8",0+a,g);switch(x.debug(`Read ${f}:`,E),f){case"url":this.url=E;break;case"name":this.name=E;break;case"path":this.path=E;break;case"value":this.value=E;break;case"comment":this.comment=E;break}}}decode(e){let{size:r,hasPort:o,offsets:i}=this.readHeader(e),s=e.offset;e.offset=s+24,this.readTimestamps(e),o>0&&(this.port=e.buffer.readUInt16LE(e.offset),e.offset+=2),e.offset=s,this.readStrings(e,r,i)}convertFlags(){return(this.flags.isSecure?1:0)|(this.flags.isHTTPOnly?4:0)|(this.flags.unknown1?8:0)|(this.flags.unknown2?16:0)}};var h=m("BinaryCodablePage"),B=class B{constructor(e){this.cookies=[];let r={offset:0,buffer:e};this.decode(r)}toCookieRows(){let e=[];for(let r of this.cookies)try{let o=r.toCookieRow();o!==null&&e.push(o)}catch(o){let i=o instanceof Error?o.message:String(o);v("BinaryCookies","Error converting cookie",{error:i})}return e}decode(e){let r=e.buffer.readUInt32BE(e.offset);if(h.debug("Page header:",r.toString(16)),e.offset+=4,r!==B.HEADER)throw new Error("Invalid page header");let o=e.buffer.readUInt32LE(e.offset);h.debug("Cookie count:",o),e.offset+=4;let i=e.offset-8;h.debug("Page start offset:",i);let s=[];for(let f=0;f<o;f++){let a=e.buffer.readUInt32LE(e.offset);s.push(a),h.debug(`Cookie ${f} offset:`,a),e.offset+=4}let n=e.buffer.readUInt32BE(e.offset);if(h.debug("Page footer:",n.toString(16)),e.offset+=4,n!==B.FOOTER)throw new Error("Invalid page footer");for(let f=0;f<o;f++)try{let a=s[f];h.debug(`Reading cookie ${f} at offset:`,a);let c=e.buffer.readUInt32LE(a);if(h.debug(`Cookie ${f} size:`,c),c<48){h.warn(`Invalid cookie size ${c} at index ${f}`);continue}if(a+c>e.buffer.length){h.warn(`Cookie size ${c} at index ${f} would exceed buffer length ${e.buffer.length}`);continue}let l=e.buffer.subarray(a,a+c),g=new q(l);this.cookies.push(g)}catch(a){h.warn("Invalid cookie data",{error:a instanceof Error?a.message:String(a)})}}};B.HEADER=256,B.FOOTER=0;var Q=B;var S=m("BinaryCodableCookies"),y=class y{constructor(e){let r={offset:0,buffer:e};this.pages=[],this.metadata={},this.decode(r)}static fromFile(e){let r=lr(e);return new y(r)}static fromDefaultPath(){return y.fromFile(y.DEFAULT_COOKIE_PATH)}toCookieRows(){let e=[];for(let r of this.pages)try{let o=r.toCookieRows();Array.isArray(o)&&e.push(...o)}catch(o){let i=o instanceof Error?o.message:String(o);v("BinaryCookies","Error converting page cookies",{error:i})}return e}decode(e){try{let r=e.buffer.subarray(e.offset,e.offset+4);if(e.offset+=4,S.debug("Magic bytes:",r.toString()),!r.equals(y.MAGIC))throw new Error("Missing magic value");let o=e.buffer.readUInt32BE(e.offset);S.debug("Page count:",o),e.offset+=4;let i=[];for(let c=0;c<o;c++){let l=e.buffer.readUInt32BE(e.offset);i.push(l),S.debug(`Page ${c} size:`,l),e.offset+=4}let s=e.offset;S.debug("Starting page data at offset:",s);for(let c of i)try{S.debug("Reading page at offset:",s,"with size:",c);let l=e.buffer.subarray(s,s+c),g=new Q(l);this.pages.push(g),s+=c}catch(l){let g=l instanceof Error?l.message:String(l);S.warn("Error decoding page:",{error:g}),s+=c}e.offset=s;let n=e.buffer.readUInt32BE(e.offset);S.debug("Checksum:",n.toString(16)),e.offset+=4;let f=e.buffer.readBigUInt64BE(e.offset);S.debug("Footer:",f.toString(16)),e.offset+=8,f!==y.FOOTER&&v("BinaryCookies","Invalid cookie file format: wrong footer");let a=e.buffer.subarray(e.offset);this.metadata={}}catch(r){let o=r instanceof Error?r.message:String(r);throw v("BinaryCookies","Error decoding binary cookies file",{error:o}),r}}};y.MAGIC=ur.from("cook","utf8"),y.FOOTER=BigInt("0x071720050000004b"),y.DEFAULT_COOKIE_PATH=mr(pr(),"Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookies");var z=y;function ge(t){return z.fromFile(t).toCookieRows()}var F=class extends d{constructor(){super("SafariCookieQueryStrategy","Safari")}getCookieDbPath(e){return dr(e,"Library","Containers","com.apple.Safari","Data","Library","Cookies","Cookies.binarycookies")}formatDomain(e){return e.startsWith(".")?e.slice(1):e}formatExpiry(e){if(e==null){let i=new Date;return Object.defineProperty(i,"valueOf",{value:()=>Number.NaN}),Object.defineProperty(i,"getTime",{value:()=>Number.NaN}),i}return typeof e!="number"||Number.isNaN(e)||e<=0?"Infinity":e<0||e>4102444800?(this.logger.warn("Invalid expiry timestamp, treating as session cookie",{expiry:e}),"Infinity"):new Date(e*1e3)}isFlagSet(e,r){return typeof e!="number"||Number.isNaN(e)||e<=0?!1:(e&r)===r}formatCreation(e){if(typeof e!="number"||Number.isNaN(e)||e<=0)return;if(e<0||e>4102444800){this.logger.warn("Invalid creation timestamp, ignoring",{creation:e});return}return e*1e3}processValue(e){return e===null?"null":e===void 0?"undefined":Buffer.isBuffer(e)?e.toString():String(e)}decodeCookies(e,r,o){try{return ge(e).filter(s=>(r==="%"||s.name===r)&&(o==="%"||this.formatDomain(s.domain).includes(o))).map(s=>({domain:this.formatDomain(s.domain),name:s.name,value:this.processValue(s.value),expiry:this.formatExpiry(s.expiry),meta:{file:e,browser:"Safari",decrypted:!1,secure:this.isFlagSet(s.flags,1),httpOnly:this.isFlagSet(s.flags,4),path:s.path,version:s.version,comment:s.comment,commentURL:s.commentURL,port:s.port,creation:this.formatCreation(s.creation)}}))}catch(i){return i instanceof Error?this.logger.error(`Error decoding ${e}`,{error:i.message,file:e,name:r,domain:o}):this.logger.error(`Error decoding ${e}`,{error:String(i),file:e,name:r,domain:o}),[]}}executeQuery(e,r,o,i){try{this.logger.info("Querying cookies",{name:e,domain:r,store:o});let s=gr();if(typeof s!="string"||s.length===0)return this.logger.error("Failed to get home directory"),Promise.resolve([]);let n=o??this.getCookieDbPath(s);return Promise.resolve(this.decodeCookies(n,e||"%",r||"%"))}catch(s){return s instanceof Error?this.logger.error("Failed to query cookies",{error:s.message,name:e,domain:r}):this.logger.error("Failed to query cookies",{error:String(s),name:e,domain:r}),Promise.resolve([])}}};async function de(t){if(!t.name||!t.domain)return[];let{name:e,domain:r}=t;if(typeof e!="string"||typeof r!="string")return[];let o=[new R,new L,new F];return(await Promise.allSettled(o.map(s=>s.queryCookies(e,r)))).filter(s=>s.status==="fulfilled").flatMap(s=>s.value)}async function hr(t){try{return await de(t)}catch(e){return w.warn("Error querying cookies:",e instanceof Error?e.message:String(e)),[]}}import Cr from"fast-glob";import{homedir as yr,platform as wr}from"os";import{join as p}from"path";function he(t){let e=yr();if(!e)throw new Error("Unable to determine user home directory");let r=wr(),i={chrome:{windows:p(e,"AppData","Local","Google","Chrome","User Data"),macos:p(e,"Library","Application Support","Google","Chrome"),linux:p(e,".config","google-chrome")},chromium:{windows:p(e,"AppData","Local","Chromium","User Data"),macos:p(e,"Library","Application Support","Chromium"),linux:p(e,".config","chromium")},brave:{windows:p(e,"AppData","Local","BraveSoftware","Brave-Browser","User Data"),macos:p(e,"Library","Application Support","BraveSoftware","Brave-Browser"),linux:p(e,".config","BraveSoftware","Brave-Browser")},edge:{windows:p(e,"AppData","Local","Microsoft","Edge","User Data"),macos:p(e,"Library","Application Support","Microsoft Edge"),linux:p(e,".config","microsoft-edge")},opera:{windows:p(e,"AppData","Roaming","Opera Software","Opera Stable"),macos:p(e,"Library","Application Support","com.operasoftware.Opera"),linux:p(e,".config","opera")},vivaldi:{windows:p(e,"AppData","Local","Vivaldi","User Data"),macos:p(e,"Library","Application Support","Vivaldi"),linux:p(e,".config","vivaldi")},whale:{windows:p(e,"AppData","Local","Naver","Naver Whale","User Data"),macos:p(e,"Library","Application Support","Naver","Whale"),linux:p(e,".config","naver-whale")}}[t];if(!i)throw new Error(`Unknown browser: ${t}`);switch(r){case"win32":return i.windows;case"darwin":return i.macos;case"linux":return i.linux;default:throw new Error(`Platform ${r} is not supported`)}}function br(t){return typeof t!="number"||t<=0?"Infinity":new Date(t)}function ye(t,e,r,o,i,s,n){return{domain:t,name:e,value:r,expiry:br(o),meta:{file:i,browser:s.charAt(0).toUpperCase()+s.slice(1),decrypted:n}}}var j=class extends d{constructor(e="chrome"){let r=e.charAt(0).toUpperCase()+e.slice(1);super(`${r}CookieQueryStrategy`,"Chrome"),this.browser=e}listBrowserCookiePaths(){try{let e=he(this.browser),r=Cr.sync("./**/Cookies",{cwd:e,absolute:!0});return this.logger.debug(`Found ${r.length} cookie files for ${this.browser}`),r}catch(e){return this.logger.warn(`Failed to find ${this.browser} cookie files`,{error:e}),[]}}async executeQuery(e,r,o,i){let s=["darwin","win32","linux"];if(!s.includes(process.platform))return this.logger.warn("Platform not supported",{platform:process.platform,supportedPlatforms:s}),[];let n=o??this.listBrowserCookiePaths(),f=Array.isArray(n)?n:[n];if(f.length===0)return this.logger.warn(`No ${this.browser} cookie files found`),[];try{let a=await _();return(await Promise.all(f.map(l=>this.processFile(l,e,r,a)))).flat()}catch(a){return this.logger.error(`Failed to get ${this.browser} password`,{error:a}),[]}}async processFile(e,r,o,i){try{let s=await I({name:r,domain:o,file:e}),n={file:e,password:i,browser:this.browser};return(await Promise.allSettled(s.map(a=>this.processCookie(a,n)))).map(a=>a.status==="fulfilled"?a.value:null).filter(a=>a!==null)}catch(s){return this.logger.error(`Failed to process ${this.browser} cookie file`,{error:s instanceof Error?s.message:String(s),file:e,name:r,domain:o}),[]}}async processCookie(e,r){try{let o=Buffer.isBuffer(e.value)?e.value:Buffer.from(String(e.value)),i=await A(o,r.password);return ye(e.domain,e.name,i,e.expiry,r.file,r.browser,!0)}catch(o){return this.logger.warn(`Failed to decrypt ${this.browser} cookie`,{error:o instanceof Error?o.message:String(o)}),ye(e.domain,e.name,e.value.toString("utf-8"),e.expiry,r.file,r.browser,!1)}}};async function we(t,e,r=[]){return t.length===0?r:(await Promise.all(t.map(async i=>{try{return await e(i)}catch{return r}}))).flat()}var G=class{constructor(e){this.strategies=e;this.logger=m("CompositeCookieQueryStrategy");this.browserName="internal"}handleStrategyError(e,r){e instanceof Error?this.logger.error("Strategy failed",{error:e,strategy:r}):this.logger.error("Strategy failed with unknown error",{error:String(e),strategy:r})}async queryCookies(e,r,o,i){try{return this.logger.info("Querying cookies from all strategies",{name:e,domain:r,store:o,force:i,strategyCount:this.strategies.length}),await we(this.strategies,async s=>{try{return await s.queryCookies(e,r,o,i)}catch(n){return this.handleStrategyError(n,s),[]}},[])}catch(s){return s instanceof Error?this.logger.error("Failed to query cookies",{error:s}):this.logger.error("Failed to query cookies with unknown error",{error:String(s)}),[]}}};export{R as ChromeCookieQueryStrategy,j as ChromiumCookieQueryStrategy,G as CompositeCookieQueryStrategy,L as FirefoxCookieQueryStrategy,F as SafariCookieQueryStrategy,hr as getCookie};
|
|
2
3
|
//# sourceMappingURL=index.js.map
|