extractMatchingEntry method
File?
extractMatchingEntry({
- required File archiveFile,
- required Directory outputDir,
- required ArchiveSelectionContext selection,
Extracts the entry matching canonicalName from a .tar.gz archive.
Returns the extracted file, or null if no matching entry was found.
The file is written to outputDir.
Validates:
- Entry paths are safe (no traversal, no absolute paths)
- Only regular files are selected (symlinks and hard links rejected)
- At most one matching entry exists
Implementation
File? extractMatchingEntry({
required File archiveFile,
required Directory outputDir,
required ArchiveSelectionContext selection,
}) {
final bytes = archiveFile.readAsBytesSync();
final gzBytes = gzip.decode(bytes);
final archive = TarDecoder().decodeBytes(gzBytes);
ArchiveFile? matched;
var matchCount = 0;
for (final entry in archive.files) {
if (!entry.isFile) continue;
final basename = p.basename(entry.name);
final matches = matchesLibraryName(
basename,
canonicalName: selection.canonicalName,
acceptVersionedNames: selection.acceptVersionedNames,
);
if (matches) {
matched = entry;
matchCount++;
}
}
if (matchCount > 1) {
throw StateError(
'Multiple entries match ${selection.canonicalName} '
'in ${archiveFile.path}',
);
}
if (matched == null) return null;
// Validate path safety.
if (matched.name.startsWith('/') || matched.name.contains('..')) {
throw StateError('Unsafe archive entry path: ${matched.name}');
}
// Write the selected entry.
outputDir.createSync(recursive: true);
final outFile = File(p.join(outputDir.path, p.basename(matched.name)));
outFile.writeAsBytesSync(matched.content);
return outFile;
}