Skip to content

Commit 7da8661

Browse files
Jakub SzczyrkJakub Szczyrk
authored andcommitted
Fix too long path for unpacking. Checking path length on Windows
1 parent b23f368 commit 7da8661

21 files changed

+317
-58
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Collections.Generic;
2+
3+
namespace PatchKit.Unity.Patcher.AppData.Local
4+
{
5+
public class MapHashExtractedFiles
6+
{
7+
private static Dictionary<string, string> MapHash = new Dictionary<string, string>();
8+
9+
public static void Clear()
10+
{
11+
MapHash.Clear();
12+
}
13+
14+
public static string Add(string path)
15+
{
16+
string nameHash = HashCalculator.ComputeMD5Hash(path);
17+
MapHash.Add(path, nameHash);
18+
return nameHash;
19+
}
20+
21+
public static bool TryGetHash(string path,out string nameHash)
22+
{
23+
if (MapHash.TryGetValue(path, out nameHash))
24+
{
25+
return true;
26+
}
27+
28+
return false;
29+
}
30+
}
31+
}

Assets/PatchKit Patcher/Scripts/AppData/Local/MapHashExtractedFiles.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/PatchKit Patcher/Scripts/AppData/Local/Pack1Meta.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,7 @@ public static Pack1Meta ParseFromFile(string filename)
3434
public static Pack1Meta Parse(string content)
3535
{
3636
DebugLogger.Log(content);
37-
Pack1Meta pack = JsonConvert.DeserializeObject<Pack1Meta>(content);
38-
foreach (var fileEntry in pack.Files)
39-
{
40-
fileEntry.Hash = HashCalculator.ComputeMD5Hash(fileEntry.Name);
41-
}
42-
43-
return pack;
37+
return JsonConvert.DeserializeObject<Pack1Meta>(content);
4438
}
4539
#endregion
4640

@@ -51,8 +45,6 @@ public class FileEntry
5145
{
5246
public string Name { get; set; }
5347

54-
public string Hash { get; set; }
55-
5648
public string Type { get; set; }
5749

5850
public string Target { get; set; }

Assets/PatchKit Patcher/Scripts/AppData/Local/Pack1Unarchiver.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private void Unpack(Pack1Meta.FileEntry file, Action<double> progress, Cancellat
199199

200200
private void UnpackDirectory(Pack1Meta.FileEntry file, CancellationToken cancellationToken)
201201
{
202-
string destPath = Path.Combine(_destinationDirPath, file.Hash);
202+
string destPath = Path.Combine(_destinationDirPath, MapHashExtractedFiles.Add(file.Name));
203203

204204
DebugLogger.Log("Creating directory " + destPath);
205205
DirectoryOperations.CreateDirectory(destPath, cancellationToken);
@@ -208,7 +208,7 @@ private void UnpackDirectory(Pack1Meta.FileEntry file, CancellationToken cancell
208208

209209
private void UnpackSymlink(Pack1Meta.FileEntry file)
210210
{
211-
string destPath = Path.Combine(_destinationDirPath, file.Hash);
211+
string destPath = Path.Combine(_destinationDirPath, MapHashExtractedFiles.Add(file.Name));
212212
DebugLogger.Log("Creating symlink: " + destPath);
213213
// TODO: how to create a symlink?
214214
}
@@ -230,7 +230,8 @@ private DecompressorCreator ResolveDecompressor(Pack1Meta meta)
230230

231231
private void UnpackRegularFile(Pack1Meta.FileEntry file, Action<double> onProgress, CancellationToken cancellationToken, string destinationDirPath = null)
232232
{
233-
string destPath = Path.Combine(destinationDirPath == null ? _destinationDirPath : destinationDirPath, file.Hash + _suffix);
233+
string destPath = Path.Combine(destinationDirPath == null ? _destinationDirPath : destinationDirPath, MapHashExtractedFiles.Add(file.Name) + _suffix);
234+
234235
DebugLogger.LogFormat("Unpacking regular file {0} to {1}", file, destPath);
235236

236237
if (file.Size == null)
@@ -285,8 +286,7 @@ private void UnpackRegularFile(Pack1Meta.FileEntry file, Action<double> onProgre
285286
}
286287
}
287288
}
288-
//Rename
289-
//File.Move(destPath, finePath);
289+
290290
DebugLogger.Log("File " + file.Name + " unpacked successfully!");
291291
}
292292

Assets/PatchKit Patcher/Scripts/AppData/Local/ZipUnarchiver.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Ionic.Zip;
1+
using System.IO;
2+
using Ionic.Zip;
23
using PatchKit.Unity.Patcher.Debug;
34
using PatchKit.Unity.Patcher.Cancellation;
45

@@ -69,8 +70,13 @@ public void Unarchive(CancellationToken cancellationToken)
6970
private void UnarchiveEntry(ZipEntry zipEntry)
7071
{
7172
DebugLogger.Log(string.Format("Unarchiving entry {0}", zipEntry.FileName));
72-
73-
zipEntry.Extract(_destinationDirPath, ExtractExistingFileAction.OverwriteSilently);
73+
MemoryStream memoryStream = new MemoryStream();
74+
string destPath = Path.Combine(_destinationDirPath, HashCalculator.ComputeMD5Hash(zipEntry.FileName));
75+
zipEntry.Extract(memoryStream);
76+
using (var target = new FileStream(destPath, FileMode.Create))
77+
{
78+
memoryStream.WriteTo(target);
79+
}
7480
}
7581

7682
protected virtual void OnUnarchiveProgressChanged(string name, bool isFile, int entry, int amount, double entryProgress)

Assets/PatchKit Patcher/Scripts/AppUpdater/AppUpdaterContentStrategy.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public void Update(CancellationToken cancellationToken)
5353

5454
DebugLogger.LogVariable(latestVersionId, "latestVersionId");
5555

56+
#if UNITY_STANDALONE_WIN
57+
var checkPathLengthCommand = commandFactory.CreateCheckPathLengthCommandForContent(latestVersionId, _context, cancellationToken);
58+
checkPathLengthCommand.Prepare(_status, cancellationToken);
59+
checkPathLengthCommand.Execute(cancellationToken);
60+
#endif
61+
5662
var checkDiskSpaceCommand = commandFactory.CreateCheckDiskSpaceCommandForContent(latestVersionId, _context, cancellationToken);
5763
checkDiskSpaceCommand.Prepare(_status, cancellationToken);
5864
checkDiskSpaceCommand.Execute(cancellationToken);

Assets/PatchKit Patcher/Scripts/AppUpdater/AppUpdaterDiffStrategy.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ public void Update(CancellationToken cancellationToken)
6868
geolocateCommand.Prepare(_status, cancellationToken);
6969
geolocateCommand.Execute(cancellationToken);
7070

71+
#if UNITY_STANDALONE_WIN
72+
var checkPathLengthCommand = commandFactory.CreateCheckPathLengthCommandForDiff(latestVersionId, _context, cancellationToken);
73+
checkPathLengthCommand.Prepare(_status, cancellationToken);
74+
checkPathLengthCommand.Execute(cancellationToken);
75+
#endif
76+
7177
var checkDiskSpaceCommand = commandFactory.CreateCheckDiskSpaceCommandForDiff(latestVersionId, _context, cancellationToken);
7278
checkDiskSpaceCommand.Prepare(_status, cancellationToken);
7379
checkDiskSpaceCommand.Execute(cancellationToken);

Assets/PatchKit Patcher/Scripts/AppUpdater/Commands/AppUpdaterCommandFactory.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,17 @@ public IGeolocateCommand CreateGeolocateCommand()
133133
var geolocateCommand = new GeolocateCommand();
134134
return geolocateCommand;
135135
}
136+
137+
public ICheckPathLengthCommand CreateCheckPathLengthCommandForDiff(int versionId, AppUpdaterContext context, CancellationToken cancellationToken)
138+
{
139+
AppDiffSummary diffSummary = context.App.RemoteMetaData.GetDiffSummary(versionId, cancellationToken);
140+
return new CheckPathLengthCommand(diffSummary, context.App.LocalDirectory.Path);
141+
}
142+
143+
public ICheckPathLengthCommand CreateCheckPathLengthCommandForContent(int versionId, AppUpdaterContext context, CancellationToken cancellationToken)
144+
{
145+
AppContentSummary contentSummary = context.App.RemoteMetaData.GetContentSummary(versionId, cancellationToken);
146+
return new CheckPathLengthCommand(contentSummary, context.App.LocalDirectory.Path);
147+
}
136148
}
137149
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.IO;
2+
using PatchKit.Api.Models.Main;
3+
using PatchKit.Unity.Patcher.AppUpdater.Status;
4+
using PatchKit.Unity.Patcher.Cancellation;
5+
using PatchKit.Unity.Patcher.Debug;
6+
7+
8+
namespace PatchKit.Unity.Patcher.AppUpdater.Commands
9+
{
10+
public class CheckPathLengthCommand : ICheckPathLengthCommand
11+
{
12+
private static readonly DebugLogger DebugLogger = new DebugLogger(typeof(CheckPathLengthCommand));
13+
14+
private readonly AppContentSummary? _contentSummary;
15+
private readonly AppDiffSummary? _diffSummary;
16+
private readonly string _localDirectoryPath;
17+
private OperationStatus _status;
18+
19+
public CheckPathLengthCommand(AppContentSummary contentSummary, string localDirectoryPath)
20+
{
21+
Checks.ArgumentNotNull(localDirectoryPath, "localDirectoryPath");
22+
23+
_contentSummary = contentSummary;
24+
_localDirectoryPath = localDirectoryPath;
25+
}
26+
27+
public CheckPathLengthCommand(AppDiffSummary diffSummary, string localDirectoryPath)
28+
{
29+
Checks.ArgumentNotNull(localDirectoryPath, "localDirectoryPath");
30+
31+
_diffSummary = diffSummary;
32+
_localDirectoryPath = localDirectoryPath;
33+
}
34+
35+
public void Execute(CancellationToken cancellationToken)
36+
{
37+
_status.IsActive.Value = true;
38+
_status.IsIdle.Value = true;
39+
40+
try
41+
{
42+
string pathFile;
43+
if (UseContentSummary())
44+
{
45+
foreach (AppContentSummaryFile contentSummaryFile in _contentSummary.Value.Files)
46+
{
47+
pathFile = Path.Combine(_localDirectoryPath, contentSummaryFile.Path);
48+
49+
if (pathFile.Length > 259)
50+
{
51+
throw new FilePathTooLongException(string.Format(
52+
"Cannot install file {0}, the destination path length has exceeded Windows path length limit (260).",
53+
pathFile));
54+
}
55+
}
56+
}
57+
else
58+
{
59+
foreach (string contentSummaryFile in _diffSummary.Value.AddedFiles)
60+
{
61+
pathFile = Path.Combine(_localDirectoryPath, contentSummaryFile);
62+
if (pathFile.Length > 259)
63+
{
64+
throw new FilePathTooLongException(string.Format(
65+
"Cannot install file {0}, the destination path length has exceeded Windows path length limit (260).",
66+
pathFile));
67+
}
68+
}
69+
}
70+
}
71+
finally
72+
{
73+
_status.IsActive.Value = false;
74+
}
75+
}
76+
77+
private bool UseContentSummary()
78+
{
79+
return _contentSummary != null;
80+
}
81+
82+
public void Prepare(UpdaterStatus status, CancellationToken cancellationToken)
83+
{
84+
_status = new OperationStatus
85+
{
86+
Weight = {Value = 0.00001},
87+
Description = {Value = "Check path length..."}
88+
};
89+
status.RegisterOperation(_status);
90+
}
91+
}
92+
}

Assets/PatchKit Patcher/Scripts/AppUpdater/Commands/CheckPathLengthCommand.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)