// Program name: cfdata.cpp // Programmed by: Anthony Barbachan // Programmed in: C++ (Turbo C++ 3.0 Compatable) // Purpose: Source file for a cabinet file data block object. // Version: 1.00 // Last modified on: 11/5/1998 // Version: 1.00a // Last modified on: 11/29/1998 // Changes: Removed check for data block size, unneeded. Fixed program name. // Version: 1.00b // Last modified on: 12/6/1998 // Changes: Modified error checking code to check for short reads as well. // Version: 2.00 // Last modification date: 10-18-1999 // Changes: Replaced code with new classes' code. #ifndef __CFDBLOCK_CPP__ #define __CFDBLOCK_CPP__ #include #include "cftypes.h" #include "cfdblock.h" #include "cfheader.h" ////////////////////////////////////////**************************************** Error cabinet_datablock_fixed_header::read(istream& in) { return (in.read((char *) this, sizeof(*this)).bad()) ? ((in.fail()) ? READ_ERROR : UNEXPECTED_EOF) : OK; } ////////////////////////////////////////**************************************** Error cabinet_datablock_fixed_header::write(ostream& out) { return (out.write((char *) this, sizeof(*this)).fail()) ? WRITE_ERROR : OK; } ////////////////////////////////////////**************************************** ///////////////////////////////////////*************************************** cabinet_datablock_fixed_header::CHECKSUM cabinet_datablock::CSUMCompute( byte* pb, unsigned cb, CHECKSUM seed) { dword temp = 0ul; CHECKSUM csum = seed; // Init checksum accumulator // Checksum integral multiple of unsigned longs for(int numdw = cb / 4; numdw > 0; numdw--) // Loop through dwords { // NOTE: Building unsigned long in big/little-endian independent manner temp = (dword) (*pb++); // Get low-order byte temp |= ((dword) (*pb++)) << 8; // Add 2nd byte temp |= ((dword) (*pb++)) << 16; // Add 3nd byte temp |= ((dword) (*pb++)) << 24; // Add 4th byte csum ^= temp; // Update checksum } // Checksum remainder bytes temp = 0ul; switch (cb % 4) { case 3: temp |= ((dword) (*pb++)) << 16; // Add 3nd byte case 2: temp |= ((dword) (*pb++)) << 8; // Add 2nd byte case 1: temp |= (dword) (*pb++); // Get low-order byte csum ^= temp; // Update checksum break; } return csum; // Return computed checksum } ///////////////////////////////////////*************************************** void cabinet_datablock::compute_checksum() { csum = CSUMCompute((byte *) &compressed_size, sizeof(compressed_size) + sizeof(uncompressed_size), CSUMCompute(compressed_data,compressed_size,0)); } ///////////////////////////////////////*************************************** int cabinet_datablock::checksum_ok() { return csum == CSUMCompute((byte *) &compressed_size, sizeof(compressed_size) + sizeof(uncompressed_size), CSUMCompute(compressed_data,compressed_size,0)); } ///////////////////////////////////////*************************************** int cabinet_datablock::checksum_not_ok() { return csum != CSUMCompute((byte *) &compressed_size, sizeof(compressed_size) + sizeof(uncompressed_size), CSUMCompute(compressed_data,compressed_size,0)); } ///////////////////////////////////////*************************************** int cabinet_datablock::read(istream& in, cabinet_header& cab_header) { int err = OK; clear(); if((err = cabinet_datablock_fixed_header::read(in)) != OK) return err; if(cab_header.has_reserved_area() && cab_header.get_datablock_ra_size()) { // If reserve area, read it ra_size = cab_header.get_datablock_ra_size(); reserved_area = new byte[ra_size]; if(in.read((char*)reserved_area, ra_size).bad()) { return (in.fail()) ? READ_ERROR : UNEXPECTED_EOF; } } compressed_data = new byte[compressed_size]; if((err = io_read(in, compressed_data, compressed_size)) != OK) { return err; } return (checksum_ok()) ? OK : CHECKSUM_ERROR; } ///////////////////////////////////////*************************************** // Warning: as a safety measure this function computes and sets the checksum int cabinet_datablock::write(ostream& out) { Error err = OK; compute_checksum(); // Sets the checksum - csum if((err = cabinet_datablock_fixed_header::write(out)) != OK) return err; if(ra_size) // If reserve area, write it { if(out.write((char*)reserved_area, ra_size).fail()) return WRITE_ERROR; } // write data to stream // if(out.write(compressed_data, compressed_size).bad()) return WRITE_ERROR; return io_write(out, compressed_data, compressed_size); // return OK; } ///////////////////////////////////////*************************************** void cabinet_datablock::set_reserved_area(const byte* ra, byte len) { if(reserved_area != NULL) delete[] reserved_area; reserved_area = NULL; ra_size = (byte) 0u; if(len > (byte) 0u) { ra_size = len; reserved_area = new byte[ra_size]; memcpy(reserved_area, ra, ra_size); } } ///////////////////////////////////////*************************************** void cabinet_datablock::set_compressed_data(const byte* cdata, word csize, word usize) { if(compressed_data != NULL) delete[] compressed_data; compressed_size = csize; uncompressed_size = usize; compressed_data = new byte[compressed_size]; memcpy(compressed_data, cdata, compressed_size); } ///////////////////////////////////////*************************************** #endif