context: // Shared.cs
  // ------------------------------------------------------------------
  //
  // Copyright (c) 2006-2011 Dino Chiesa.
  // All rights reserved.
  //
  // This code module is part of DotNetZip, a zipfile class library.
  //
  // ------------------------------------------------------------------
  //
  // This code is licensed under the Microsoft Public License.
  // See the file License.txt for the license details.
  // More info on: http://dotnetzip.codeplex.com
  //
  // ------------------------------------------------------------------
  //
  // Last Saved: <2011-August-02 19:41:01>
  //
  // ------------------------------------------------------------------
  //
  // This module defines some shared utility classes and methods.
  //
  // Created: Tue, 27 Mar 2007  15:30
  //
  
  using System;
  using System.IO;
  using System.Security.Permissions;
  
  namespace AL.Utils.Ionic.Zip
  {
      /// <summary>
      /// Collects general purpose utility methods.
      /// </summary>
      internal static class SharedUtilities
      {
          /// private null constructor
          //private SharedUtilities() { }
  
          // workitem 8423
          public static Int64 GetFileLength(string fileName)
          {
              if (!File.Exists(fileName))
                  throw new System.IO.FileNotFoundException(fileName);
  
              long fileLength = 0L;
              FileShare fs = FileShare.ReadWrite;
  #if !NETCF
              // FileShare.Delete is not defined for the Compact Framework
              fs |= FileShare.Delete;
  #endif
              using (var s = File.Open(fileName, FileMode.Open, FileAccess.Read, fs))
              {
                  fileLength = s.Length;
              }
              return fileLength;
          }
  
  
          [System.Diagnostics.Conditional("NETCF")]
          public static void Workaround_Ladybug318918(Stream s)
          {
              // This is a workaround for this issue:
              // https://connect.microsoft.com/VisualStudio/feedback/details/318918
              // It's required only on NETCF.
              s.Flush();
          }
  
  
  #if LEGACY
          /// <summary>
          /// Round the given DateTime value to an even second value.
          /// </summary>
          ///
          /// <remarks>
          /// <para>
          /// Round up in the case of an odd second value.  The rounding does not consider
          /// fractional seconds.
          /// </para>
          /// <para>
          /// This is useful because the Zip spec allows storage of time only to the nearest
          /// even second.  So if you want to compare the time of an entry in the archive with
          /// it's actual time in the filesystem, you need to round the actual filesystem
          /// time, or use a 2-second threshold for the comparison.
          /// </para>
          /// <para>
          /// This is most nautrally an extension method for the DateTime class but this
          /// library is built for .NET 2.0, not for .NET 3.5; This means extension methods
          /// are a no-no.
          /// </para>
          /// </remarks>
          /// <param name="source">The DateTime value to round</param>
          /// <returns>The ruonded DateTime value</returns>
          public static DateTime RoundToEvenSecond(DateTime source)
          {
              // round to nearest second:
              if ((source.Second % 2) == 1)
                  source += new TimeSpan(0, 0, 1);
  
              DateTime dtRounded = new DateTime(source.Year, source.Month, source.Day, source.Hour, source.Minute, source.Second);
              //if (source.Millisecond >= 500) dtRounded = dtRounded.AddSeconds(1);
              return dtRounded;
          }
  #endif
  
  #if YOU_LIKE_REDUNDANT_CODE
          internal static string NormalizePath(string path)
          {
              // remove leading single dot slash
              if (path.StartsWith(".\\")) path = path.Substring(2);
  
              // remove intervening dot-slash
              path = path.Replace("\\.\\", "\\");
  
              // remove double dot when preceded by a directory name
              var re = new System.Text.RegularExpressions.Regex(@"^(.*\\)?([^\\\.]+\\\.\.\\)(.+)$");
              path = re.Replace(path, "$1$3");
              return path;
          }
  #endif
  
          private static System.Text.RegularExpressions.Regex doubleDotRegex1 =
              new System.Text.RegularExpressions.Regex(@"^(.*/)?([^/\\.]+/\\.\\./)(.+)$");
  
          private static string SimplifyFwdSlashPath(string path)
          {
              if (path.StartsWith("./")) path = path.Substring(2);
              path = path.Replace("/./", "/");
  
              // Replace foo/anything/../bar with foo/bar
              path = doubleDotRegex1.Replace(path, "$1$3");
              return path;
          }
  
  
          /// <summary>
          /// Utility routine for transforming path names from filesystem format (on Windows that means backslashes) to
          /// a format suitable for use within zipfiles. This means trimming the volume letter and colon (if any) And
          /// swapping backslashes for forward slashes.
          /// </summary>
          /// <param name="pathName">source path.</param>
          /// <returns>transformed path</returns>
          public static string NormalizePathForUseInZipFile(string pathName)
          {
              // boundary case
              if (String.IsNullOrEmpty(pathName)) return pathName;
  
              // trim volume if necessary
              if ((pathName.Length >= 2)  && ((pathName[1] == ':') && (pathName[2] == '\\')))
                  pathName =  pathName.Substring(3);
  
              // swap slashes
              pathName = pathName.Replace('\\', '/');
  
              // trim all leading slashes
              while (pathName.StartsWith("/")) pathName = pathName.Substring(1);
  
              return SimplifyFwdSlashPath(pathName);
          }
  
  
          static System.Text.Encoding ibm437 = System.Text.Encoding.GetEncoding("IBM437");
          static System.Text.Encoding utf8 = System.Text.Encoding.GetEncoding("UTF-8");
  
          internal static byte[] StringToByteArray(string value, System.Text.Encoding encoding)
          {
              byte[] a = encoding.GetBytes(value);
              return a;
          }
          internal static byte[] StringToByteArray(string value)
          {
              return StringToByteArray(value, ibm437);
          }
  
          //internal static byte[] Utf8StringToByteArray(string value)
          //{
          //    return StringToByteArray(value, utf8);
          //}
  
          //internal static string StringFromBuffer(byte[] buf, int maxlength)
          //{
          //    return StringFromBuffer(buf, maxlength, ibm437);
          //}
  
          internal static string Utf8StringFromBuffer(byte[] buf)
          {
              return StringFromBuffer(buf, utf8);
          }
  
          internal static string StringFromBuffer(byte[] buf, System.Text.Encoding encoding)
          {
              // this form of the GetString() method is required for .NET CF compatibility
              string s = encoding.GetString(buf, 0, buf.Length);
              return s;
          }
  
  
          internal static int ReadSignature(System.IO.Stream s)
          {
              int x = 0;
              try { x = _ReadFourBytes(s, "n/a"); }
              catch (BadReadException) { }
              return x;
          }
  
  
          internal static int ReadEntrySignature(System.IO.Stream s)
          {
              // handle the case of ill-formatted zip archives - includes a data descriptor
              // when none is expected.
              int x = 0;
              try
              {
                  x = _ReadFourBytes(s, "n/a");
                  if (x == ZipConstants.ZipEntryDataDescriptorSignature)
                  {
                      // advance past data descriptor - 12 bytes if not zip64
                      s.Seek(12, SeekOrigin.Current);
                      // workitem 10178
                      Workaround_Ladybug318918(s);
                      x = _ReadFourBytes(s, "n/a");
                      if (x != ZipConstants.ZipEntrySignature)
                      {
                          // Maybe zip64 was in use for the prior entry.
                          // Therefore, skip another 8 bytes.
                          s.Seek(8, SeekOrigin.Current);
                          // workitem 10178
                          Workaround_Ladybug318918(s);
                          x = _ReadFourBytes(s, "n/a");
  
gt:                         if (x != ZipConstants.ZipEntrySignature)