Panda3D
Loading...
Searching...
No Matches
hashVal.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file hashVal.cxx
10 * @author drose
11 * @date 2000-11-14
12 */
13
14#include "hashVal.h"
15#include "virtualFileSystem.h"
16#include <ctype.h>
17
18#ifdef HAVE_OPENSSL
19#include "openSSLWrapper.h" // must be included before any other openssl.
20#include <openssl/md5.h>
21#endif // HAVE_OPENSSL
22
23using std::istream;
24using std::istringstream;
25using std::ostream;
26using std::ostringstream;
27using std::string;
28
29
30/**
31 * Outputs the HashVal as a 32-digit hexadecimal number.
32 */
34output_hex(ostream &out) const {
35 char buffer[32];
36 encode_hex(_hv[0], buffer);
37 encode_hex(_hv[1], buffer + 8);
38 encode_hex(_hv[2], buffer + 16);
39 encode_hex(_hv[3], buffer + 24);
40 out.write(buffer, 32);
41}
42
43/**
44 * Inputs the HashVal as a 32-digit hexadecimal number.
45 */
47input_hex(istream &in) {
48 in >> std::ws;
49 char buffer[32];
50 size_t i = 0;
51 int ch = in.get();
52
53 while (ch != EOF && !in.fail() && isxdigit(ch)) {
54 if (i < 32) {
55 buffer[i] = (char)ch;
56 }
57 i++;
58 ch = in.get();
59 }
60
61 if (i != 32) {
62 in.clear(std::ios::failbit|in.rdstate());
63 return;
64 }
65
66 if (ch != EOF) {
67 in.putback((char)ch);
68 } else {
69 in.clear();
70 }
71
72 decode_hex(buffer, _hv[0]);
73 decode_hex(buffer + 8, _hv[1]);
74 decode_hex(buffer + 16, _hv[2]);
75 decode_hex(buffer + 24, _hv[3]);
76}
77
78/**
79 * Outputs the HashVal as a binary stream of bytes in order. This is not the
80 * same order generated by write_stream().
81 */
83output_binary(ostream &out) const {
84 StreamWriter writer(out);
85 writer.add_be_uint32(_hv[0]);
86 writer.add_be_uint32(_hv[1]);
87 writer.add_be_uint32(_hv[2]);
88 writer.add_be_uint32(_hv[3]);
89}
90
91/**
92 * Inputs the HashVal as a binary stream of bytes in order. This is not the
93 * same order expected by read_stream().
94 */
96input_binary(istream &in) {
97 StreamReader reader(in);
98 _hv[0] = reader.get_be_uint32();
99 _hv[1] = reader.get_be_uint32();
100 _hv[2] = reader.get_be_uint32();
101 _hv[3] = reader.get_be_uint32();
102}
103
104/**
105 * Returns the HashVal as a string with four decimal numbers.
106 */
108as_dec() const {
109 ostringstream strm;
110 output_dec(strm);
111 return strm.str();
112}
113
114/**
115 * Sets the HashVal from a string with four decimal numbers. Returns true if
116 * valid, false otherwise.
117 */
119set_from_dec(const string &text) {
120 istringstream strm(text);
121 input_dec(strm);
122 return !strm.fail();
123}
124
125/**
126 * Returns the HashVal as a 32-byte hexadecimal string.
127 */
129as_hex() const {
130 char buffer[32];
131 encode_hex(_hv[0], buffer);
132 encode_hex(_hv[1], buffer + 8);
133 encode_hex(_hv[2], buffer + 16);
134 encode_hex(_hv[3], buffer + 24);
135 return string(buffer, 32);
136}
137
138/**
139 * Sets the HashVal from a 32-byte hexademical string. Returns true if
140 * successful, false otherwise.
141 */
143set_from_hex(const string &text) {
144 istringstream strm(text);
145 input_hex(strm);
146 return !strm.fail();
147}
148
149/**
150 * Returns the HashVal as a 16-byte binary string.
151 */
152vector_uchar HashVal::
153as_bin() const {
154 Datagram dg;
155 write_datagram(dg);
156 return vector_uchar((unsigned char *)dg.get_data(), (unsigned char *)dg.get_data() + dg.get_length());
157}
158
159/**
160 * Sets the HashVal from a 16-byte binary string. Returns true if successful,
161 * false otherwise.
162 */
164set_from_bin(const vector_uchar &text) {
165 nassertr(text.size() == 16, false);
166 Datagram dg(text);
167 DatagramIterator dgi(dg);
168 read_datagram(dgi);
169 return true;
170}
171
172#ifdef HAVE_OPENSSL
173/**
174 * Generates the hash value from the indicated file. Returns true on success,
175 * false if the file cannot be read. This method is only defined if we have
176 * the OpenSSL library (which provides md5 functionality) available.
177 */
178bool HashVal::
179hash_file(const Filename &filename) {
180 Filename bin_filename = Filename::binary_filename(filename);
182 istream *istr = vfs->open_read_file(bin_filename, false);
183 if (istr == nullptr) {
184 (*this) = HashVal();
185 return false;
186 }
187
188 bool result = hash_stream(*istr);
189 vfs->close_read_file(istr);
190
191 return result;
192}
193#endif // HAVE_OPENSSL
194
195#ifdef HAVE_OPENSSL
196/**
197 * Generates the hash value from the indicated file. Returns true on success,
198 * false if the file cannot be read. This method is only defined if we have
199 * the OpenSSL library (which provides md5 functionality) available.
200 */
201bool HashVal::
202hash_stream(istream &stream) {
203 unsigned char md[16];
204
205 MD5_CTX ctx;
206 MD5_Init(&ctx);
207
208 static const int buffer_size = 1024;
209 char buffer[buffer_size];
210
211 // Seek the stream to the beginning in case it wasn't there already.
212 stream.seekg(0, std::ios::beg);
213
214 stream.read(buffer, buffer_size);
215 size_t count = stream.gcount();
216 while (count != 0) {
217 MD5_Update(&ctx, buffer, count);
218 stream.read(buffer, buffer_size);
219 count = stream.gcount();
220 }
221
222 // Clear the fail bit so the caller can still read the stream (if it wants
223 // to).
224 stream.clear();
225
226 MD5_Final(md, &ctx);
227
228 // Store the individual bytes as big-endian ints, from historical
229 // convention.
230 _hv[0] = (md[0] << 24) | (md[1] << 16) | (md[2] << 8) | (md[3]);
231 _hv[1] = (md[4] << 24) | (md[5] << 16) | (md[6] << 8) | (md[7]);
232 _hv[2] = (md[8] << 24) | (md[9] << 16) | (md[10] << 8) | (md[11]);
233 _hv[3] = (md[12] << 24) | (md[13] << 16) | (md[14] << 8) | (md[15]);
234
235 return true;
236}
237#endif // HAVE_OPENSSL
238
239
240#ifdef HAVE_OPENSSL
241/**
242 * Generates the hash value by hashing the indicated data. This method is
243 * only defined if we have the OpenSSL library (which provides md5
244 * functionality) available.
245 */
246void HashVal::
247hash_buffer(const char *buffer, int length) {
248 unsigned char md[16];
249 MD5((const unsigned char *)buffer, length, md);
250
251 // Store the individual bytes as big-endian ints, from historical
252 // convention.
253 _hv[0] = (md[0] << 24) | (md[1] << 16) | (md[2] << 8) | (md[3]);
254 _hv[1] = (md[4] << 24) | (md[5] << 16) | (md[6] << 8) | (md[7]);
255 _hv[2] = (md[8] << 24) | (md[9] << 16) | (md[10] << 8) | (md[11]);
256 _hv[3] = (md[12] << 24) | (md[13] << 16) | (md[14] << 8) | (md[15]);
257}
258
259#endif // HAVE_OPENSSL
260
261
262/**
263 * Encodes the indicated unsigned int into an eight-digit hex string, stored
264 * at the indicated buffer and the following 8 positions.
265 */
266void HashVal::
267encode_hex(uint32_t val, char *buffer) {
268 buffer[0] = tohex(val >> 28);
269 buffer[1] = tohex(val >> 24);
270 buffer[2] = tohex(val >> 20);
271 buffer[3] = tohex(val >> 16);
272 buffer[4] = tohex(val >> 12);
273 buffer[5] = tohex(val >> 8);
274 buffer[6] = tohex(val >> 4);
275 buffer[7] = tohex(val);
276}
277
278/**
279 * Decodes the indicated eight-digit hex string into an unsigned integer.
280 */
281void HashVal::
282decode_hex(const char *buffer, uint32_t &val) {
283 unsigned int bytes[8];
284 for (int i = 0; i < 8; i++) {
285 bytes[i] = fromhex(buffer[i]);
286 }
287
288 val = ((bytes[0] << 28) |
289 (bytes[1] << 24) |
290 (bytes[2] << 20) |
291 (bytes[3] << 16) |
292 (bytes[4] << 12) |
293 (bytes[5] << 8) |
294 (bytes[6] << 4) |
295 (bytes[7]));
296}
A class to retrieve the individual data elements previously stored in a Datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
size_t get_length() const
Returns the number of bytes in the datagram.
Definition datagram.I:335
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
Definition datagram.I:327
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
Stores a 128-bit value that represents the hashed contents (typically MD5) of a file or buffer.
Definition hashVal.h:31
void input_binary(std::istream &in)
Inputs the HashVal as a binary stream of bytes in order.
Definition hashVal.cxx:96
void output_dec(std::ostream &out) const
Outputs the HashVal as four unsigned decimal integers.
Definition hashVal.I:103
void output_hex(std::ostream &out) const
Outputs the HashVal as a 32-digit hexadecimal number.
Definition hashVal.cxx:34
bool set_from_bin(const vector_uchar &text)
Sets the HashVal from a 16-byte binary string.
Definition hashVal.cxx:164
void output_binary(std::ostream &out) const
Outputs the HashVal as a binary stream of bytes in order.
Definition hashVal.cxx:83
void input_dec(std::istream &in)
Inputs the HashVal as four unsigned decimal integers.
Definition hashVal.I:111
bool set_from_hex(const std::string &text)
Sets the HashVal from a 32-byte hexademical string.
Definition hashVal.cxx:143
std::string as_dec() const
Returns the HashVal as a string with four decimal numbers.
Definition hashVal.cxx:108
std::string as_hex() const
Returns the HashVal as a 32-byte hexadecimal string.
Definition hashVal.cxx:129
bool set_from_dec(const std::string &text)
Sets the HashVal from a string with four decimal numbers.
Definition hashVal.cxx:119
vector_uchar as_bin() const
Returns the HashVal as a 16-byte binary string.
Definition hashVal.cxx:153
void input_hex(std::istream &in)
Inputs the HashVal as a 32-digit hexadecimal number.
Definition hashVal.cxx:47
A class to read sequential binary data directly from an istream.
uint32_t get_be_uint32()
Extracts an unsigned big-endian 32-bit integer.
A StreamWriter object is used to write sequential binary data directly to an ostream.
void add_be_uint32(uint32_t value)
Adds an unsigned 32-bit big-endian integer to the streamWriter.
A hierarchy of directories and files that appears to be one continuous file system,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
std::istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read,...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.