diff --git a/app/src/main/java/deltazero/amarok/PrefMgr.java b/app/src/main/java/deltazero/amarok/PrefMgr.java
index 3d7f39ab..0b8f1cbe 100644
--- a/app/src/main/java/deltazero/amarok/PrefMgr.java
+++ b/app/src/main/java/deltazero/amarok/PrefMgr.java
@@ -52,6 +52,7 @@ public static SharedPreferences getPrefs() {
public static final String FILE_HIDER_MODE = "fileHiderMode";
public static final String IS_ENABLE_AUTO_UPDATE = "isEnableAutoUpdate";
public static final String ENABLE_OBFUSCATE_FILE_HEADER = "enableObfuscateFileHeader";
+ public static final String ENABLE_TRUNCATE_FILE_NAMES = "enableTruncateFileName";
public static final String ENABLE_OBFUSCATE_TEXT_FILE = "enableObfuscateTextFile";
public static final String ENABLE_OBFUSCATE_TEXT_FILE_ENHANCED = "enableObfuscateTextFileEnhanced";
public static final String ENABLE_QUICK_HIDE_SERVICE = "enableQuickHideService";
@@ -139,6 +140,15 @@ public static BaseFileHider getFileHider(Context context) {
};
}
+ public static void setTruncate(boolean shouldTruncate) {
+ mPrefEditor.putBoolean(ENABLE_TRUNCATE_FILE_NAMES, shouldTruncate);
+ mPrefEditor.apply();
+ }
+
+ public static boolean getTruncate() {
+ return mPrefs.getBoolean(ENABLE_TRUNCATE_FILE_NAMES, false);
+ }
+
public static void setFileHiderMode(Class extends BaseFileHider> mode) {
int modeCode;
if (mode == NoneFileHider.class)
diff --git a/app/src/main/java/deltazero/amarok/filehider/ObfuscateFileHider.java b/app/src/main/java/deltazero/amarok/filehider/ObfuscateFileHider.java
index 7c654574..a1b5859d 100644
--- a/app/src/main/java/deltazero/amarok/filehider/ObfuscateFileHider.java
+++ b/app/src/main/java/deltazero/amarok/filehider/ObfuscateFileHider.java
@@ -20,6 +20,7 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Set;
+import java.nio.charset.StandardCharsets;
import deltazero.amarok.PrefMgr;
import deltazero.amarok.utils.FileHiderUtil;
@@ -28,6 +29,7 @@
public class ObfuscateFileHider extends BaseFileHider {
private final static String TAG = "FileHider";
+ private static final int MAX_FILENAME_LENGTH = 255;
private final static int MAX_PROCESS_WHOLE_FILE_SIZE_KB = 10 * 1024; // In KB.
private final static int MAX_PROCESS_ENHANCED_WHOLE_FILE_SIZE_KB = 30 * 1024;
private final static int BASE64_TAG = Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING;
@@ -104,7 +106,6 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
endingMark = FILENAME_FULL_PROCESS_MARK;
// Process filename
- // TODO: 2023/1/9 Handle long filename that invalid to android after Base64 encode
Path newPath = processFilename(path, method, endingMark);
// Process file content
@@ -148,52 +149,26 @@ public FileVisitResult postVisitDirectory(Path dir, IOException e) {
*/
@Nullable
private Path processFilename(Path path, ProcessMethod method, String extraEndingMark) {
- String filename = path.getFileName().toString();
- String newFilename = null;
- Path newPath;
-
- boolean hasEncoded = FileHiderUtil.checkIsMarkInFilename(filename);
-
- if (method == HIDE) {
- if (hasEncoded) {
- Log.d(TAG, "Found encoded name: " + filename + ", skip...");
- return null;
+ String originalFilename = path.getFileName().toString();
+ String encodedFilename = Base64.encodeToString(originalFilename.getBytes(StandardCharsets.UTF_8), Base64.URL_SAFE | Base64.NO_WRAP);
+ if (encodedFilename.length() > MAX_FILENAME_LENGTH) {
+ String truncatedFilename = encodedFilename.substring(0, MAX_FILENAME_LENGTH - extraEndingMark.length()) + extraEndingMark;
+ String fileExtension = "";
+ int extIndex = originalFilename.lastIndexOf('.');
+ if (extIndex > 0) {
+ fileExtension = originalFilename.substring(extIndex);
}
- newFilename = "." + Base64.encodeToString(filename.getBytes(UTF_8), BASE64_TAG) + extraEndingMark;
- Log.d(TAG, "Encode: " + path + " -> " + newFilename);
+ Path parentDir = path.getParent();
+ Path newPath = parentDir.resolve(truncatedFilename + fileExtension);
- } else if (method == UNHIDE) {
- if (!hasEncoded) {
- Log.w(TAG, "Found not coded name: " + filename + ", skip...");
- return null;
- }
-
- try {
- newFilename = new String(
- Base64.decode(FileHiderUtil.stripFilenameExtras(filename), BASE64_TAG), UTF_8
- );
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "Unable to decode: " + filename);
- return null;
- }
-
- Log.d(TAG, "Decode: " + path + " -> " + newFilename);
- }
-
- // Try to rename.
-
- assert newFilename != null;
- newPath = Paths.get(path.getParent().toString(), newFilename);
-
- boolean is_succeeded = path.toFile().renameTo(newPath.toFile());
-
- if (!is_succeeded) {
- Log.w(TAG, "Error when renaming file: " + path + " -> " + newPath);
- return null;
- } else {
+ Log.i(TAG, "Filename exceeded limit, truncated to: " + newPath);
return newPath;
}
+
+ Path parentDir = path.getParent();
+ Path newPath = parentDir.resolve(encodedFilename + extraEndingMark);
+ return newPath;
}
private void processFileHeader(Path path) {
diff --git a/app/src/main/java/deltazero/amarok/ui/settings/ObfuscateFileHiderSettingsActivity.java b/app/src/main/java/deltazero/amarok/ui/settings/ObfuscateFileHiderSettingsActivity.java
index f0a613ec..653d10f3 100644
--- a/app/src/main/java/deltazero/amarok/ui/settings/ObfuscateFileHiderSettingsActivity.java
+++ b/app/src/main/java/deltazero/amarok/ui/settings/ObfuscateFileHiderSettingsActivity.java
@@ -11,7 +11,7 @@
public class ObfuscateFileHiderSettingsActivity extends AmarokActivity {
- private MaterialSwitch swObfuscateFileHeader, swObfuscateTextFile, swObfuscateTextFileEnhanced;
+ private MaterialSwitch swObfuscateFileHeader, swObfuscateTextFile, swObfuscateTextFileEnhanced, swTruncateFileNames;
private MaterialToolbar tbToolBar;
@Override
@@ -22,6 +22,7 @@ protected void onCreate(Bundle savedInstanceState) {
swObfuscateFileHeader = findViewById(R.id.switch_filehider_sw_obfuscate_header);
swObfuscateTextFile = findViewById(R.id.switch_filehider_sw_obfuscate_text);
swObfuscateTextFileEnhanced = findViewById(R.id.switch_filehider_sw_obfuscate_text_enhanced);
+ swTruncateFileNames = findViewById(R.id.filehider_truncate_long_names);
tbToolBar = findViewById(R.id.switch_filehider_tb_toolbar);
// Init UI
@@ -44,6 +45,11 @@ protected void onCreate(Bundle savedInstanceState) {
PrefMgr.setEnableObfuscateTextFileEnhanced(isChecked);
updateUI();
});
+ swTruncateFileNames.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ PrefMgr.setTruncate(isChecked);
+ updateUI();
+ });
+
// Enable back button
tbToolBar.setNavigationOnClickListener(v -> finish());
@@ -62,8 +68,9 @@ private void updateUI() {
swObfuscateFileHeader.setChecked(PrefMgr.getEnableObfuscateFileHeader());
swObfuscateTextFile.setChecked(PrefMgr.getEnableObfuscateTextFile());
swObfuscateTextFileEnhanced.setChecked(PrefMgr.getEnableObfuscateTextFileEnhanced());
+ swTruncateFileNames.setChecked(PrefMgr.getTruncate());
swObfuscateTextFile.setEnabled(PrefMgr.getEnableObfuscateFileHeader());
swObfuscateTextFileEnhanced.setEnabled(PrefMgr.getEnableObfuscateFileHeader() && PrefMgr.getEnableObfuscateTextFile());
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 37e25d04..78afecd4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -162,6 +162,7 @@
Change file permissions to make them unreadable. Root access required. The procedure is immediate.
NoMedia Mode
Simply adds .nomedia to folders. No root access required.
+ Truncates overly long file names for better filesystem compatibility. No root access required.
Welcome
Amarok is a free and freedom tool for hiding private files & applications.\n\nPlease note that Amarok is not an encryption software, but rather a tool for hiding things. We strongly advise against using Amarok to protect confidential files and applications.\n\nDisclaimers: Amarok is provided without any warranties or conditions. The user is fully responsible for any harm or consequences that may arise from using Amarok.
WARNING