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

Ensure Unique Temporary File Names and Guaranteed Clean-up #1044

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,66 @@ namespace PnP.Framework.Provisioning.ObjectHandlers.Extensions
{
internal static class UserResourceExtensions
{

public static ProvisioningTemplate SaveResourceValues(ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
{
var tempFolder = Path.GetTempPath();
List<Tuple<string, int, string>> resourceTokens = creationInfo.ResourceTokens;

var languages = resourceTokens.Select(t => t.Item2).Distinct();
foreach (int language in languages)
{
var culture = new CultureInfo(language);
// Use a unique file name by appending a GUID
var uniqueFileName = $"{creationInfo.ResourceFilePrefix}.{culture.Name}.{Guid.NewGuid()}.resx";
var resourceFileName = Path.Combine(tempFolder, uniqueFileName);
var resourceFileToDelete = resourceFileName;

var resourceFileName = Path.Combine(tempFolder, $"{creationInfo.ResourceFilePrefix}.{culture.Name}.resx");
if (System.IO.File.Exists(resourceFileName))
try
{
// Read existing entries, if any
using (ResourceReader resxReader = new ResourceReader(resourceFileName))
//using (ResXResourceReader resxReader = new ResXResourceReader(resourceFileName))
if (System.IO.File.Exists(resourceFileName))
{
foreach (DictionaryEntry entry in resxReader)
// Read existing entries, if any
using (ResourceReader resxReader = new ResourceReader(resourceFileName))
{
// find if token is already there
var existingToken = resourceTokens.FirstOrDefault(t => t.Item1 == entry.Key.ToString() && t.Item2 == language);
if (existingToken == null)
foreach (DictionaryEntry entry in resxReader)
{
resourceTokens.Add(new Tuple<string, int, string>(entry.Key.ToString(), language, entry.Value as string));
// find if token is already there
var existingToken = resourceTokens.FirstOrDefault(t => t.Item1 == entry.Key.ToString() && t.Item2 == language);
if (existingToken == null)
{
resourceTokens.Add(new Tuple<string, int, string>(entry.Key.ToString(), language, entry.Value as string));
}
}
}
}
}

// Create new resource file - use implementation copied from .Net Framework cause otherwise we end up with binary serialized files
//using (ResourceWriter resx = new ResourceWriter(resourceFileName))
using (ResXResourceWriter resx = new ResXResourceWriter(resourceFileName))
{
foreach (var token in resourceTokens.Where(t => t.Item2 == language))
// Create new resource file - use implementation copied from .Net Framework cause otherwise we end up with binary serialized files
//using (ResourceWriter resx = new ResourceWriter(resourceFileName))
using (ResXResourceWriter resx = new ResXResourceWriter(resourceFileName))
{

resx.AddResource(token.Item1, token.Item3);
foreach (var token in resourceTokens.Where(t => t.Item2 == language))
{
resx.AddResource(token.Item1, token.Item3);
}
}
}

template.Localizations.Add(new Localization() { LCID = language, Name = culture.NativeName, ResourceFile = $"{creationInfo.ResourceFilePrefix}.{culture.Name}.resx" });
template.Localizations.Add(new Localization() { LCID = language, Name = culture.NativeName, ResourceFile = uniqueFileName });

// Persist the file using the connector
using (FileStream stream = System.IO.File.Open(resourceFileName, FileMode.Open))
// Persist the file using the connector
using (FileStream stream = System.IO.File.Open(resourceFileName, FileMode.Open))
{
creationInfo.FileConnector.SaveFileStream(uniqueFileName, stream);
}
}
finally
{
creationInfo.FileConnector.SaveFileStream($"{creationInfo.ResourceFilePrefix}.{culture.Name}.resx", stream);
// Ensure the temp resx file is deleted even if an exception occurs
if (System.IO.File.Exists(resourceFileToDelete))
{
System.IO.File.Delete(resourceFileToDelete);
}
}
// remove the temp resx file
System.IO.File.Delete(resourceFileName);
}

return template;
}

Expand Down Expand Up @@ -140,8 +149,8 @@ public static bool PersistResourceValue(List siteList, Guid viewId, string token
}

clientContext.PendingRequest.RequestExecutor.WebRequest.Headers["Accept-Language"] = acceptLanguage;

}

return returnValue;
}

Expand All @@ -155,8 +164,6 @@ public static bool ContainsResourceToken(this string value)
{
return false;
}

}
}

}
}