dev
dart 133 lines 4.71 KB
Raw
1 import 'dart:io';
2 import 'package:cw_core/utils/print_verbose.dart';
3 import 'package:path_provider/path_provider.dart';
4 import 'package:path/path.dart' as p;
5
6 String? _rootDirPath;
7
8 const String _tailsData = '/live/persistence/TailsData_unlocked/Persistent';
9
10 bool get isNonAmnesticTails {
11 try {
12 final os = File("/etc/os-release").readAsLinesSync();
13 for (var line in os) {
14 if (!line.startsWith("ID=")) continue;
15 if (!line.contains("tails")) continue;
16 return Directory(_tailsData).existsSync();
17 }
18 } catch (e) {
19 return false;
20 }
21 return false;
22 }
23
24 bool showNotice = true;
25
26 void setRootDirFromEnv() => _rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
27
28 void copyDirectory(Directory source, Directory destination) {
29 source.listSync(recursive: false).forEach((var entity) {
30 if (entity is Directory) {
31 var newDirectory = Directory(p.join(destination.absolute.path, p.basename(entity.path)));
32 newDirectory.createSync(recursive: true);
33 copyDirectory(entity.absolute, newDirectory);
34 } else if (entity is File) {
35 destination.createSync(recursive: true);
36 entity.copySync(p.join(destination.path, p.basename(entity.path)));
37 }
38 });
39 }
40
41 Future<void> linuxSymlinkSharedPreferences() async {
42 if (!Platform.isLinux) return; // nuh-uh
43 final dataHome = Platform.environment["XDG_DATA_HOME"] ??
44 p.join(Platform.environment["HOME"] ?? "", ".local", "share");
45 var cakeNames = ['com.example.cake_wallet', 'cake_wallet'];
46 for (String name in cakeNames) {
47 final oldPath = p.join(dataHome, name);
48 final newPath = p.join((await getAppDir()).path, "_local_share");
49 final oldDir = Directory(oldPath);
50 final oldLink = Link(oldPath);
51 final newDir = Directory(newPath);
52 if (oldDir.existsSync()) {
53 if (oldLink.existsSync()) {
54 printV("not creating, link exists");
55 } else {
56 if (newDir.existsSync()) {
57 newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch ~/ 1000}");
58 }
59 copyDirectory(oldDir, newDir);
60 oldDir.deleteSync(recursive: true);
61 }
62 }
63 if (!oldLink.existsSync()) {
64 oldLink.create(newPath, recursive: true);
65 }
66 if (!newDir.existsSync()) {
67 newDir.createSync(recursive: true);
68 }
69 }
70 }
71
72 Future<Directory> getAppDir() async {
73 const String appName = 'cake_wallet';
74 Directory dir;
75
76 if (_rootDirPath != null && _rootDirPath!.isNotEmpty) {
77 dir = Directory.fromUri(Uri.file(_rootDirPath!));
78 dir.create(recursive: true);
79 } else {
80 if (Platform.isWindows) {
81 dir = await getApplicationSupportDirectory();
82 } else if (Platform.isLinux) {
83 String? appDirPath;
84 try {
85 dir = await getApplicationDocumentsDirectory();
86 appDirPath = '${dir.path}/$appName';
87 } catch (e) {
88 appDirPath = null;
89 }
90 // App will try to use last entry in here, so {distro,package}-specific paths can be
91 // be put as one of last items (tails - I'm looking at you), and other paths can be
92 // added in the order of preference
93 // Which currently is $HOME/.config/$appName - as this is the most standard directory
94 // for storing things that users in general back-up
95 var linuxAppPath = [
96 if (appDirPath != null) appDirPath, // old preferred
97 p.join('/home', Platform.environment['USER'] ?? "null", appName), // old fallback
98 if (Platform.environment['HOME'] != null)
99 p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
100 if (Platform.environment['HOME'] != null)
101 p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
102 if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
103 ];
104
105 String preferredPath = linuxAppPath.last;
106
107 preferredLoop:
108 for (String notSoPreferredPath in linuxAppPath) {
109 if (notSoPreferredPath == linuxAppPath.last) continue;
110 bool useThisOne = Directory(notSoPreferredPath).existsSync();
111 if (useThisOne) {
112 if (showNotice) {
113 showNotice = false;
114 printV(
115 "Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
116 printV(
117 "Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
118 printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
119 }
120 preferredPath = notSoPreferredPath;
121 break preferredLoop;
122 }
123 }
124
125 dir = Directory.fromUri(Uri.file(preferredPath));
126 await dir.create(recursive: true);
127 } else {
128 dir = await getApplicationDocumentsDirectory();
129 }
130 }
131
132 return dir;
133 }