Ejemplo n.º 1
0
        // Open the source file, compute the MD5 Hash of the whole file and the first
        // 16k of the file, and then compute the FileId and store the results
        // in a file description packet and a file verification packet.
        public bool Open(string filename, ulong blocksize, bool deferhashcomputation)
        {
            // Get the filename and filesize
            targetfilename = filename;
            filesize       = (ulong)new FileInfo(filename).Length;

            // Work out how many blocks the file will be sliced into
            blockcount = (uint)((filesize + blocksize - 1) / blocksize);

            // Determine what filename to record in the PAR2 files
            parfilename = Path.GetFileName(filename);

            // Create the Description and Verification packets
            FileDescriptionPacket  = Packets.FileDescriptionPacket.Create(parfilename, filesize);
            FileVerificationPacket = Packets.FileVerificationPacket.Create(blockcount);

            // Create the diskfile object
            targetfile = new DiskFile();

            // Open the source file
            if (!targetfile.Open(targetfilename, filesize))
            {
                return(false);
            }

            // Do we want to defer the computation of the full file hash, and
            // the block crc and hashes. This is only permitted if there
            // is sufficient memory available to create all recovery blocks
            // in one pass of the source files (i.e. chunksize == blocksize)
            if (deferhashcomputation)
            {
                // Initialise a buffer to read the first 16k of the source file
                uint buffersize = Math.Min((uint)filesize, 16 * 1024);

                byte[] buffer = new byte[buffersize];

                // Read the data from the file
                if (!targetfile.Read(0, buffer, buffersize))
                {
                    targetfile.Close();
                    return(false);
                }

                // Compute the hash of the data read from the file
                // Store the hash in the descriptionpacket and compute the file id
                MD5 md5Hasher = MD5.Create();
                FileDescriptionPacket.hash16k = md5Hasher.ComputeHash(buffer);


                // Compute the fileid and store it in the verification packet.
                FileDescriptionPacket.ComputeFileId();
                FileVerificationPacket.fileid = (byte[])FileDescriptionPacket.fileid.Clone();

                //// Allocate an MD5 context for computing the file hash
                //// during the recovery data generation phase
                contextfull = MD5.Create();
                //contextfull = new MD5Context;
            }
            else
            {
                // Compute 16k MD5 hash
                using (BinaryReader br = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    MD5    md5Hasher = MD5.Create();
                    byte[] buffer16k = br.ReadBytes(16 * 1024);
                    FileDescriptionPacket.hash16k = md5Hasher.ComputeHash(buffer16k);
                }

                // Compute the fileid and store it in the verification packet.
                FileDescriptionPacket.ComputeFileId();
                FileVerificationPacket.fileid = (byte[])FileDescriptionPacket.fileid.Clone();

                // Compute full file MD5 hash & block CRC32 and MD5 hashes
                //long readSize = 5 * (long)blocksize;
                long readSize    = (long)blocksize;
                long fileSize    = new FileInfo(filename).Length;
                long nbSteps     = fileSize / readSize;
                long remaining   = fileSize % readSize;
                uint blocknumber = 0;

                // TODO : switch to async filestream
                using (BinaryReader br = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    MD5 md5FullHasher = MD5.Create();
                    MD5 md5Hasher     = MD5.Create();
                    //FastCRC32.FastCRC32 crc32 = new FastCRC32.FastCRC32(blocksize);
                    FastCRC32.FastCRC32 crc32 = FastCRC32.FastCRC32.GetCRC32Instance(blocksize);

                    byte[] blockHash  = new byte[16];
                    uint   blockCRC32 = 0;
                    for (int i = 0; i < nbSteps + 1; ++i)
                    {
                        byte[] buffer = br.ReadBytes((int)(i == nbSteps ? remaining : readSize));

                        // Global MD5 hash
                        if (i == nbSteps)
                        {
                            md5FullHasher.TransformFinalBlock(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            md5FullHasher.TransformBlock(buffer, 0, buffer.Length, null, 0);
                        }

                        //for (uint j = 0; j < 5; ++j)
                        //{
                        // Block MD5 hash & CRC32
                        uint length = (uint)blocksize;

                        //if (i == nbSteps && j == 4)
                        //if (i == nbSteps && (buffer.Length - (uint)(j * blocksize))  < (int)blocksize)
                        if (i == nbSteps && remaining != 0)
                        {
                            // We need arry padding since calculation **MUST** always be done on blocksize-length buffers
                            byte[] smallBuffer = buffer;
                            buffer = new byte[blocksize];
                            Buffer.BlockCopy(smallBuffer, 0, buffer, 0, smallBuffer.Length);
                        }

                        blockCRC32 = crc32.CRCUpdateBlock(0xFFFFFFFF, (uint)blocksize, buffer, 0) ^ 0xFFFFFFFF;
                        blockHash  = md5Hasher.ComputeHash(buffer, 0, (int)blocksize);

                        //Console.WriteLine("blocknumber:{0},hash:{1},crc32:{2}", blocknumber, blockHash, blockCRC32);
                        FileVerificationPacket.SetBlockHashAndCRC(blocknumber++, blockHash, blockCRC32);
                        //}
                    }

                    FileDescriptionPacket.hashfull = md5FullHasher.Hash;
                }
            }

            return(true);
        }
Ejemplo n.º 2
0
        // Open the source file, compute the MD5 Hash of the whole file and the first
        // 16k of the file, and then compute the FileId and store the results
        // in a file description packet and a file verification packet.
        public bool Open(string filename, ulong blocksize, bool deferhashcomputation)
        {
            // Get the filename and filesize
            targetfilename = filename;
            filesize = (ulong)new FileInfo(filename).Length;

            // Work out how many blocks the file will be sliced into
            blockcount = (uint)((filesize + blocksize - 1) / blocksize);

            // Determine what filename to record in the PAR2 files
            parfilename = Path.GetFileName(filename);

            // Create the Description and Verification packets
            FileDescriptionPacket = Packets.FileDescriptionPacket.Create(parfilename, filesize);
            FileVerificationPacket = Packets.FileVerificationPacket.Create(blockcount);

            // Create the diskfile object
            targetfile = new DiskFile();

            // Open the source file
            if (!targetfile.Open(targetfilename, filesize))
                return false;

            // Do we want to defer the computation of the full file hash, and
            // the block crc and hashes. This is only permitted if there
            // is sufficient memory available to create all recovery blocks
            // in one pass of the source files (i.e. chunksize == blocksize)
            if (deferhashcomputation)
            {
                // Initialise a buffer to read the first 16k of the source file
                uint buffersize = Math.Min((uint)filesize, 16 * 1024);

                byte[] buffer = new byte[buffersize];

                // Read the data from the file
                if (!targetfile.Read(0, buffer, buffersize))
                {
                    targetfile.Close();
                    return false;
                }

                // Compute the hash of the data read from the file
                // Store the hash in the descriptionpacket and compute the file id
                MD5 md5Hasher = MD5.Create();
                FileDescriptionPacket.hash16k = md5Hasher.ComputeHash(buffer);

                // Compute the fileid and store it in the verification packet.
                FileDescriptionPacket.ComputeFileId();
                FileVerificationPacket.fileid = (byte[])FileDescriptionPacket.fileid.Clone();

                //// Allocate an MD5 context for computing the file hash
                //// during the recovery data generation phase
                contextfull = MD5.Create();
                //contextfull = new MD5Context;
            }
            else
            {
                // Compute 16k MD5 hash
                using (BinaryReader br = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    MD5 md5Hasher = MD5.Create();
                    byte[] buffer16k = br.ReadBytes(16 * 1024);
                    FileDescriptionPacket.hash16k = md5Hasher.ComputeHash(buffer16k);
                }

                // Compute the fileid and store it in the verification packet.
                FileDescriptionPacket.ComputeFileId();
                FileVerificationPacket.fileid = (byte[])FileDescriptionPacket.fileid.Clone();

                // Compute full file MD5 hash & block CRC32 and MD5 hashes
                //long readSize = 5 * (long)blocksize;
                long readSize = (long)blocksize;
                long fileSize = new FileInfo(filename).Length;
                long nbSteps =  fileSize / readSize;
                long remaining = fileSize % readSize;
                uint blocknumber = 0;

                // TODO : switch to async filestream
                using (BinaryReader br = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                {
                    MD5 md5FullHasher = MD5.Create();
                    MD5 md5Hasher = MD5.Create();
                    //FastCRC32.FastCRC32 crc32 = new FastCRC32.FastCRC32(blocksize);
                    FastCRC32.FastCRC32 crc32 = FastCRC32.FastCRC32.GetCRC32Instance(blocksize);

                    byte[] blockHash = new byte[16];
                    uint blockCRC32 = 0;
                    for (int i = 0; i < nbSteps + 1; ++i)
                    {
                        byte[] buffer = br.ReadBytes((int)(i == nbSteps ? remaining : readSize));

                        // Global MD5 hash
                        if (i == nbSteps)
                            md5FullHasher.TransformFinalBlock(buffer, 0, buffer.Length);
                        else
                            md5FullHasher.TransformBlock(buffer, 0, buffer.Length, null, 0);

                        //for (uint j = 0; j < 5; ++j)
                        //{
                            // Block MD5 hash & CRC32
                            uint length = (uint)blocksize;

                            //if (i == nbSteps && j == 4)
                            //if (i == nbSteps && (buffer.Length - (uint)(j * blocksize))  < (int)blocksize)
                            if (i == nbSteps && remaining != 0)
                            {
                                // We need arry padding since calculation **MUST** always be done on blocksize-length buffers
                                byte[] smallBuffer = buffer;
                                buffer = new byte[blocksize];
                                Buffer.BlockCopy(smallBuffer, 0, buffer, 0, smallBuffer.Length);
                            }

                            blockCRC32 = crc32.CRCUpdateBlock(0xFFFFFFFF, (uint)blocksize, buffer, 0) ^ 0xFFFFFFFF;
                            blockHash = md5Hasher.ComputeHash(buffer, 0, (int)blocksize);

                            //Console.WriteLine("blocknumber:{0},hash:{1},crc32:{2}", blocknumber, blockHash, blockCRC32);
                            FileVerificationPacket.SetBlockHashAndCRC(blocknumber++, blockHash, blockCRC32);
                        //}
                    }

                    FileDescriptionPacket.hashfull = md5FullHasher.Hash;
                }
            }

            return true;
        }
Ejemplo n.º 3
0
 internal void Close()
 {
     targetfile.Close();
 }