mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-16 05:05:05 +00:00
Merge branch 'zip' of Common/Utils into dev
This commit is contained in:
@@ -98,6 +98,9 @@
|
|||||||
<Compile Include="Extensions\UriExtensions.cs" />
|
<Compile Include="Extensions\UriExtensions.cs" />
|
||||||
<Compile Include="Extensions\UshortExtensions.cs" />
|
<Compile Include="Extensions\UshortExtensions.cs" />
|
||||||
<Compile Include="IcdUriBuilder.cs" />
|
<Compile Include="IcdUriBuilder.cs" />
|
||||||
|
<Compile Include="IO\Compression\IcdZipEntry.cs" />
|
||||||
|
<Compile Include="IO\IcdBinaryReader.cs" />
|
||||||
|
<Compile Include="IO\eSeekOrigin.cs" />
|
||||||
<Compile Include="ProcessorUtils.SimplSharp.cs" />
|
<Compile Include="ProcessorUtils.SimplSharp.cs" />
|
||||||
<Compile Include="ProcessorUtils.Standard.cs" />
|
<Compile Include="ProcessorUtils.Standard.cs" />
|
||||||
<Compile Include="ProgramUtils.SimplSharp.cs" />
|
<Compile Include="ProgramUtils.SimplSharp.cs" />
|
||||||
@@ -122,7 +125,7 @@
|
|||||||
<Compile Include="IcdEnvironment.cs" />
|
<Compile Include="IcdEnvironment.cs" />
|
||||||
<Compile Include="IcdEnvironment.SimplSharp.cs" />
|
<Compile Include="IcdEnvironment.SimplSharp.cs" />
|
||||||
<Compile Include="IcdEnvironment.Standard.cs" />
|
<Compile Include="IcdEnvironment.Standard.cs" />
|
||||||
<Compile Include="IcdZip.cs" />
|
<Compile Include="IO\Compression\IcdZip.cs" />
|
||||||
<Compile Include="IO\IcdDirectory.cs" />
|
<Compile Include="IO\IcdDirectory.cs" />
|
||||||
<Compile Include="EnumUtils.cs" />
|
<Compile Include="EnumUtils.cs" />
|
||||||
<Compile Include="Extensions\AssemblyExtensions.cs" />
|
<Compile Include="Extensions\AssemblyExtensions.cs" />
|
||||||
|
|||||||
184
ICD.Common.Utils/IO/Compression/IcdZip.cs
Normal file
184
ICD.Common.Utils/IO/Compression/IcdZip.cs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#else
|
||||||
|
using System.IO.Compression;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO.Compression
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utils for managing archives.
|
||||||
|
/// </summary>
|
||||||
|
public static class IcdZip
|
||||||
|
{
|
||||||
|
private const int DIRECTORY_SIGNATURE = 0x06054B50;
|
||||||
|
private const int ENTRY_SIGNATURE = 0x02014B50;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unzips the archive at the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="outputPath"></param>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
public static bool Unzip(string path, string outputPath, out string message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronZIP.ResultCode result = CrestronZIP.Unzip(path, outputPath);
|
||||||
|
message = result.ToString();
|
||||||
|
return result == CrestronZIP.ResultCode.ZR_OK;
|
||||||
|
#else
|
||||||
|
using (ZipArchive archive = ZipFile.Open(path, ZipArchiveMode.Read))
|
||||||
|
archive.ExtractToDirectory(outputPath);
|
||||||
|
message = "Success";
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
message = e.Message;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sequence of files names in the archive at the given path.
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerable<string> GetFileNames(string path)
|
||||||
|
{
|
||||||
|
return GetEntries(path).Select(e => e.Name)
|
||||||
|
.Where(f => !f.EndsWith("/"))
|
||||||
|
.OrderBy(f => f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets sequence of zip file entries in the archive at the given path.
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerable<IcdZipEntry> GetEntries(string path)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012-2013 Alexey Yakovlev
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using (IcdStream stream = IcdFile.OpenRead(path))
|
||||||
|
{
|
||||||
|
using (IcdBinaryReader reader = new IcdBinaryReader(stream))
|
||||||
|
{
|
||||||
|
if (stream.Length < 22)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
stream.Seek(-22, eSeekOrigin.End);
|
||||||
|
|
||||||
|
// find directory signature
|
||||||
|
while (reader.ReadInt32() != DIRECTORY_SIGNATURE)
|
||||||
|
{
|
||||||
|
if (stream.Position <= 5)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
// move 1 byte back
|
||||||
|
stream.Seek(-5, eSeekOrigin.Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read directory properties
|
||||||
|
stream.Seek(6, eSeekOrigin.Current);
|
||||||
|
ushort entries = reader.ReadUInt16();
|
||||||
|
int difSize = reader.ReadInt32();
|
||||||
|
uint dirOffset = reader.ReadUInt32();
|
||||||
|
stream.Seek(dirOffset, eSeekOrigin.Begin);
|
||||||
|
|
||||||
|
// read directory entries
|
||||||
|
for (int i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
if (reader.ReadInt32() != ENTRY_SIGNATURE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// read file properties
|
||||||
|
reader.ReadInt32();
|
||||||
|
bool utf8 = (reader.ReadInt16() & 0x0800) != 0;
|
||||||
|
short method = reader.ReadInt16();
|
||||||
|
int timestamp = reader.ReadInt32();
|
||||||
|
uint crc32 = reader.ReadUInt32();
|
||||||
|
int compressedSize = reader.ReadInt32();
|
||||||
|
int fileSize = reader.ReadInt32();
|
||||||
|
short fileNameSize = reader.ReadInt16();
|
||||||
|
short extraSize = reader.ReadInt16();
|
||||||
|
short commentSize = reader.ReadInt16();
|
||||||
|
int headerOffset = reader.ReadInt32();
|
||||||
|
reader.ReadInt32();
|
||||||
|
int fileHeaderOffset = reader.ReadInt32();
|
||||||
|
byte[] fileNameBytes = reader.ReadBytes(fileNameSize);
|
||||||
|
stream.Seek(extraSize, eSeekOrigin.Current);
|
||||||
|
byte[] fileCommentBytes = reader.ReadBytes(commentSize);
|
||||||
|
int fileDataOffset = CalculateFileDataOffset(stream, reader, fileHeaderOffset);
|
||||||
|
|
||||||
|
// decode zip file entry
|
||||||
|
Encoding encoder = utf8 ? Encoding.UTF8 : Encoding.Default;
|
||||||
|
|
||||||
|
yield return new IcdZipEntry
|
||||||
|
{
|
||||||
|
Name = encoder.GetString(fileNameBytes, 0, fileNameBytes.Length),
|
||||||
|
Comment = encoder.GetString(fileCommentBytes, 0, fileCommentBytes.Length),
|
||||||
|
Crc32 = crc32,
|
||||||
|
CompressedSize = compressedSize,
|
||||||
|
OriginalSize = fileSize,
|
||||||
|
HeaderOffset = fileHeaderOffset,
|
||||||
|
DataOffset = fileDataOffset,
|
||||||
|
Deflated = method == 8,
|
||||||
|
Timestamp = ConvertToDateTime(timestamp)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CalculateFileDataOffset(IcdStream stream, IcdBinaryReader reader, int fileHeaderOffset)
|
||||||
|
{
|
||||||
|
long position = stream.Position;
|
||||||
|
stream.Seek(fileHeaderOffset + 26, eSeekOrigin.Begin);
|
||||||
|
short fileNameSize = reader.ReadInt16();
|
||||||
|
short extraSize = reader.ReadInt16();
|
||||||
|
|
||||||
|
int fileOffset = (int)stream.Position + fileNameSize + extraSize;
|
||||||
|
stream.Seek(position, eSeekOrigin.Begin);
|
||||||
|
return fileOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts DOS timestamp to a <see cref="DateTime"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dosTimestamp">The DOS timestamp.</param>
|
||||||
|
/// <returns>The <see cref="DateTime"/> instance.</returns>
|
||||||
|
private static DateTime ConvertToDateTime(int dosTimestamp)
|
||||||
|
{
|
||||||
|
return new DateTime((dosTimestamp >> 25) + 1980,
|
||||||
|
(dosTimestamp >> 21) & 15,
|
||||||
|
(dosTimestamp >> 16) & 31,
|
||||||
|
(dosTimestamp >> 11) & 31,
|
||||||
|
(dosTimestamp >> 5) & 63,
|
||||||
|
(dosTimestamp & 31) * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
ICD.Common.Utils/IO/Compression/IcdZipEntry.cs
Normal file
59
ICD.Common.Utils/IO/Compression/IcdZipEntry.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO.Compression
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Zip archive entry.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class IcdZipEntry
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of a file or a directory.
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the comment.
|
||||||
|
/// </summary>
|
||||||
|
public string Comment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the CRC32.
|
||||||
|
/// </summary>
|
||||||
|
public uint Crc32 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the compressed size of the file.
|
||||||
|
/// </summary>
|
||||||
|
public int CompressedSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the original size of the file.
|
||||||
|
/// </summary>
|
||||||
|
public int OriginalSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this <see cref="IcdZipEntry" /> is deflated.
|
||||||
|
/// </summary>
|
||||||
|
public bool Deflated { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this <see cref="IcdZipEntry" /> is a directory.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDirectory { get { return Name.EndsWith("/"); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the timestamp.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this <see cref="IcdZipEntry" /> is a file.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFile { get { return !IsDirectory; } }
|
||||||
|
|
||||||
|
public int HeaderOffset { get; set; }
|
||||||
|
|
||||||
|
public int DataOffset { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
69
ICD.Common.Utils/IO/IcdBinaryReader.cs
Normal file
69
ICD.Common.Utils/IO/IcdBinaryReader.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdBinaryReader : IDisposable
|
||||||
|
{
|
||||||
|
private readonly BinaryReader m_Reader;
|
||||||
|
|
||||||
|
public BinaryReader WrappedReader { get { return m_Reader; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"></param>
|
||||||
|
public IcdBinaryReader(IcdStream stream)
|
||||||
|
: this(new BinaryReader(stream.WrappedStream))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
public IcdBinaryReader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
m_Reader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_Reader.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_Reader.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort ReadUInt16()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadInt32()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short ReadInt16()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadInt16();
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint ReadUInt32()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ReadBytes(short numberOfBytesToRead)
|
||||||
|
{
|
||||||
|
return m_Reader.ReadBytes(numberOfBytesToRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,6 +66,11 @@ namespace ICD.Common.Utils.IO
|
|||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IcdStream OpenRead(string path)
|
||||||
|
{
|
||||||
|
return new IcdFileStream(File.OpenRead(path));
|
||||||
|
}
|
||||||
|
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IcdFileStream OpenWrite(string path)
|
public static IcdFileStream OpenWrite(string path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ namespace ICD.Common.Utils.IO
|
|||||||
|
|
||||||
public Stream WrappedStream { get { return m_Stream; } }
|
public Stream WrappedStream { get { return m_Stream; } }
|
||||||
|
|
||||||
|
public long Length { get { return m_Stream.Length; } }
|
||||||
|
|
||||||
|
public long Position { get { return m_Stream.Position; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -29,5 +33,10 @@ namespace ICD.Common.Utils.IO
|
|||||||
{
|
{
|
||||||
m_Stream.Dispose();
|
m_Stream.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Seek(long offset, eSeekOrigin seekOrigin)
|
||||||
|
{
|
||||||
|
m_Stream.Seek(offset, seekOrigin.ToSeekOrigin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
40
ICD.Common.Utils/IO/eSeekOrigin.cs
Normal file
40
ICD.Common.Utils/IO/eSeekOrigin.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public enum eSeekOrigin
|
||||||
|
{
|
||||||
|
Begin,
|
||||||
|
Current,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SeekOriginExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the seek origin enum to a system seek origin.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static SeekOrigin ToSeekOrigin(this eSeekOrigin extends)
|
||||||
|
{
|
||||||
|
switch (extends)
|
||||||
|
{
|
||||||
|
case eSeekOrigin.Begin:
|
||||||
|
return SeekOrigin.Begin;
|
||||||
|
case eSeekOrigin.Current:
|
||||||
|
return SeekOrigin.Current;
|
||||||
|
case eSeekOrigin.End:
|
||||||
|
return SeekOrigin.End;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("extends");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using System;
|
|
||||||
#if SIMPLSHARP
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
#else
|
|
||||||
using System.IO.Compression;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ICD.Common.Utils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Utils for managing archives.
|
|
||||||
/// </summary>
|
|
||||||
public static class IcdZip
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unzips the archive at the given path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path"></param>
|
|
||||||
/// <param name="outputPath"></param>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
public static bool Unzip(string path, string outputPath, out string message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
#if SIMPLSHARP
|
|
||||||
CrestronZIP.ResultCode result = CrestronZIP.Unzip(path, outputPath);
|
|
||||||
message = result.ToString();
|
|
||||||
return result == CrestronZIP.ResultCode.ZR_OK;
|
|
||||||
#else
|
|
||||||
using (ZipArchive archive = ZipFile.Open(path, ZipArchiveMode.Read))
|
|
||||||
archive.ExtractToDirectory(outputPath);
|
|
||||||
message = "Success";
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
message = e.Message;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user