mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-13 03:35:04 +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\UshortExtensions.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.Standard.cs" />
|
||||
<Compile Include="ProgramUtils.SimplSharp.cs" />
|
||||
@@ -122,7 +125,7 @@
|
||||
<Compile Include="IcdEnvironment.cs" />
|
||||
<Compile Include="IcdEnvironment.SimplSharp.cs" />
|
||||
<Compile Include="IcdEnvironment.Standard.cs" />
|
||||
<Compile Include="IcdZip.cs" />
|
||||
<Compile Include="IO\Compression\IcdZip.cs" />
|
||||
<Compile Include="IO\IcdDirectory.cs" />
|
||||
<Compile Include="EnumUtils.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);
|
||||
}
|
||||
|
||||
public static IcdStream OpenRead(string path)
|
||||
{
|
||||
return new IcdFileStream(File.OpenRead(path));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static IcdFileStream OpenWrite(string path)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace ICD.Common.Utils.IO
|
||||
|
||||
public Stream WrappedStream { get { return m_Stream; } }
|
||||
|
||||
public long Length { get { return m_Stream.Length; } }
|
||||
|
||||
public long Position { get { return m_Stream.Position; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
@@ -29,5 +33,10 @@ namespace ICD.Common.Utils.IO
|
||||
{
|
||||
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