1 // Program name: cfdata.cpp
2 // Programmed by: Anthony Barbachan
3 // Programmed in: C++ (Turbo C++ 3.0 Compatable)
4 // Purpose: Source file for a cabinet file data block object.
5 // Version: 1.00
6 // Last modified on: 11/5/1998
7 // Version: 1.00a
8 // Last modified on: 11/29/1998
9 // Changes: Removed check for data block size, unneeded.  Fixed program name.
10 // Version: 1.00b
11 // Last modified on: 12/6/1998
12 // Changes: Modified error checking code to check for short reads as well.
13 // Version: 2.00
14 // Last modification date: 10-18-1999
15 // Changes: Replaced code with new classes' code.
16 
17 #ifndef __CFDBLOCK_CPP__
18 #define __CFDBLOCK_CPP__
19 
20 #include <fstream>
21 #include "cftypes.h"
22 #include "cfdblock.h"
23 #include "cfheader.h"
24 
25 ////////////////////////////////////////****************************************
26 
read(istream & in)27 Error cabinet_datablock_fixed_header::read(istream& in)
28 {
29 	return (in.read((char *) this, sizeof(*this)).bad())
30 			? ((in.fail()) ? READ_ERROR : UNEXPECTED_EOF) : OK;
31 }
32 
33 ////////////////////////////////////////****************************************
34 
write(ostream & out)35 Error cabinet_datablock_fixed_header::write(ostream& out)
36 {
37 	return (out.write((char *) this, sizeof(*this)).fail()) ? WRITE_ERROR : OK;
38 }
39 
40 ////////////////////////////////////////****************************************
41 
42 ///////////////////////////////////////***************************************
43 
CSUMCompute(byte * pb,unsigned cb,CHECKSUM seed)44 cabinet_datablock_fixed_header::CHECKSUM cabinet_datablock::CSUMCompute(
45 											    byte* pb,
46 											    unsigned cb,
47 											    CHECKSUM seed)
48 {
49 	dword temp = 0ul;
50 	CHECKSUM csum = seed;				// Init checksum accumulator
51 
52 		// Checksum integral multiple of unsigned longs
53 
54 	for(int numdw = cb / 4; numdw > 0; numdw--)	// Loop through dwords
55 	{
56 	// NOTE: Building unsigned long in big/little-endian independent manner
57 		temp = (dword) (*pb++);			// Get low-order byte
58 		temp |= ((dword) (*pb++)) <<  8;	// Add 2nd byte
59 		temp |= ((dword) (*pb++)) << 16;	// Add 3nd byte
60 		temp |= ((dword) (*pb++)) << 24;	// Add 4th byte
61 		csum ^= temp;					// Update checksum
62 	}
63 
64 				// Checksum remainder bytes
65 
66 	temp = 0ul;
67 
68 	switch (cb % 4)
69 	{
70 		case 3:
71 			temp |= ((dword) (*pb++)) << 16;	// Add 3nd byte
72 		case 2:
73 			temp |= ((dword) (*pb++)) <<  8;	// Add 2nd byte
74 		case 1:
75 			temp |= (dword) (*pb++);			// Get low-order byte
76 			csum ^= temp;					// Update checksum
77 			break;
78 	}
79 
80 	return csum;					// Return computed checksum
81 }
82 
83 ///////////////////////////////////////***************************************
84 
compute_checksum()85 void cabinet_datablock::compute_checksum()
86 {
87 	 csum = CSUMCompute((byte *) &compressed_size,
88 					sizeof(compressed_size) +
89 					sizeof(uncompressed_size),
90 					CSUMCompute(compressed_data,compressed_size,0));
91 }
92 
93 ///////////////////////////////////////***************************************
94 
checksum_ok()95 int cabinet_datablock::checksum_ok()
96 {
97 	 return csum == CSUMCompute((byte *) &compressed_size,
98 						  sizeof(compressed_size) +
99 						  sizeof(uncompressed_size),
100 						  CSUMCompute(compressed_data,compressed_size,0));
101 }
102 
103 ///////////////////////////////////////***************************************
104 
checksum_not_ok()105 int cabinet_datablock::checksum_not_ok()
106 {
107 	 return csum != CSUMCompute((byte *) &compressed_size,
108 						  sizeof(compressed_size) +
109 						  sizeof(uncompressed_size),
110 						  CSUMCompute(compressed_data,compressed_size,0));
111 }
112 
113 ///////////////////////////////////////***************************************
114 
read(istream & in,cabinet_header & cab_header)115 int cabinet_datablock::read(istream& in, cabinet_header& cab_header)
116 {
117 	int err = OK;
118 
119 	clear();
120 	if((err = cabinet_datablock_fixed_header::read(in)) != OK) return err;
121 
122 	if(cab_header.has_reserved_area() && cab_header.get_datablock_ra_size())
123 	{									// If reserve area, read it
124 		ra_size = cab_header.get_datablock_ra_size();
125 		reserved_area = new byte[ra_size];
126 
127 		if(in.read((char*)reserved_area, ra_size).bad())
128 		{
129 			return (in.fail()) ? READ_ERROR : UNEXPECTED_EOF;
130 		}
131 	}
132 
133 	compressed_data = new byte[compressed_size];
134 
135 	if((err = io_read(in, compressed_data, compressed_size)) != OK)
136 	{
137 		return err;
138 	}
139 
140 	return (checksum_ok()) ? OK : CHECKSUM_ERROR;
141 }
142 
143 ///////////////////////////////////////***************************************
144 
145 // Warning: as a safety measure this function computes and sets the checksum
146 
write(ostream & out)147 int cabinet_datablock::write(ostream& out)
148 {
149 	Error err = OK;
150 
151 	compute_checksum();					// Sets the checksum - csum
152 
153 	if((err = cabinet_datablock_fixed_header::write(out)) != OK) return err;
154 
155 	if(ra_size)		 				// If reserve area, write it
156 	{
157 		if(out.write((char*)reserved_area, ra_size).fail()) return WRITE_ERROR;
158 	}
159 					 				// write data to stream
160 	// if(out.write(compressed_data, compressed_size).bad()) return WRITE_ERROR;
161 	return io_write(out, compressed_data, compressed_size);
162 
163 	// return OK;
164 }
165 
166 ///////////////////////////////////////***************************************
167 
set_reserved_area(const byte * ra,byte len)168 void cabinet_datablock::set_reserved_area(const byte* ra, byte len)
169 {
170 	if(reserved_area != NULL) delete[] reserved_area;
171 
172 	reserved_area = NULL;
173 	ra_size = (byte) 0u;
174 
175 	if(len > (byte) 0u)
176 	{
177 		ra_size = len;
178 		reserved_area = new byte[ra_size];
179 		memcpy(reserved_area, ra, ra_size);
180 	}
181 }
182 
183 ///////////////////////////////////////***************************************
184 
set_compressed_data(const byte * cdata,word csize,word usize)185 void cabinet_datablock::set_compressed_data(const byte* cdata, word csize,
186 								    word usize)
187 {
188 	if(compressed_data != NULL) delete[] compressed_data;
189 
190 	compressed_size = csize;
191 	uncompressed_size = usize;
192 	compressed_data = new byte[compressed_size];
193 	memcpy(compressed_data, cdata, compressed_size);
194 }
195 
196 ///////////////////////////////////////***************************************
197 
198 #endif
199