vaultfs 1.0.1 → 1.0.3
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/bin/vaultfs-npm.js +1 -1
- package/install.bat +261 -0
- package/install.sh +1 -1
- package/package.json +1 -1
- package/src/auth/AuthConfig.java +9 -0
- package/src/auth/AuthManager.java +267 -471
- package/src/filesystem/DiskService.java +3 -0
- package/src/filesystem/FileSystem.java +9 -6
- package/src/sync/FirestoreSync.java +10 -2
- package/src/utils/EnvParser.java +25 -4
- package/version.txt +1 -1
|
@@ -39,6 +39,9 @@ public class DiskService {
|
|
|
39
39
|
|
|
40
40
|
if (existingStartBlockId >= 0) {
|
|
41
41
|
metadata.startBlockId = existingStartBlockId;
|
|
42
|
+
} else if (existingStartBlockId == -2) {
|
|
43
|
+
// Already tracked but disk was full — don't retry allocation
|
|
44
|
+
metadata.startBlockId = -1;
|
|
42
45
|
} else if (metadata.startBlockId == -1) {
|
|
43
46
|
metadata.startBlockId = diskSimulator.allocateFile(metadata.sizeBytes);
|
|
44
47
|
}
|
|
@@ -762,10 +762,13 @@ public class FileSystem {
|
|
|
762
762
|
} else if (entry.isFile()) {
|
|
763
763
|
String filePath = diskService.normalizePath(entry.getAbsolutePath());
|
|
764
764
|
Integer existingBlockId = fileBlockIndex.get(filePath);
|
|
765
|
+
// If file is already tracked (even with -1 = disk full), skip re-allocation
|
|
766
|
+
int blockHint = existingBlockId != null ? existingBlockId : -1;
|
|
767
|
+
boolean alreadyTracked = fileBlockIndex.containsKey(filePath);
|
|
765
768
|
models.FileMetadata metadata = diskService.metadataFromDiskFile(
|
|
766
769
|
entry,
|
|
767
770
|
diskSimulator,
|
|
768
|
-
|
|
771
|
+
alreadyTracked ? Math.max(blockHint, 0) == blockHint ? blockHint : -2 : -1
|
|
769
772
|
);
|
|
770
773
|
diskFiles.add(metadata);
|
|
771
774
|
diskFilePaths.add(filePath);
|
|
@@ -858,7 +861,9 @@ public class FileSystem {
|
|
|
858
861
|
}
|
|
859
862
|
|
|
860
863
|
/** Allows plain names only so commands operate within current directory scope.
|
|
861
|
-
* Rejects path separators, traversal patterns (..), null bytes, and empty/blank names.
|
|
864
|
+
* Rejects path separators, traversal patterns (..), null bytes, and empty/blank names.
|
|
865
|
+
* Note: any name containing ".." is rejected, including "foo..bar", as a
|
|
866
|
+
* defense-in-depth measure against path traversal after separator stripping. */
|
|
862
867
|
private boolean isSimpleName(String name) {
|
|
863
868
|
if (name == null || name.trim().isEmpty()) {
|
|
864
869
|
return false;
|
|
@@ -869,8 +874,6 @@ public class FileSystem {
|
|
|
869
874
|
if (".".equals(name) || "..".equals(name)) {
|
|
870
875
|
return false;
|
|
871
876
|
}
|
|
872
|
-
// Reject names that contain ".." as a substring (e.g. "foo..bar" is fine,
|
|
873
|
-
// but this catches edge cases with path separators stripped earlier)
|
|
874
877
|
if (name.contains("..")) {
|
|
875
878
|
return false;
|
|
876
879
|
}
|
|
@@ -955,7 +958,6 @@ public class FileSystem {
|
|
|
955
958
|
if (AuthManager.isLoggedIn() && syncPending.compareAndSet(false, true)) {
|
|
956
959
|
syncExecutor.submit(() -> {
|
|
957
960
|
try {
|
|
958
|
-
syncPending.set(false);
|
|
959
961
|
String stateContent = new String(
|
|
960
962
|
java.nio.file.Files.readAllBytes(
|
|
961
963
|
java.nio.file.Paths.get(
|
|
@@ -969,8 +971,9 @@ public class FileSystem {
|
|
|
969
971
|
stateContent
|
|
970
972
|
);
|
|
971
973
|
} catch (Exception e) {
|
|
972
|
-
syncPending.set(false);
|
|
973
974
|
Logger.warn("[sync] Cloud sync failed: " + e.getClass().getSimpleName());
|
|
975
|
+
} finally {
|
|
976
|
+
syncPending.set(false);
|
|
974
977
|
}
|
|
975
978
|
});
|
|
976
979
|
}
|
|
@@ -99,7 +99,13 @@ public class FirestoreSync {
|
|
|
99
99
|
if (attempt == maxRetries) {
|
|
100
100
|
Logger.warn("[sync] Push failed after " + maxRetries + " attempts");
|
|
101
101
|
} else {
|
|
102
|
-
|
|
102
|
+
try {
|
|
103
|
+
Thread.sleep((long) Math.pow(2, attempt) * 1000); // Exponential backoff
|
|
104
|
+
} catch (InterruptedException ie) {
|
|
105
|
+
Thread.currentThread().interrupt();
|
|
106
|
+
Logger.warn("[sync] Push interrupted");
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
}
|
|
@@ -136,7 +142,9 @@ public class FirestoreSync {
|
|
|
136
142
|
return null;
|
|
137
143
|
}
|
|
138
144
|
|
|
139
|
-
//
|
|
145
|
+
// Best-effort zeroing: char array can be wiped, but intermediate String
|
|
146
|
+
// instances (strippedKey, jwt) remain in the JVM string pool until GC.
|
|
147
|
+
// For stronger guarantees, consider an HSM or vault-based signer.
|
|
140
148
|
char[] privateKeyChars = privateKey.toCharArray();
|
|
141
149
|
privateKey = null; // Release string reference
|
|
142
150
|
|
package/src/utils/EnvParser.java
CHANGED
|
@@ -11,17 +11,38 @@ public class EnvParser {
|
|
|
11
11
|
private static final Map<String, String> envMap = new HashMap<>();
|
|
12
12
|
|
|
13
13
|
static {
|
|
14
|
-
|
|
14
|
+
// Try user.dir first (development), then VAULTFS_HOME / -Dvaultfs.home (global install)
|
|
15
|
+
String userDir = System.getProperty("user.dir");
|
|
16
|
+
String envPath = userDir + "/.env";
|
|
17
|
+
if (!new java.io.File(envPath).exists()) {
|
|
18
|
+
String home = System.getProperty("vaultfs.home");
|
|
19
|
+
if (home == null || home.isEmpty()) {
|
|
20
|
+
home = System.getenv("VAULTFS_HOME");
|
|
21
|
+
}
|
|
22
|
+
if (home != null && !home.isEmpty()) {
|
|
23
|
+
envPath = home + "/.env";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
loadEnvFile(envPath);
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
private static void loadEnvFile(String path) {
|
|
18
|
-
// Validate the .env path is within
|
|
30
|
+
// Validate the .env path is within an allowed base directory
|
|
19
31
|
try {
|
|
20
32
|
java.io.File envFile = new java.io.File(path);
|
|
21
33
|
String canonicalEnv = envFile.getCanonicalPath();
|
|
22
34
|
String canonicalBase = new java.io.File(System.getProperty("user.dir")).getCanonicalPath();
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
boolean allowed = canonicalEnv.startsWith(canonicalBase);
|
|
36
|
+
if (!allowed) {
|
|
37
|
+
String home = System.getProperty("vaultfs.home");
|
|
38
|
+
if (home == null || home.isEmpty()) home = System.getenv("VAULTFS_HOME");
|
|
39
|
+
if (home != null && !home.isEmpty()) {
|
|
40
|
+
String canonicalHome = new java.io.File(home).getCanonicalPath();
|
|
41
|
+
allowed = canonicalEnv.startsWith(canonicalHome);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!allowed) {
|
|
45
|
+
System.err.println("[EnvParser] Warning: .env path outside allowed directories, skipping");
|
|
25
46
|
return;
|
|
26
47
|
}
|
|
27
48
|
} catch (IOException e) {
|
package/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.3
|