@lvce-editor/main-process 6.19.0 → 6.19.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.
@@ -11,6 +11,7 @@ import { dirname, join as join$1, isAbsolute } from 'node:path';
11
11
  import { homedir, tmpdir } from 'node:os';
12
12
  import { pbkdf2Sync, createDecipheriv, createHash } from 'node:crypto';
13
13
  import { DatabaseSync } from 'node:sqlite';
14
+ import dbus, { Variant } from 'dbus-native';
14
15
  import { MessageChannel } from 'node:worker_threads';
15
16
 
16
17
  const scheme = 'lvce-oss';
@@ -4613,6 +4614,7 @@ const beep$1 = () => {
4613
4614
  };
4614
4615
 
4615
4616
  const chromeV10Prefix = Buffer.from('v10');
4617
+ const chromeV11Prefix = Buffer.from('v11');
4616
4618
  const chromeV10Key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1');
4617
4619
  const chromeV10Iv = Buffer.alloc(16, 0x20);
4618
4620
  const domainHashLength = 32;
@@ -4622,13 +4624,25 @@ class UnsupportedChromeCookieEncryptionError extends Error {
4622
4624
  this.name = 'UnsupportedChromeCookieEncryptionError';
4623
4625
  }
4624
4626
  }
4625
- const decrypt$1 = (hostKey, encryptedValue, databaseVersion) => {
4627
+ const isV11 = encryptedValue => {
4628
+ return Buffer.from(encryptedValue).subarray(0, chromeV11Prefix.length).equals(chromeV11Prefix);
4629
+ };
4630
+ const decrypt$1 = (hostKey, encryptedValue, databaseVersion, chromeSafeStoragePassword) => {
4626
4631
  const buffer = Buffer.from(encryptedValue);
4627
- if (buffer.length <= chromeV10Prefix.length || !buffer.subarray(0, chromeV10Prefix.length).equals(chromeV10Prefix)) {
4632
+ if (buffer.length <= chromeV10Prefix.length) {
4633
+ throw new UnsupportedChromeCookieEncryptionError();
4634
+ }
4635
+ const prefix = buffer.subarray(0, chromeV10Prefix.length);
4636
+ let key;
4637
+ if (prefix.equals(chromeV10Prefix)) {
4638
+ key = chromeV10Key;
4639
+ } else if (prefix.equals(chromeV11Prefix) && chromeSafeStoragePassword !== undefined) {
4640
+ key = pbkdf2Sync(chromeSafeStoragePassword, 'saltysalt', 1, 16, 'sha1');
4641
+ } else {
4628
4642
  throw new UnsupportedChromeCookieEncryptionError();
4629
4643
  }
4630
- const decipher = createDecipheriv('aes-128-cbc', chromeV10Key, chromeV10Iv);
4631
- const plaintext = Buffer.concat([decipher.update(buffer.subarray(chromeV10Prefix.length)), decipher.final()]);
4644
+ const decipher = createDecipheriv('aes-128-cbc', key, chromeV10Iv);
4645
+ const plaintext = Buffer.concat([decipher.update(buffer.subarray(prefix.length)), decipher.final()]);
4632
4646
  if (databaseVersion < 24) {
4633
4647
  return plaintext.toString('utf8');
4634
4648
  }
@@ -4657,17 +4671,17 @@ const getSameSite$1 = sameSite => {
4657
4671
  return 'unspecified';
4658
4672
  }
4659
4673
  };
4660
- const getExpirationDate$1 = expiresUtc => {
4674
+ const getExpirationDate = expiresUtc => {
4661
4675
  const chromeMicroseconds = BigInt(expiresUtc);
4662
4676
  return Number(chromeMicroseconds - chromeEpochOffsetMicroseconds) / Number(microsecondsPerSecond);
4663
4677
  };
4664
- const getValue = (row, databaseVersion) => {
4678
+ const getValue = (row, databaseVersion, chromeSafeStoragePassword) => {
4665
4679
  if (row.value) {
4666
4680
  return row.value;
4667
4681
  }
4668
- return decrypt$1(row.hostKey, row.encryptedValue, databaseVersion);
4682
+ return decrypt$1(row.hostKey, row.encryptedValue, databaseVersion, chromeSafeStoragePassword);
4669
4683
  };
4670
- const convert$1 = (row, databaseVersion, now = Date.now() / 1000) => {
4684
+ const convert$1 = (row, databaseVersion, chromeSafeStoragePassword, now = Date.now() / 1000) => {
4671
4685
  if (!row.hostKey || row.topFrameSiteKey) {
4672
4686
  return undefined;
4673
4687
  }
@@ -4683,13 +4697,13 @@ const convert$1 = (row, databaseVersion, now = Date.now() / 1000) => {
4683
4697
  sameSite: getSameSite$1(row.sameSite),
4684
4698
  secure,
4685
4699
  url: `${secure ? 'https' : 'http'}://${host}/`,
4686
- value: getValue(row, databaseVersion)
4700
+ value: getValue(row, databaseVersion, chromeSafeStoragePassword)
4687
4701
  };
4688
4702
  if (row.hostKey.startsWith('.')) {
4689
4703
  details.domain = row.hostKey;
4690
4704
  }
4691
4705
  if (row.hasExpires) {
4692
- const expirationDate = getExpirationDate$1(row.expiresUtc);
4706
+ const expirationDate = getExpirationDate(row.expiresUtc);
4693
4707
  if (!Number.isFinite(expirationDate) || expirationDate <= now) {
4694
4708
  return undefined;
4695
4709
  }
@@ -4763,6 +4777,79 @@ const readCookies$1 = path => {
4763
4777
  });
4764
4778
  };
4765
4779
 
4780
+ const secretServiceName = 'org.freedesktop.secrets';
4781
+ const secretServicePath = '/org/freedesktop/secrets';
4782
+ const secretServiceInterface = 'org.freedesktop.Secret.Service';
4783
+ const secretCollectionInterface = 'org.freedesktop.Secret.Collection';
4784
+ const secretItemInterface = 'org.freedesktop.Secret.Item';
4785
+ const propertiesInterface = 'org.freedesktop.DBus.Properties';
4786
+ const defaultCollectionPath = '/org/freedesktop/secrets/aliases/default';
4787
+ const chromeSafeStorageLabel = 'Chrome Safe Storage';
4788
+ const getProperties = async (bus, path) => {
4789
+ return bus.getService(secretServiceName).getInterface(path, propertiesInterface);
4790
+ };
4791
+ const findChromeSafeStorageItem = async (bus, service) => {
4792
+ const [unlocked, locked] = await service.SearchItems({
4793
+ application: 'chrome'
4794
+ });
4795
+ const matchingItems = [...unlocked, ...locked];
4796
+ if (matchingItems.length > 0) {
4797
+ return matchingItems[0];
4798
+ }
4799
+ const collectionProperties = await getProperties(bus, defaultCollectionPath);
4800
+ const items = await collectionProperties.Get(secretCollectionInterface, 'Items');
4801
+ for (const item of items) {
4802
+ const itemProperties = await getProperties(bus, item);
4803
+ const label = await itemProperties.Get(secretItemInterface, 'Label');
4804
+ if (label === chromeSafeStorageLabel) {
4805
+ return item;
4806
+ }
4807
+ }
4808
+ throw new Error('Chrome Safe Storage password was not found in the Linux keyring');
4809
+ };
4810
+ const unlockItem = async (service, item) => {
4811
+ const [unlocked, prompt] = await service.Unlock([item]);
4812
+ if (unlocked.includes(item)) {
4813
+ return;
4814
+ }
4815
+ if (prompt !== '/') {
4816
+ throw new Error('Chrome Safe Storage is locked; unlock the desktop keyring and try again');
4817
+ }
4818
+ throw new Error('Chrome Safe Storage could not be unlocked');
4819
+ };
4820
+ const readPassword = async bus => {
4821
+ const service = await bus.getService(secretServiceName).getInterface(secretServicePath, secretServiceInterface);
4822
+ const [, sessionPath] = await service.OpenSession('plain', new Variant('s', ''));
4823
+ const item = await findChromeSafeStorageItem(bus, service);
4824
+ let secrets;
4825
+ try {
4826
+ secrets = await service.GetSecrets([item], sessionPath);
4827
+ } catch {
4828
+ await unlockItem(service, item);
4829
+ secrets = await service.GetSecrets([item], sessionPath);
4830
+ }
4831
+ const secret = secrets[item];
4832
+ if (!secret) {
4833
+ throw new Error('Chrome Safe Storage password was not returned by the Linux keyring');
4834
+ }
4835
+ return Buffer.from(secret[2]).toString('utf8');
4836
+ };
4837
+ const getErrorMessage = error => {
4838
+ return error instanceof Error ? error.message : String(error);
4839
+ };
4840
+ const getChromeSafeStoragePassword = async () => {
4841
+ const bus = dbus.sessionBus({
4842
+ timeout: 5000
4843
+ });
4844
+ try {
4845
+ return await readPassword(bus);
4846
+ } catch (error) {
4847
+ throw new Error(`Failed to read Chrome Safe Storage password: ${getErrorMessage(error)}`);
4848
+ } finally {
4849
+ await bus.close();
4850
+ }
4851
+ };
4852
+
4766
4853
  const isValidProfileDirectory = value => {
4767
4854
  return value !== '' && value !== '.' && value !== '..' && !value.includes('/') && !value.includes('\\');
4768
4855
  };
@@ -4972,12 +5059,14 @@ const importFromDirectory$1 = async (chromeDataDirectory, session) => {
4972
5059
  rows,
4973
5060
  version
4974
5061
  } = readCookies$1(profile.cookieDatabasePath);
5062
+ const requiresChromeSafeStoragePassword = rows.some(row => !row.value && isV11(row.encryptedValue));
5063
+ const chromeSafeStoragePassword = requiresChromeSafeStoragePassword ? await getChromeSafeStoragePassword() : undefined;
4975
5064
  const cookies = [];
4976
5065
  let skipped = 0;
4977
5066
  let unsupportedEncryption = 0;
4978
5067
  for (const row of rows) {
4979
5068
  try {
4980
- const cookie = convert$1(row, version);
5069
+ const cookie = convert$1(row, version, chromeSafeStoragePassword);
4981
5070
  if (cookie) {
4982
5071
  cookies.push(cookie);
4983
5072
  } else {
@@ -6849,7 +6938,6 @@ const open2 = async (options, url) => {
6849
6938
  }
6850
6939
  };
6851
6940
 
6852
- const millisecondsExpirySchemaVersion = 16;
6853
6941
  const getSameSite = sameSite => {
6854
6942
  switch (sameSite) {
6855
6943
  case 0:
@@ -6862,13 +6950,10 @@ const getSameSite = sameSite => {
6862
6950
  return 'unspecified';
6863
6951
  }
6864
6952
  };
6865
- const getExpirationDate = (expiry, databaseVersion) => {
6866
- return databaseVersion >= millisecondsExpirySchemaVersion ? expiry / 1000 : expiry;
6867
- };
6868
6953
  const getUrlHost = host => {
6869
6954
  return host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
6870
6955
  };
6871
- const convert = (row, databaseVersion, now = Date.now() / 1000) => {
6956
+ const convert = (row, now = Date.now() / 1000) => {
6872
6957
  if (!row.host || row.originAttributes) {
6873
6958
  return undefined;
6874
6959
  }
@@ -6876,7 +6961,7 @@ const convert = (row, databaseVersion, now = Date.now() / 1000) => {
6876
6961
  if (!host) {
6877
6962
  return undefined;
6878
6963
  }
6879
- const expirationDate = getExpirationDate(row.expiry, databaseVersion);
6964
+ const expirationDate = row.expiry;
6880
6965
  if (!Number.isFinite(expirationDate) || expirationDate <= now) {
6881
6966
  return undefined;
6882
6967
  }
@@ -7042,13 +7127,12 @@ const getInfo = () => {
7042
7127
  const importFromDirectory = async (firefoxDataDirectory, session) => {
7043
7128
  const profile = getActiveProfile(firefoxDataDirectory);
7044
7129
  const {
7045
- rows,
7046
- version
7130
+ rows
7047
7131
  } = readCookies(profile.cookieDatabasePath);
7048
7132
  const cookies = [];
7049
7133
  let skipped = 0;
7050
7134
  for (const row of rows) {
7051
- const cookie = convert(row, version);
7135
+ const cookie = convert(row);
7052
7136
  if (cookie) {
7053
7137
  cookies.push(cookie);
7054
7138
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/main-process",
3
- "version": "6.19.0",
3
+ "version": "6.19.2",
4
4
  "keywords": [
5
5
  "lvce-editor",
6
6
  "electron"
@@ -14,6 +14,7 @@
14
14
  "type": "module",
15
15
  "main": "dist/mainProcessMain.js",
16
16
  "dependencies": {
17
+ "dbus-native": "^0.15.1",
17
18
  "electron": "43.2.0"
18
19
  },
19
20
  "engines": {