mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-22 07:56:55 +02:00
fix: handle nested legacy iOS Documents path in validation
Detect and recover from stale sandbox container paths embedded inside the current Documents directory. Extracts helper functions for path suffix normalization and joining to reduce duplication.
This commit is contained in:
@@ -20,6 +20,22 @@ final _iosLegacyRelativeDocumentsPattern = RegExp(
|
||||
r'^Data/Application/[A-F0-9\-]+/Documents(?:/(.*))?$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
final _iosNestedLegacyDocumentsPattern = RegExp(
|
||||
r'/Documents/Data/Application/[A-F0-9\-]+/Documents(?:/(.*))?$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
String _normalizeRecoveredIosSuffix(String suffix) {
|
||||
final trimmed = suffix.trim();
|
||||
if (trimmed.isEmpty) return '';
|
||||
return trimmed.startsWith('/') ? trimmed.substring(1) : trimmed;
|
||||
}
|
||||
|
||||
String _joinRecoveredIosPath(String documentsPath, String suffix) {
|
||||
final normalizedSuffix = _normalizeRecoveredIosSuffix(suffix);
|
||||
if (normalizedSuffix.isEmpty) return documentsPath;
|
||||
return '$documentsPath/$normalizedSuffix';
|
||||
}
|
||||
|
||||
/// Checks if a path is a valid writable directory on iOS.
|
||||
/// Returns false if:
|
||||
@@ -43,6 +59,12 @@ bool isValidIosWritablePath(String path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reject stale paths where an old sandbox container path has been embedded
|
||||
// inside the current Documents directory.
|
||||
if (_iosNestedLegacyDocumentsPattern.hasMatch(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure path contains a valid subdirectory (Documents, tmp, Library, etc.)
|
||||
// This handles cases where FilePicker returns container root
|
||||
final containerPattern = RegExp(
|
||||
@@ -70,11 +92,19 @@ Future<String> validateOrFixIosPath(
|
||||
if (!Platform.isIOS) return path;
|
||||
|
||||
final trimmed = path.trim();
|
||||
final docDir = await getApplicationDocumentsDirectory();
|
||||
|
||||
final nestedLegacyMatch = _iosNestedLegacyDocumentsPattern.firstMatch(
|
||||
trimmed,
|
||||
);
|
||||
if (nestedLegacyMatch != null) {
|
||||
return _joinRecoveredIosPath(docDir.path, nestedLegacyMatch.group(1) ?? '');
|
||||
}
|
||||
|
||||
if (isValidIosWritablePath(trimmed)) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
final docDir = await getApplicationDocumentsDirectory();
|
||||
final candidates = <String>[];
|
||||
|
||||
if (trimmed.isNotEmpty) {
|
||||
@@ -92,14 +122,8 @@ Future<String> validateOrFixIosPath(
|
||||
trimmed,
|
||||
);
|
||||
if (legacyRelativeMatch != null) {
|
||||
final suffix = (legacyRelativeMatch.group(1) ?? '').trim();
|
||||
final normalizedSuffix = suffix.startsWith('/')
|
||||
? suffix.substring(1)
|
||||
: suffix;
|
||||
candidates.add(
|
||||
normalizedSuffix.isEmpty
|
||||
? docDir.path
|
||||
: '${docDir.path}/$normalizedSuffix',
|
||||
_joinRecoveredIosPath(docDir.path, legacyRelativeMatch.group(1) ?? ''),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -109,7 +133,7 @@ Future<String> validateOrFixIosPath(
|
||||
final index = trimmed.indexOf(documentsMarker);
|
||||
if (index >= 0) {
|
||||
final suffix = trimmed.substring(index + documentsMarker.length).trim();
|
||||
candidates.add(suffix.isEmpty ? docDir.path : '${docDir.path}/$suffix');
|
||||
candidates.add(_joinRecoveredIosPath(docDir.path, suffix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +205,14 @@ IosPathValidationResult validateIosPath(String path) {
|
||||
);
|
||||
}
|
||||
|
||||
if (_iosNestedLegacyDocumentsPattern.hasMatch(path)) {
|
||||
return const IosPathValidationResult(
|
||||
isValid: false,
|
||||
errorReason:
|
||||
'Invalid iOS app folder path. Please choose App Documents or another local folder.',
|
||||
);
|
||||
}
|
||||
|
||||
// Check for container root without subdirectory
|
||||
final containerPattern = RegExp(
|
||||
r'/var/mobile/Containers/Data/Application/[A-F0-9\-]+',
|
||||
|
||||
Reference in New Issue
Block a user