Skip to content
85 changes: 0 additions & 85 deletions src/System.Management.Automation/engine/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,96 +1391,11 @@ internal static bool Succeeded(int hresult)
return hresult >= 0;
}

// Attempt to determine the existing encoding
internal static Encoding GetEncoding(string path)
{
if (!File.Exists(path))
{
return ClrFacade.GetDefaultEncoding();
}

byte[] initialBytes = new byte[100];
int bytesRead = 0;

try
{
using (FileStream stream = System.IO.File.OpenRead(path))
{
using (BinaryReader reader = new BinaryReader(stream))
{
bytesRead = reader.Read(initialBytes, 0, 100);
}
}
}
catch (IOException)
{
return ClrFacade.GetDefaultEncoding();
}

// Test for four-byte preambles
string preamble = null;
Encoding foundEncoding = ClrFacade.GetDefaultEncoding();

if (bytesRead > 3)
{
preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2], initialBytes[3]);

if (encodingMap.TryGetValue(preamble, out foundEncoding))
{
return foundEncoding;
}
}

// Test for three-byte preambles
if (bytesRead > 2)
{
preamble = string.Join("-", initialBytes[0], initialBytes[1], initialBytes[2]);
if (encodingMap.TryGetValue(preamble, out foundEncoding))
{
return foundEncoding;
}
}

// Test for two-byte preambles
if (bytesRead > 1)
{
preamble = string.Join("-", initialBytes[0], initialBytes[1]);
if (encodingMap.TryGetValue(preamble, out foundEncoding))
{
return foundEncoding;
}
}

// Check for binary
string initialBytesAsAscii = System.Text.Encoding.ASCII.GetString(initialBytes, 0, bytesRead);
if (initialBytesAsAscii.IndexOfAny(nonPrintableCharacters) >= 0)
{
return Encoding.Unicode;
}

return utf8NoBom;
}

// BigEndianUTF32 encoding is possible, but requires creation
internal static readonly Encoding BigEndianUTF32Encoding = new UTF32Encoding(bigEndian: true, byteOrderMark: true);
// [System.Text.Encoding]::GetEncodings() | Where-Object { $_.GetEncoding().GetPreamble() } |
// Add-Member ScriptProperty Preamble { $this.GetEncoding().GetPreamble() -join "-" } -PassThru |
// Format-Table -Auto
internal static readonly Dictionary<string, Encoding> encodingMap =
new Dictionary<string, Encoding>()
{
{ "255-254", Encoding.Unicode },
{ "254-255", Encoding.BigEndianUnicode },
{ "255-254-0-0", Encoding.UTF32 },
{ "0-0-254-255", BigEndianUTF32Encoding },
{ "239-187-191", Encoding.UTF8 },
};

internal static readonly char[] nonPrintableCharacters = {
(char) 0, (char) 1, (char) 2, (char) 3, (char) 4, (char) 5, (char) 6, (char) 7, (char) 8,
(char) 11, (char) 12, (char) 14, (char) 15, (char) 16, (char) 17, (char) 18, (char) 19, (char) 20,
(char) 21, (char) 22, (char) 23, (char) 24, (char) 25, (char) 26, (char) 28, (char) 29, (char) 30,
(char) 31, (char) 127, (char) 129, (char) 141, (char) 143, (char) 144, (char) 157 };

internal static readonly UTF8Encoding utf8NoBom =
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1068,22 +1068,7 @@ internal TranscriptionOption()
/// <summary>
/// The path that this transcript is being logged to.
/// </summary>
internal string Path
{
get
{
return _path;
}

set
{
_path = value;
// Get the encoding from the file, or default (UTF8-NoBom)
Encoding = Utils.GetEncoding(value);
}
}

private string _path;
internal string Path { get; set; }

/// <summary>
/// Any output to log for this transcript.
Expand All @@ -1101,19 +1086,20 @@ internal string Path
/// </summary>
internal bool IncludeInvocationHeader { get; set; }

/// <summary>
/// The encoding of this transcript, so that appending to it
/// can be done correctly.
/// </summary>
internal Encoding Encoding { get; private set; }

/// <summary>
/// Logs buffered content to disk. We use this instead of File.AppendAllLines
/// so that we don't need to pay seek penalties all the time, and so that we
/// don't need append permission to our own files.
/// </summary>
internal void FlushContentToDisk()
{
static Encoding GetPathEncoding(string path)
{
using StreamReader reader = new StreamReader(path, Utils.utf8NoBom, detectEncodingFromByteOrderMarks: true);
_ = reader.Read();
return reader.CurrentEncoding;
}

lock (OutputBeingLogged)
{
if (!_disposed)
Expand All @@ -1122,11 +1108,13 @@ internal void FlushContentToDisk()
{
try
{
var currentEncoding = GetPathEncoding(this.Path);

// Try to first open the file with permissions that will allow us to read from it
// later.
_contentWriter = new StreamWriter(
new FileStream(this.Path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read),
this.Encoding);
currentEncoding);
_contentWriter.BaseStream.Seek(0, SeekOrigin.End);
}
catch (IOException)
Expand All @@ -1135,7 +1123,7 @@ internal void FlushContentToDisk()
// file permissions.
_contentWriter = new StreamWriter(
new FileStream(this.Path, FileMode.Append, FileAccess.Write, FileShare.Read),
this.Encoding);
Utils.utf8NoBom);
}

_contentWriter.AutoFlush = true;
Expand Down Expand Up @@ -1332,4 +1320,3 @@ internal static int DetermineChoicePicked(string response, Collection<ChoiceDesc
}
}
}