Ejemplo n.º 1
0
        private uint _standardStreamMinBytes; //in bytes

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new, blank, Ole2Document object.
        /// </summary>
        public Ole2Document()
        {
            SetDefaults();

            _header = new Header(this);
            _msat = new Msat(this);
            _sat = new Sat(this);
            _ssat = new Ssat(this);
            _directory = new Directory(this);
            _streams = new Streams(this);

            _streams.AddNamed(new Bytes(), Directory.RootName);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Loads this Ole2Document object from the provided stream (e.g. a FileStream to load
        /// from a File).  This is only preliminarily supported and tested for Excel
        /// files.
        /// </summary>
        /// <param name="stream">Stream to load the document from.</param>
        public void Load(System.IO.Stream stream)
        {
            if (stream.Length == 0)
            {
                throw new Exception("No data (or zero-length) found!");
            }

            if (stream.Length < 512)
            {
                throw new Exception(string.Format("File length {0} < 512 bytes", stream.Length));
            }

            byte[] head = new byte[512];
            stream.Read(head, 0, 512);

            bool isLE = false;

            if (head[28] == 254 && head[29] == 255)
            {
                isLE = true;
            }

            if (!isLE)
            {
                throw new NotSupportedException("File is not Little-Endian");
            }
            _isLittleEndian = isLE;

            ushort sectorSize = BitConverter.ToUInt16(MidByteArray(head, 30, 2), 0);

            if (sectorSize < 7 || sectorSize > 32)
            {
                throw new Exception(string.Format("Invalid Sector Size [{0}] (should be 7 <= sectorSize <= 32", sectorSize));
            }
            _sectorSize = sectorSize;

            ushort shortSectorSize = BitConverter.ToUInt16(MidByteArray(head, 32, 2), 0);

            if (shortSectorSize > sectorSize)
            {
                throw new Exception(
                          string.Format("Invalid Short Sector Size [{0}] (should be < sectorSize; {1})", shortSectorSize, sectorSize));
            }
            _shortSectorSize = shortSectorSize;

            //if (readError) ExitFunction;

            uint satSectorCount = BitConverter.ToUInt32(MidByteArray(head, 44, 4), 0);

            if (satSectorCount < 0)
            {
                throw new Exception(string.Format("Invalid SAT Sector Count [{0}] (should be > 0)", satSectorCount));
            }

            int dirSID0 = BitConverter.ToInt32(MidByteArray(head, 48, 4), 0);

            if (dirSID0 < 0)
            {
                throw new Exception(string.Format("Invalid Directory SID0 [{0}] (should be > 0)", dirSID0));
            }

            uint minStandardStreamSize = BitConverter.ToUInt32(MidByteArray(head, 56, 4), 0);

            if ((minStandardStreamSize < (Math.Pow(2, sectorSize))) || (minStandardStreamSize % (Math.Pow(2, sectorSize)) > 0))
            {
                throw new Exception(string.Format("Invalid MinStdStreamSize [{0}] (should be multiple of (2^SectorSize)", minStandardStreamSize));
            }
            _standardStreamMinBytes = minStandardStreamSize;

            int  ssatSID0        = BitConverter.ToInt32(MidByteArray(head, 60, 4), 0);
            uint ssatSectorCount = BitConverter.ToUInt32(MidByteArray(head, 64, 4), 0);

            if (ssatSID0 < 0 && ssatSID0 != -2)
            {
                throw new Exception(string.Format("Invalid SSAT SID0 [{0}] (must be >=0 or -2", ssatSID0));
            }
            if (ssatSectorCount > 0 && ssatSID0 < 0)
            {
                throw new Exception(
                          string.Format("Invalid SSAT SID0 [{0}] (must be >=0 when SSAT Sector Count > 0)", ssatSID0));
            }
            if (ssatSectorCount < 0)
            {
                throw new Exception(string.Format("Invalid SSAT Sector Count [{0}] (must be >= 0)", ssatSectorCount));
            }

            int msatSID0 = BitConverter.ToInt32(MidByteArray(head, 68, 4), 0);

            if (msatSID0 < 1 && msatSID0 != -2)
            {
                throw new Exception(string.Format("Invalid MSAT SID0 [{0}]", msatSID0));
            }

            uint msatSectorCount = BitConverter.ToUInt32(MidByteArray(head, 72, 4), 0);

            if (msatSectorCount < 0)
            {
                throw new Exception(string.Format("Invalid MSAT Sector Count [{0}]", msatSectorCount));
            }
            else if (msatSectorCount == 0 && msatSID0 != -2)
            {
                throw new Exception(string.Format("Invalid MSAT SID0 [{0}] (should be -2)", msatSID0));
            }

            int i = 0;
            int k = ((int)Math.Pow(2, sectorSize) / 4) - 1;

            int[] msat = new int[108 + (k * msatSectorCount) + 1];         //add 1 compared to VBScript version due to C#/VBS array declaration diff
            for (int j = 0; j < 109; j++)
            {
                msat[j] = BitConverter.ToInt32(MidByteArray(head, 76 + (j * 4), 4), 0);
            }
            int msatSidNext = msatSID0;

            while (i < msatSectorCount)
            {
                Bytes sector = GetSector(stream, sectorSize, msatSidNext);
                if (sector.Length == 0)
                {
                    throw new Exception(string.Format("MSAT SID Chain broken - SID [{0}] not found / EOF reached", msatSidNext));
                }
                for (int j = 0; j < k; j++)
                {
                    msat[109 + (i * k) + j] = BitConverter.ToInt32(sector.Get(j * 4, 4).ByteArray, 0);
                }
                msatSidNext = BitConverter.ToInt32(sector.Get(k * 4, 4).ByteArray, 0);
                i++;
            }

            //if (re) Exit Function;

            //Find number of Sectors in SAT --> i
            i = msat.Length;
            while (msat[i - 1] < 0)
            {
                i--;
            }

            //Size and fill SAT SID array
            int[] sat = new int[(uint)(i * (Math.Pow(2, sectorSize) / 4))];
            int   m   = (int)(Math.Pow(2, sectorSize) / 4);

            for (int j = 0; j < i; j++)
            {
                Bytes sector = GetSector(stream, sectorSize, msat[j]);
                if (sector.Length == 0)
                {
                    throw new Exception(string.Format("SAT SID Chain broken - SAT Sector SID{0} not found / EOF reached", msat[j]));
                }
                for (k = 0; k < m; k++)
                {
                    sat[(j * m) + k] = BitConverter.ToInt32(sector.Get(k * 4, 4).ByteArray, 0);
                }
            }

            //Size and fill SSAT SID array
            i = 0;
            int ssatSidNext = ssatSID0;

//		    m = (int) (Math.Pow(2, sectorSize) / 4);
            //Dictionary<int, int> ssat = new Dictionary<int, int>();
            int[] ssat = new int[(ssatSectorCount + 1) * m];
            while (ssatSidNext > -2)
            {
                Bytes sector = GetSector(stream, sectorSize, ssatSidNext);
                if (sector.Length == 0)
                {
                    throw new Exception(string.Format("SSAT Sector SID{0} not found", ssatSidNext));
                }
                for (int j = 0; j < m; j++)
                {
                    ssat[(i * m) + j] = BitConverter.ToInt32(sector.Get(j * 4, 4).ByteArray, 0);
                }
                ssatSidNext = sat[ssatSidNext];
                i++;
            }
            if (i < ssatSectorCount)
            {
                throw new Exception(string.Format("SSAT Sector chain broken: {0} found, header indicates {1}", i, ssatSectorCount));
            }

            //Size and fill Directory byte array array
            int dirSectorCount = 0;
            int dirSidNext     = dirSID0;

            m = (int)(Math.Pow(2, sectorSize) / 128);
            Dictionary <int, byte[]> dir = new Dictionary <int, byte[]>();

            while (dirSidNext > -2)
            {
                Bytes sector = GetSector(stream, sectorSize, dirSidNext);
                if (sector.Length == 0)
                {
                    throw new Exception(string.Format("Directory Sector SID{0} not found", dirSidNext));
                }
                for (int j = 0; j < m; j++)
                {
                    dir[(dirSectorCount * m) + j] = sector.Get(j * 128, 128).ByteArray;
                }
                dirSidNext = sat[dirSidNext];
                dirSectorCount++;
            }

            for (i = 0; i < dir.Count; i++)
            {
                byte[] dirEntry      = dir[i];
                int    nameLength    = BitConverter.ToInt16(MidByteArray(dirEntry, 64, 2), 0);
                byte[] docStreamName = MidByteArray(dirEntry, 0, nameLength);
                bool   overwrite     = false;
                if (Bytes.AreEqual(docStreamName, Directory.RootName))
                {
                    overwrite = true;
                }
                Bytes docStream =
                    GetStream(stream, i, dir, sectorSize, sat, shortSectorSize, ssat, minStandardStreamSize);
                if (docStreamName.Length == 0 && docStream.Length == 0)
                {
                    continue; //don't add streams for directory padding entries
                }
                Streams.AddNamed(docStream, docStreamName, overwrite);
            }
        }