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