示例#1
0
        private int cbHeader;                   // Size of the serialized package header

        /// <summary>
        /// Instantiates an empty file package for writing.  Call <see cref="Create(string)" />
        /// to indicate where the package should be written.
        /// </summary>
        public Package()
        {
            this.entries    = new Hashtable();
            this.root       = new PackageEntry(this, null, string.Empty, true);
            this.packageIn  = null;
            this.packageOut = null;

            entries.Add(string.Empty, root);
        }
示例#2
0
 /// <summary>
 /// Instantiates a folder or file package entry.
 /// </summary>
 /// <param name="package">The package that owns this entry.</param>
 /// <param name="parent">The parent folder (or <c>null</c> for the root folder).</param>
 /// <param name="name">The entry's local name.</param>
 /// <param name="isFolder"><c>true</c> if this is a folder, false for a file.</param>
 internal PackageEntry(Package package, PackageEntry parent, string name, bool isFolder)
 {
     this.package  = package;
     this.type     = isFolder ? FOLDER : FILE;
     this.parent   = parent;
     this.name     = name;
     this.fullName = GetFullName();
     this.size     = 0;
     this.children = new ArrayList();
 }
示例#3
0
        /// <summary>
        /// Adds the entry passed to the set of this folder's children.
        /// </summary>
        /// <param name="entry">The entry to be added.</param>
        internal void AddChild(PackageEntry entry)
        {
            if (type != FOLDER)
            {
                throw new PackageException(Package.NotFolder);
            }

            if (children == null)
            {
                children = new ArrayList();
            }

            children.Add(entry);
        }
示例#4
0
        /// <summary>
        /// Adds a file entry to the package by copying data from a stream.
        /// </summary>
        /// <param name="packagePath">The fully qualified name of the file to be added.</param>
        /// <param name="input">The input stream.</param>
        /// <param name="size">The number of bytes to copy.</param>
        /// <returns>The package entry added.</returns>
        /// <remarks>
        /// The input stream's position will be advanced past the last
        /// byte read.
        /// </remarks>
        public PackageEntry AddFile(string packagePath, Stream input, int size)
        {
            PackageEntry entry;

            byte[] buffer;
            int    cb, cbRemain;

            if (packageOut == null)
            {
                throw new PackageException(ReadOnly);
            }

            CheckPath(packagePath);
            if (entries[packagePath.ToUpper()] != null)
            {
                throw new PackageException(AlreadyExists, packagePath);
            }

            entry = new PackageEntry(this, packagePath, false);
            entry.SetSize(size);

            AddEntry(entry);
            entry.Serialize(packageOut);

            buffer   = new byte[CopyBufSize];
            cbRemain = entry.Size;

            while (cbRemain > 0)
            {
                cb = cbRemain;
                if (cb > CopyBufSize)
                {
                    cb = CopyBufSize;
                }

                input.Read(buffer, 0, cb);
                packageOut.Write(buffer, 0, cb);

                cbRemain -= cb;
            }

            return(entry);
        }
示例#5
0
        /// <summary>
        /// Instantiates a package entry with a fully qualified name.
        /// </summary>
        /// <param name="package">The package that owns this entry.</param>
        /// <param name="fullName">The entry's fully qualified name.</param>
        /// <param name="isFolder">Pass <c>true</c> if this entry is a folder.</param>
        internal PackageEntry(Package package, string fullName, bool isFolder)
        {
            int pos;

            pos = fullName.LastIndexOf('/');
            if (pos == -1)
            {
                name = fullName;
            }
            else
            {
                name = fullName.Substring(pos + 1);
            }

            this.package  = package;
            this.type     = isFolder ? FOLDER : FILE;
            this.parent   = null;
            this.fullName = fullName;
            this.size     = 0;
            this.children = new ArrayList();
        }
示例#6
0
        /// <summary>
        /// Adds the package passed to the entry hierarchy, creating folders
        /// as necessary.
        /// </summary>
        /// <param name="entry">The new entry.</param>
        private void AddEntry(PackageEntry entry)
        {
            PackageEntry parent;
            string       path;
            int          pos, posEnd;

            // Make sure that all of the folders up
            // the hierarchy exist.

            parent = root;
            pos    = 1;
            while (true)
            {
                posEnd = entry.FullName.IndexOf('/', pos);
                if (posEnd == -1)
                {
                    break;
                }

                path   = entry.FullName.Substring(0, posEnd);
                parent = this[path];
                if (parent != null && !parent.IsFolder)
                {
                    throw new PackageException(MustBeFolder, path);
                }
                else if (parent == null)
                {
                    parent = AddFolder(path);
                }

                pos = posEnd + 1;
            }

            entry.SetParent(parent);
            parent.AddChild(entry);

            entries.Add(entry.FullName.ToUpper(), entry);
        }
示例#7
0
        /// <summary>
        /// Adds a folder entry to the package.
        /// </summary>
        /// <param name="packagePath">The fully wualified name of the folder to be added.</param>
        /// <returns>The package entry added.</returns>
        public PackageEntry AddFolder(string packagePath)
        {
            PackageEntry entry;

            if (packageOut == null)
            {
                throw new PackageException(ReadOnly);
            }

            CheckPath(packagePath);
            if (entries[packagePath.ToUpper()] != null)
            {
                throw new PackageException(AlreadyExists, packagePath);
            }

            entry = new PackageEntry(this, packagePath, true);
            entry.SetSize(0);

            AddEntry(entry);
            entry.Serialize(packageOut);

            return(entry);
        }
示例#8
0
        /// <summary>
        /// Adds a file entry to the package.
        /// </summary>
        /// <param name="packagePath">The fully qualified name of the file to be added.</param>
        /// <param name="buffer">The entry data to be added.</param>
        /// <returns>The package entry added.</returns>
        public PackageEntry AddFile(string packagePath, byte[] buffer)
        {
            PackageEntry entry;

            if (packageOut == null)
            {
                throw new PackageException(ReadOnly);
            }

            CheckPath(packagePath);
            if (entries[packagePath.ToUpper()] != null)
            {
                throw new PackageException(AlreadyExists, packagePath);
            }

            entry = new PackageEntry(this, packagePath, false);
            entry.SetSize(buffer.Length);

            AddEntry(entry);
            entry.Serialize(packageOut);
            packageOut.Write(buffer, 0, buffer.Length);

            return(entry);
        }
示例#9
0
 /// <summary>
 /// Sets the entry's parent.
 /// </summary>
 /// <param name="parent">The parent being assigned.</param>
 internal void SetParent(PackageEntry parent)
 {
     this.parent = parent;
 }
示例#10
0
        /// <summary>
        /// Scans the input stream, validating its structure and loading
        /// the package entries.
        /// </summary>
        private void Load()
        {
            PackageHeader header;

            byte[] hash;

            packageIn.Position = 0;
            header             = new PackageHeader(packageIn);
            cbHeader           = (int)packageIn.Position;

            // Compute a MD5 hash on the rest of then file and compare
            // the result to what we read from the header.

            hash = MD5Hasher.Compute(packageIn, packageIn.Length - cbHeader);
            if (hash.Length != header.Hash.Length)
            {
                throw new PackageException(CorruptPackage);
            }

            for (int i = 0; i < hash.Length; i++)
            {
                if (hash[i] != header.Hash[i])
                {
                    throw new PackageException(CorruptPackage);
                }
            }

            // Read the package entry headers.

            packageIn.Position = cbHeader;
            while (true)
            {
                var entry = new PackageEntry(this, packageIn);

                if (entry.IsEol)
                {
                    break;
                }

                entries.Add(entry.FullName.ToUpper(), entry);
            }

            // Walk back through the entries and link each entry to
            // its parent folder.

            foreach (PackageEntry entry in entries.Values)
            {
                PackageEntry parent;
                int          pos;

                if (entry == root)
                {
                    continue;
                }

                pos = entry.FullName.LastIndexOf('/');
                if (pos == -1)
                {
                    throw new PackageException(CorruptPackage);
                }

                if (pos == 0)
                {
                    parent = root;
                }
                else
                {
                    parent = (PackageEntry)entries[entry.FullName.Substring(0, pos).ToUpper()];
                    if (parent == null)
                    {
                        throw new PackageException(CorruptPackage);
                    }
                }

                entry.SetParent(parent);
                parent.AddChild(entry);
            }
        }