Skip to content

Commit

Permalink
Fixed a bug in ArchiveExtractor that caused it to fail on case-insens…
Browse files Browse the repository at this point in the history
…itive file systems.
  • Loading branch information
MikeThomsen committed Oct 26, 2019
1 parent b50455d commit 5a5eb07
Showing 1 changed file with 54 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private void prepDestination(File path, boolean directory) throws IOException {
if (!path.getParentFile().exists()) {
path.getParentFile().mkdirs();
}
if(!path.getParentFile().canWrite()) {
if (!path.getParentFile().canWrite()) {
throw new AccessDeniedException(
String.format("Could not get write permissions for '%s'", path.getParentFile().getAbsolutePath()));
}
Expand All @@ -60,17 +60,17 @@ public void extract(String archive, String destinationDirectory) throws ArchiveE
try (FileInputStream fis = new FileInputStream(archiveFile)) {
if ("msi".equals(FileUtils.getExtension(archiveFile.getAbsolutePath()))) {
String command = "msiexec /a " + archiveFile.getAbsolutePath() + " /qn TARGETDIR=\""
+ destinationDirectory + "\"";
+ destinationDirectory + "\"";
Process child = Runtime.getRuntime().exec(command);
try {
int result = child.waitFor();
if (result != 0) {
throw new ArchiveExtractionException(
"Could not extract " + archiveFile.getAbsolutePath() + "; return code " + result);
"Could not extract " + archiveFile.getAbsolutePath() + "; return code " + result);
}
} catch (InterruptedException e) {
throw new ArchiveExtractionException(
"Unexpected interruption of while waiting for extraction process", e);
"Unexpected interruption of while waiting for extraction process", e);
}
} else if ("zip".equals(FileUtils.getExtension(archiveFile.getAbsolutePath()))) {
ZipFile zipFile = new ZipFile(archiveFile);
Expand All @@ -80,7 +80,7 @@ public void extract(String archive, String destinationDirectory) throws ArchiveE
ZipEntry entry = entries.nextElement();
final File destPath = new File(destinationDirectory + File.separator + entry.getName());
prepDestination(destPath, entry.isDirectory());
if(!entry.isDirectory()){
if (!entry.isDirectory()) {
InputStream in = null;
OutputStream out = null;
try {
Expand All @@ -104,16 +104,18 @@ public void extract(String archive, String destinationDirectory) throws ArchiveE
tarIn = new TarArchiveInputStream(new GzipCompressorInputStream(fis));

TarArchiveEntry tarEntry = tarIn.getNextTarEntry();
String canonicalDestinationDirectory = new File(destinationDirectory).getCanonicalPath();
while (tarEntry != null) {
// Create a file for this tarEntry
final File destPath = new File(destinationDirectory + File.separator + tarEntry.getName());
prepDestination(destPath, tarEntry.isDirectory());
if (!destPath.getCanonicalPath().startsWith(canonicalDestinationDirectory)) {
throw new IOException(
"Expanding " + tarEntry.getName() + " would create file outside of " + canonicalDestinationDirectory
);


if (!startsWithPath(destPath.getCanonicalPath(), destinationDirectory)) {
throw new IOException(
"Expanding " + tarEntry.getName() + " would create file outside of " + destinationDirectory
);
}

if (!tarEntry.isDirectory()) {
destPath.createNewFile();
boolean isExecutable = (tarEntry.getMode() & 0100) > 0;
Expand All @@ -139,4 +141,46 @@ public void extract(String archive, String destinationDirectory) throws ArchiveE
+ "'", e);
}
}

/**
* Do multiple file system checks that should enable the plugin to work on any file system
* whether or not it's case sensitive or not.
*
* @param destPath
* @param destDir
* @return
*/
private boolean startsWithPath(String destPath, String destDir) {
if (destDir.startsWith(destDir)) {
return true;
} else if (destDir.length() > destPath.length()) {
return false;
} else {
/*
* The first check should handle case-sensitive file systems. We need this
* in order to weed out case-sensitive file systems with a non-existent path
* that slipped through the first test.
*/
if (new File(destPath).exists() && !(new File(destPath.toLowerCase()).exists())) {
return false;
}

boolean retVal = true;
for (int index = 0; index < destDir.length(); index++) {
char left = destPath.charAt(index);
char right = destDir.charAt(index);

if (left != right) {
char leftUc = Character.toUpperCase(left);
char rightUc = Character.toUpperCase(right);

if (leftUc != rightUc) {
retVal = false;
}
}
}

return retVal;
}
}
}

0 comments on commit 5a5eb07

Please sign in to comment.