Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method to extract nupkg to directory #1456

Merged
merged 4 commits into from
Oct 25, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion src/code/InstallHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Management.Automation;
using System.Net;
Expand Down Expand Up @@ -936,7 +937,11 @@ private bool TryInstallToTempPath(
var pkgVersion = pkgToInstall.Version.ToString();
var tempDirNameVersion = Path.Combine(tempInstallPath, pkgName.ToLower(), pkgVersion);
Directory.CreateDirectory(tempDirNameVersion);
System.IO.Compression.ZipFile.ExtractToDirectory(pathToFile, tempDirNameVersion);

if (!TryExtractToDirectory(pathToFile, tempDirNameVersion, out error))
{
return false;
}

File.Delete(pathToFile);

Expand Down Expand Up @@ -1146,6 +1151,65 @@ private bool TrySaveNupkgToTempPath(
}
}

/// <summary>
/// Extracts files from .nupkg
/// Similar functionality as System.IO.Compression.ZipFile.ExtractToDirectory,
/// but while ExtractToDirectory cannot overwrite files, this method can.
/// </summary>
private bool TryExtractToDirectory(string zipPath, string extractPath, out ErrorRecord error)
{
error = null;
// Normalize the path
extractPath = Path.GetFullPath(extractPath);

// Ensures that the last character on the extraction path is the directory separator char.
// Without this, a malicious zip file could try to traverse outside of the expected extraction path.
if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
{
extractPath += Path.DirectorySeparatorChar;
}

try
{
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
// If a file has one or more parent directories.
if (entry.FullName.Contains(Path.DirectorySeparatorChar) || entry.FullName.Contains(Path.AltDirectorySeparatorChar))
{
// Create the parent directories if they do not already exist
var lastPathSeparatorIdx = entry.FullName.Contains(Path.DirectorySeparatorChar) ?
entry.FullName.LastIndexOf(Path.DirectorySeparatorChar) : entry.FullName.LastIndexOf(Path.AltDirectorySeparatorChar);
var parentDirs = entry.FullName.Substring(0, lastPathSeparatorIdx);
var destinationDirectory = Path.Combine(extractPath, parentDirs);
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
}
}

// Gets the full path to ensure that relative segments are removed.
string destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName));
Fixed Show fixed Hide fixed

entry.ExtractToFile(destinationPath, overwrite:true);
}
}
}
catch (Exception e)
{
error = new ErrorRecord(
new Exception($"Error occured while extracting .nupkg: '{e.Message}'"),
"ErrorExtractingNupkg",
ErrorCategory.OperationStopped,
_cmdletPassedIn);

return false;
}

return true;
}

/// <summary>
/// Moves package files/directories from the temp install path into the final install path location.
/// </summary>
Expand Down