// // File: hzCodec.cpp // // Legal Notice: This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#include <iostream> #include <fstream>
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <crypt.h> #include <zlib.h> #include <sys/stat.h> #include <openssl/sha.h> #include <openssl/hmac.h>
#include "hzBasedefs.h" #include "hzChars.h" #include "hzErrcode.h" #include "hzDirectory.h" #include "hzCodec.h" #include "hzProcess.h"
using namespace std ;
/* ** Variables */
global const hzMD5 _hz_null_hzMD5 ;
/* ** Endian Conversion Functions */
// Import an internal uint16_t from char array of 2 bytes void _endian_import2 (uint16_t& v, const uchar* i) { v=0; if (i) v=(i[0]<<8)+i[1]; }
// Import an internal uint32_t from char array of 2 to 8 bytes void _endian_import2 (uint32_t& v, const uchar* i) { v=0; if (i) v=(i[0]<<8)+i[1]; }
void _endian_import3 (uint32_t& v, const uchar* i) { v=0; if (i) v=(i[0]<<16)+(i[1]<<8)+i[2]; }
void _endian_import4 (uint32_t& v, const uchar* i) { v=0; if (i) v=(i[0]<<24)+(i[1]<<16)+(i[2]<<8)+i[3]; }
// Import an internal uint64_t from char array of 2 to 8 bytes void _endian_import2 (uint64_t& v, const uchar* i) { v = 0 ; if (i) v = (i[0]<<8) + i[1] ; }
void _endian_import3 (uint64_t& v, const uchar* i) { v = 0 ; if (i) v = (i[0]<<16) + (i[1]<<8) + i[2] ; }
void _endian_import4 (uint64_t& v, const uchar* i) { v = 0 ; if (i) v = (i[0]<<24) + (i[1]<<16) + (i[2]<<8) + i[3] ; }
void _endian_import5 (uint64_t& v, const uchar* i) { v = 0 ; if (i) { v = i[0] ; v <<= 32 ; v |= ((i[1]<<24) + (i[2]<<16) + (i[3]<<8) + i[4]) ; } }
void _endian_import6 (uint64_t& v, const uchar* i) { v = 0 ; if (i) { v = (i[0]<<8) + i[1] ; v <<= 32 ; v |= ((i[2]<<24) + (i[3]<<16) + (i[4]<<8) + i[5]) ; } }
void _endian_import7 (uint64_t& v, const uchar* i) { v = 0 ; if (i) { v = (i[0]<<16) + (i[1]<<8) + i[2] ; v <<= 32 ; v |= ((i[3]<<24) + (i[4]<<16) + (i[5]<<8) + i[6]); } }
void _endian_import8 (uint64_t& v, const uchar* i) { v = 0 ; if (i) { v = (i[0]<<24) + (i[1]<<16) + (i[2]<<8) + i[3]; v <<= 32; v |= ((i[4]<<24) + (i[5]<<16) + (i[6]<<8) + i[7]); } }
// Export an internal uint16_t to char array of 2 bytes void _endian_export2 (uchar* s, uint16_t n) { if (!s) return ; s[0]=(n&0xff00)>>8; s[1]=n&0xff; }
// Export an internal uint32_t to char array of 2 to 4 bytes void _endian_export2 (uchar* s, uint32_t n) { if (!s) return ; s[0]=(n&0xff00)>>8; s[1]=n&0xff; }
void _endian_export3 (uchar* s, uint32_t n) { if (!s) return ; s[0]=(n&0xff0000)>>16; s[1]=(n&0xff00)>>8; s[2]=n&0xff; }
void _endian_export4 (uchar* s, uint32_t n) { if (!s) return ; s[0]=(n&0xff000000)>>24; s[1]=(n&0xff0000)>>16; s[2]=(n&0xff00)>>8; s[3]=n&0xff; }
// Export an internal uint64_t to char array of 2 to 8 bytes void _endian_export2 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff00)>>8; s[1]=n&0xff; }
void _endian_export3 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff0000)>>16; s[1]=(n&0xff00)>>8; s[2]=n&0xff; }
void _endian_export4 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff000000)>>24; s[1]=(n&0xff0000)>>16; s[2]=(n&0xff00)>>8; s[3]=n&0xff; }
void _endian_export5 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff00000000)>>32; s[1]=(n&0xff000000)>>24; s[2]=(n&0xff0000)>>16; s[3]=(n&0xff00)>>8; s[4]=n&0xff; }
void _endian_export6 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff0000000000)>>40; s[1]=(n&0xff00000000)>>32; s[2]=(n&0xff000000)>>24; s[3]=(n&0xff0000)>>16; s[4]=(n&0xff00)>>8; s[5]=n&0xff; }
void _endian_export7 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff000000000000)>>48; s[1]=(n&0xff0000000000)>>40; s[2]=(n&0xff00000000)>>32; s[3]=(n&0xff000000)>>24; s[4]=(n&0xff0000)>>16; s[5]=(n&0xff00)>>8; s[6]=n&0xff; }
void _endian_export8 (uchar* s, uint64_t n) { if (!s) return ; s[0]=(n&0xff00000000000000)>>56; s[1]=(n&0xff000000000000)>>48; s[2]=(n&0xff0000000000)>>40; s[3]=(n&0xff00000000)>>32; s[4]=(n&0xff000000)>>24; s[5]=(n&0xff0000)>>16; s[6]=(n&0xff00)>>8; s[7]=n&0xff; }
/* ** Serialized Integer Read Functions: Restores to uint64, int64, uint32 and int32 from char* input */
hzEcode ReadSerialUINT64 (uint64_t& nValue, uint32_t& nLen, const uchar* ptr) { // Convert a serialized integer into a 64-bit unsigned integer. // // Arguments: 1) nValue Indicated length or value // 2) nLen The size of the indicator itself // 3) ptr Pointer into a uchar buffer (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint64_t inc ; // Increament value
if (!ptr) return hzerr(E_ARGUMENT, "No length indicator supplied") ;
if (*ptr & 0x80) { nLen = (*ptr & 0x78) >> 3 ; nValue = *ptr & 0x07 ;
switch (nLen) { case 0: nValue <<= 8 ; nValue += ptr[1] ; break ; case 1: nValue <<= 16 ; _endian_import2(inc, ptr+1) ; nValue += inc ; break ; case 2: nValue <<= 24 ; _endian_import3(inc, ptr+1) ; nValue += inc ; break ; case 3: nValue <<= 32 ; _endian_import4(inc, ptr+1) ; nValue += inc ; break ; case 4: nValue <<= 40 ; _endian_import5(inc, ptr+1) ; nValue += inc ; break ; case 5: nValue <<= 48 ; _endian_import6(inc, ptr+1) ; nValue += inc ; break ; case 6: nValue <<= 56 ; _endian_import7(inc, ptr+1) ; nValue += inc ; break ; default: _endian_import8(nValue, ptr+1) ; break ; } } else { nLen = 1 ; nValue = *ptr & 0x7f ; }
return E_OK ; }
hzEcode ReadSerialSINT64 (int64_t& nValue, uint32_t& nLen, const uchar* ptr) { // Convert a serialized integer into a 64-bit unsigned integer. // // Arguments: 1) nValue Indicated length or value // 2) nLen The size of the indicator itself // 3) ptr Pointer into a uchar buffer (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint64_t inc ; // Increament value bool bNeg ; // Set if negative
if (!ptr) return hzerr(E_ARGUMENT, "No length indicator supplied") ;
if (*ptr & 0x80) { nLen = (*ptr & 0x70) >> 4 ; bNeg = *ptr & 0x0c ; nValue = *ptr & 0x03 ;
switch (nLen) { case 0: nValue <<= 8 ; nValue += ptr[1] ; break ; case 1: nValue <<= 16 ; _endian_import2(inc, ptr+1) ; nValue += inc ; break ; case 2: nValue <<= 24 ; _endian_import3(inc, ptr+1) ; nValue += inc ; break ; case 3: nValue <<= 32 ; _endian_import4(inc, ptr+1) ; nValue += inc ; break ; case 4: nValue <<= 40 ; _endian_import5(inc, ptr+1) ; nValue += inc ; break ; case 5: nValue <<= 48 ; _endian_import6(inc, ptr+1) ; nValue += inc ; break ; case 6: nValue <<= 56 ; _endian_import7(inc, ptr+1) ; nValue += inc ; break ; default: _endian_import8(inc, ptr+1) ; nValue = (int64_t) inc ; break ; }
if (bNeg && nLen < 7) nValue *= -1 ; } else { nLen = 1 ; nValue = *ptr & 0x7f ; }
return E_OK ; }
hzEcode ReadSerialUINT32 (uint32_t& nValue, uint32_t& nLen, const uchar* ptr) { // Convert a serialized integer into a 32-bit unsigned integer. // // Arguments: 1) nValue Indicated length or value // 2) nLen The size of the indicator itself // 3) ptr Pointer into a uchar buffer (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
if (!ptr) return hzerr(E_ARGUMENT, "No length indicator supplied") ;
if (*ptr & 0x80) { // Top bit set so indicator length will be ... switch (*ptr & 0xE0) { case 0x80: // 100xxxxx: 2 byte serial nValue = ((ptr[0] & 0x1f) << 8) ; nValue += ptr[1] ; nLen = 2 ; break ;
case 0xA0: // 101xxxxx: 3 byte serial nValue += ((ptr[1] << 8) + ptr[2]) ; nLen = 3 ; break ;
case 0xC0: // 110xxxxx: 4 byte serial nValue += ((ptr[1] << 16) + (ptr[2] << 8) + ptr[3]) ; nLen = 4 ; break ;
case 0xE0: // 11100000: Next 4 bytes _endian_import4(nValue, ptr + 1) ; nLen = 5 ; break ; } } else { nLen = 1 ; nValue = *ptr & 0x7f ; }
return E_OK ; }
hzEcode ReadSerialSINT32 (int32_t& nValue, uint32_t& nLen, const uchar* ptr) { // Convert a serialized integer into a 32-bit signed integer. // // Arguments: 1) nValue Indicated length or value // 2) nLen The size of the indicator itself // 3) ptr Pointer into a uchar buffer (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint32_t val ; // Value bool bNeg ; // Negative
if (!ptr) { nValue = 0 ; nLen = 0 ; return E_ARGUMENT ; }
if (!(*ptr & 0x80)) { bNeg = *ptr & 0x40 ; val = *ptr & 0x3f ; } else { // Top bit set so indicator length will be ... bNeg = *ptr & 0x10 ; nLen = (*ptr & 0x60) >> 5 ; nLen += 2 ;
switch (nLen) { case 2: val = ((ptr[0] & 0x0f) << 8) ; val += ptr[1] ; break ;
case 3: val = ((ptr[0] & 0x0f) << 16) ; val += ((ptr[1] << 8) + ptr[2]) ; break ;
case 4: val = ((ptr[0] & 0x0f) << 24) ; val += ((ptr[1] << 16) + (ptr[2] << 8) + ptr[3]) ; break ;
case 5: _endian_import4(val, ptr) ; break ; } }
nValue = bNeg ? -val : val ; return E_OK ; }
/* ** Serialized Integer Read Functions: Restores to uint64, int64, uint32 and int32 from hzChain input */
hzEcode ReadSerialUINT64 (uint64_t& nValue, hzChain::Iter& zi) { // Convert a serialized integer into a 64-bit unsigned integer. // // Arguments: 1) nValue Indicated length or value // 2) zi Chain iterator (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint64_t val ; // Value uint32_t nLen ; // Length of serial integer uint32_t n ; // Counter
if (!(*zi & 0x80)) { val = *zi & 0x7f ; zi++ ; } else { // Top bit set so indicator length will be ... nLen = (*zi & 0x70) >> 4 ; nLen += 2 ; val = *zi & 0x0f ;
if (nLen == 9) { // Max value, next 8 bytes are the number val = 0 ; }
for (n = nLen == 9 ? 1 : 2 ; n < nLen ; n++) { zi++ ; val <<= 8 ; val += *zi ; } }
nValue = val ; return E_OK ; }
hzEcode ReadSerialSINT64 (int64_t& nValue, hzChain::Iter& zi) { // Convert a serialized integer into a 64-bit signed integer. // // Arguments: 1) nValue Indicated length or value // 2) zi Chain iterator (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint64_t val ; // Value uint32_t n ; // Counter uint32_t nLen ; // Length of serial integer bool bNeg ; // Negative
bNeg = *zi & 0x40 ;
if (!(*zi & 0x80)) { val = *zi & 0x3f ; zi++ ; } else { // Top bit set so indicator length will be ... nLen = (*zi & 0x70) >> 4 ; nLen += 2 ; val = *zi & 0x0f ;
if (nLen == 9) { // Max value, next 8 bytes are the number val = 0 ; }
for (n = nLen == 9 ? 1 : 2 ; n < nLen ; n++) { zi++ ; val <<= 8 ; val += *zi ; } }
nValue = bNeg ? -val : val ; return E_OK ; }
hzEcode ReadSerialUINT32 (uint32_t& nValue, hzChain::Iter& zi) { // Convert a serialized integer into a 32-bit unsigned integer. // // Arguments: 1) nValue Indicated length or value // 2) zi Chain iterator (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint32_t val ; // Value
if (!(*zi & 0x80)) { nValue = *zi & 0x7f ; zi++ ; return E_OK ; }
switch (*zi & 0xE0) { case 0x80: // 100xxxxx: 2 byte value val = *zi & 0x1f ; zi++ ; val <<= 8 ; val += (uchar) *zi ; break ;
case 0xA0: // 101xxxxx: 3 byte value val = *zi & 0x1f ; zi++ ; val <<= 8 ; val += (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; break ;
case 0xC0: // 110xxxxx: 4 byte value val = *zi & 0x1f ; zi++ ; val <<= 8 ; val += (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; break ;
case 0xE0: // 11100000: Next 4 bytes are the value zi++ ; val = (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; zi++ ; val <<= 8 ; val += (uchar) *zi ; break ; }
zi++ ; nValue = val ; return E_OK ; }
hzEcode ReadSerialSINT32 (int32_t& nValue, hzChain::Iter& zi) { // Convert a serialized integer into a 32-bit signed integer. // // Arguments: 1) nValue Indicated length or value // 2) zi Chain iterator (start of indicator) // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint32_t val ; // Value bool bNeg ; // Negative
bNeg = *zi & 0x40 ;
if (!(*zi & 0x80)) { val = *zi & 0x3f ; zi++ ; } else { switch (*zi & 0x30) { case 0x00: // 1n00xxxx: 2 byte value val = *zi & 0x0f ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; break ;
case 0x10: // 1n01xxxx: 3 byte value val = *zi & 0x0f ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; break ;
case 0x20: // 1n10xxxx: 4 byte value val = *zi & 0x0f ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; break ;
case 0x30: // 1n11xxxx: Next 4 bytes are the value zi++ ; val = (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; zi++ ; val <<= 8 ; val+= (uchar) *zi ; break ; } }
nValue = bNeg ? -val : val ; return E_OK ; }
/* ** Serialized Integer Read Functions: Restores to uint64 and uint32 from hzXbuf input. Note that there are currently no signed variants and no Write functions to hzXbuf. */
hzEcode ReadSerialUINT64 (uint64_t& nValue, xbufIter& zi) { // Convert a serialized integer into a 64-bit unsigned integer. // // Arguments: 1) nValue Restored integer // 2) zi X-buffer iterator // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint64_t val ; // Value uint32_t n ; // Counter
val = nValue = 0 ;
if (zi.eof()) return E_OK ;
if (!(*zi & 0x80)) { nValue = *zi & 0x7f ; zi++ ; return E_OK ; }
switch (*zi & 0xF0) { case 0x80: // 1000 xxxx: 2 byte value val = *zi & 0x0f ; val <<= 8 ; zi++ ; val += *zi ; break ;
case 0x90: // 1001 xxxx: 3 byte value val = *zi & 0x0f ; for (n = 2 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xA0: // 1010 xxxx: 4 byte value val = *zi & 0x0f ; for (n = 3 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xB0: // 1011 xxxx: 5 byte value val = *zi & 0x0f ; for (n = 4 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xC0: // 1100 xxxx: 6 byte value val = *zi & 0x0f ; for (n = 5 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xD0: // 1101 xxxx: 7 byte value val = *zi & 0x0f ; for (n = 6 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xE0: // 1110 xxxx: 8 byte value val = *zi & 0x0f ; for (n = 7 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ;
case 0xF0: // 1111 xxxx: Value in next 8 bytes zi++ ; val = *zi ; for (n = 7 ; n ; n--) { val <<= 8 ; zi++ ; val += *zi ; } break ; }
nValue = val ; return E_OK ; }
hzEcode ReadSerialUINT32 (uint32_t& nValue, xbufIter& zi) { // Convert a serialized integer into a 32-bit unsigned integer. // // Arguments: 1) nValue Restored integer // 2) zi X-buffer iterator // // Returns: E_ARGUMENT If no ptr is supplied // E_OK Operation successful
uint32_t val = 0 ; // Value
if (zi.eof()) { nValue = 0 ; return E_OK ; }
if (!(*zi & 0x80)) { val = *zi & 0x7f ; zi++ ; nValue = val ; return E_OK ; }
switch (*zi & 0xE0) { case 0x80: // 100x xxxx: 2 byte value val = ((*zi & 0x1f) << 8) ; zi++ ; val += *zi ; break ;
case 0xA0: // 101x xxxx: 3 byte value val = ((*zi & 0x1f) << 16) ; zi++ ; val += (*zi << 8) ; zi++ ; val += *zi ; break ;
case 0xC0: // 110x xxxx: 4 byte value val = ((*zi & 0x1f) << 24) ; zi++ ; val += (*zi << 16) ; zi++ ; val += (*zi << 8) ; zi++ ; val += *zi ; break ;
case 0xE0: // 111x xxxx: Value is in the next 4 bytes zi++ ; val = (*zi << 24) ; zi++ ; val += (*zi << 16) ; zi++ ; val += (*zi << 8) ; zi++ ; val += *zi ; break ; }
zi++ ; nValue = val ; return E_OK ; }
/* ** Serialized Integer Write Functions: Write to hzChain, serialized integer of uint64, int64, uint32 and int32 */
void WriteSerialUINT64 (hzChain& Z, uint32_t& nLen, uint64_t nValue) { // Serialize unsigned 64-bit integer to a hzChain. // // Arguments: 1) Z Chain appended by the length indicator // 2) nLen The size of the indicator itself (set by this function) // 3) nValue Indicated length or value // // Returns: None
if (nValue < 0x80) { // Bit 0 is 0, bits 1-7 are the value nLen = 1 ; Z.AddByte(nValue & 0x7f) ; } else if (nValue < 0x1000) { // 2 byte serial integer. Control byte is 1000 xxxx. Total range 12 bits. nLen = 2 ; Z.AddByte(0x80 + ((nValue & 0x0f00) >> 8)) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x100000) { // 3 byte serial integer. Control byte is 1001 xxxx. Total range 20 bits. nLen = 3 ; Z.AddByte(0x90 + ((nValue & 0x0f0000) >> 16)) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x10000000) { // 4 byte serial integer. Control byte is 1010 xxxx. Total range 28 bits. nLen = 4 ; Z.AddByte(0xA0 + ((nValue & 0x0f000000) >> 24)) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x1000000000) { // 5 byte serial integer. Control byte is 1011 xxxx. Total range 36 bits. nLen = 5 ; Z.AddByte(0xB0 + ((nValue & 0x0f00000000) >> 32)) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x100000000000) { // 6 byte serial integer. Control byte is 1100 xxxx. Total range 44 bits. nLen = 6 ; Z.AddByte(0xC0 + ((nValue & 0x0f0000000000) >> 40)) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x10000000000000) { // 7 byte serial integer. Control byte is 1101 xxxx. Total range 52 bits. nLen = 7 ; Z.AddByte(0xD0 + ((nValue & 0x0f000000000000) >> 48)) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x1000000000000000) { // 8 byte serial integer. Control byte is 1110 xxxx. Total range 60 bits. nLen = 8 ; Z.AddByte(0xE0 + ((nValue & 0x0f00000000000000) >> 56)) ; Z.AddByte((nValue & 0xff000000000000) >> 48) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else { // 9 byte serial integer (8 byte absolute value). Control byte is 1111 0000. Total range 64 bits. nLen = 5 ; Z.AddByte(0xf0) ; Z.AddByte((nValue & 0xff00000000000000) >> 56) ; Z.AddByte((nValue & 0xff000000000000) >> 48) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } }
void WriteSerialSINT64 (hzChain& Z, uint32_t& nLen, int64_t nValue) { // Serialize signed 64-bit integer to a hzChain. // // Arguments: 1) Z Chain appended by the length indicator // 2) nLen The size of the indicator itself (set by this function) // 3) nValue Indicated length or value // // Returns: None
bool bNeg ; // Set if negative char byte ; // Byte to write
if (nValue < 0) { bNeg = true ; nValue *= -1 ; }
if (nValue < 0x40) { // Bit 0 is 0, bit 1 is negator, bits 2 thru 7 are the value nLen = 1 ; byte = bNeg ? 0x40 : 0 ; byte |= nValue ; Z.AddByte(byte) ; } else if (nValue < 0x0800) { // Bit 0 is 1, bits 1, 2 and 3 are controls (000), bit 4 is the negator, bits 5-7 are top 3 bits of value, 1 more byte to go nLen = 2 ; byte = bNeg ? 0x88 : 0x80 ; byte |= ((nValue & 0x0700) >> 8) ; Z.AddByte(byte) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x080000) { // Bit 0 is 1, bits 1, 2 and 3 are controls (001), bit 4 is the negator, bits 5-7 are top 3 bits of value, 2 more bytes to go nLen = 3 ; byte = bNeg ? 0x98 : 0x90 ; byte |= ((nValue & 0x070000) >> 16) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x08000000) { // Bit 0 is 1, bits 1 and 2 are controls (010), bit 4 is the negator, bits 5-7 are top 3 bits of value, 3 more bytes to go nLen = 4 ; byte = bNeg ? 0xA8 : 0xA0 ; byte |= ((nValue & 0x07000000) >> 24) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x0800000000) { // Bit 0 is 1, bits 1 and 2 are controls (011), bit 4 is the negator, bits 5-7 are top 3 bits of value, 4 more bytes to go nLen = 4 ; byte = bNeg ? 0xB8 : 0xB0 ; byte |= ((nValue & 0x0700000000) >> 32) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x080000000000) { // Bit 0 is 1, bits 1 and 2 are controls (100), bit 4 is the negator, bits 5-7 are top 3 bits of value, 5 more bytes to go nLen = 4 ; byte = bNeg ? 0xC8 : 0xC0 ; byte |= ((nValue & 0x0700000000) >> 40) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x08000000000000) { // Bit 0 is 1, bits 1 and 2 are controls (101), bit 4 is the negator, bits 5-7 are top 3 bits of value, 6 more bytes to go nLen = 4 ; byte = bNeg ? 0xD8 : 0xD0 ; byte |= ((nValue & 0x070000000000) >> 48) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x08000000000000) { // Bit 0 is 1, bits 1 and 2 are controls (110), bit 4 is the negator, bits 5-7 are top 3 bits of value, 7 more bytes to go nLen = 4 ; byte = bNeg ? 0xD8 : 0xD0 ; byte |= ((nValue & 0x07000000000000) >> 56) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff000000000000) >> 48) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else { // Bit 0 is 1, bits 1 and 2 are controls (111), bit 4 is the negator, 8 more bytes to go nLen = 5 ; byte = bNeg ? 0xF8 : 0xF0 ; byte |= ((nValue & 0x0f000000) >> 24) ; Z.AddByte(0xC0) ; Z.AddByte((nValue & 0xff00000000000000) >> 56) ; Z.AddByte((nValue & 0xff000000000000) >> 48) ; Z.AddByte((nValue & 0xff0000000000) >> 40) ; Z.AddByte((nValue & 0xff00000000) >> 32) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } }
void WriteSerialUINT32 (hzChain& Z, uint32_t& nLen, uint32_t nValue) { // Serialize unsigned 32-bit integer to a hzChain. // // Arguments: 1) Z Chain appended by the length indicator // 2) nLen The size of the indicator itself (set by this function) // 3) nValue Indicated length or value // // Returns: None
if (nValue < 0x80) { // Bit 0 is 0, bits 1-7 are the value nLen = 1 ; Z.AddByte(nValue & 0x7f) ; } else if (nValue < 0x2000) { // 100xxxxx: 2 byte value nLen = 2 ; Z.AddByte(0x80 + ((nValue & 0x1f00) >> 8)) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x200000) { // 101xxxxx: 3 byte value nLen = 3 ; Z.AddByte(0xA0 + ((nValue & 0x1f0000) >> 16)) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x20000000) { // 110xxxxx: 4 byte value nLen = 4 ; Z.AddByte(0xC0 + ((nValue & 0x1f000000) >> 24)) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else { // 11100000: Value in the next 4 bytes nLen = 5 ; Z.AddByte(0xE0) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } }
void WriteSerialSINT32 (hzChain& Z, uint32_t& nLen, int32_t nValue) { // Serialize signed 32-bit integer to a hzChain. // // Arguments: 1) Z Chain appended by the length indicator // 2) nLen The size of the indicator itself (set by this function) // 3) nValue Indicated length or value // // Returns: None
bool bNeg ; // Set if negative char byte ; // Byte to write
if (nValue < 0) { bNeg = true ; nValue *= -1 ; }
if (nValue < 0x40) { // Bit 0 is 0, bit 1 is negator, bits 2 thru 7 are the value nLen = 1 ; byte = bNeg ? 0x40 : 0 ; byte |= nValue ; Z.AddByte(byte) ; } else if (nValue < 0x1000) { // Bit 0 is 1, bits 1 and 2 are controls (00), bit 3 is the negator, bits 4-7 are top 4 bits of value, 1 more byte to go nLen = 2 ; byte = bNeg ? 0x90 : 0x80 ; byte |= ((nValue & 0x0f00) >> 8) ; Z.AddByte(byte) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x400000) { // Bit 0 is 1, bits 1 and 2 are controls (01), bit 3 is the negator, bits 4-7 are top 4 bits of value, 2 more bytes to go nLen = 3 ; byte = bNeg ? 0xB0 : 0xA0 ; byte |= ((nValue & 0x0f0000) >> 16) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else if (nValue < 0x40000000) { // Bit 0 is 1, bits 1 and 2 are controls (10), bit 3 is the negator, bits 4-7 are top 4 bits of value, 3 more bytes to go nLen = 4 ; byte = bNeg ? 0xD0 : 0xC0 ; byte |= ((nValue & 0x0f000000) >> 24) ; Z.AddByte(byte) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } else { // Bit 0 is 1, bits 1 and 2 are controls (11), bit 3 is the negator, bits 4-7 are top 4 bits of value, 3 more bytes to go nLen = 5 ; byte = bNeg ? 0xF0 : 0xE0 ; byte |= ((nValue & 0x0f000000) >> 24) ; Z.AddByte(0xC0) ; Z.AddByte((nValue & 0xff000000) >> 24) ; Z.AddByte((nValue & 0xff0000) >> 16) ; Z.AddByte((nValue & 0xff00) >> 8) ; Z.AddByte(nValue & 0xff) ; } }
/* ** SECTION 2: BASE 64 CODEC */
//hzString Base64Encode (const char* pAscii) ; //hzString Base64Decode (const char* pBase64) ;
/* ** Support macro definitions for Base-64 CODEC: */
#define b64is7bit(c) ((c) > 0x7f ? 0 : 1) // Valid 7-Bit ASCII character? #define b64blocks(l) (((l) + 2) / 3 * 4 + 1) // Length rounded to 4 byte block. #define b64octets(l) ((l) / 4 * 3 + 1) // Length rounded to 3 byte octet.
#define _Base64Size(n) ((((n+2)/3)*4)+4) #define AsciiSize(n) (((n/4)*3)+1) #define Is7Bit(ch) (ch & 0x80 ? 0:1) #define IsBase64Ch(ch) ()
#define _get6bit(z) (z>='A'&&z<='Z'? z-'A' : z>='a'&&z<='z'? z-'a'+26 : z>='0'&&z<='9'? z-'0'+52 : z=='+'? 62 : z=='/'? 63 : z=='='? 100 : 101) #define _get1hex(z) (z>='A' && z<='F' ? z-'A'+10 : z>='a' && z<='f' ? z-'a'+10 : z>='0' && z<='9' ? z-'0' : -1)
// Note: Tables are in hex to support different collating sequences static const char* s_base64_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; // Array of allowed base-64 characters
static const uchar pIndex [] = { // Collation sequence 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f } ;
static const uchar pBase64 [] = { // Collation sequence 0x3e, 0x7f, 0x7f, 0x7f, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 } ;
bool _b64valid (uchar* c) { // Category: Codec // // Tests for a valid Base64 char. // // Arguments: 1) c The test char // // Returns: True If the char belongs in the Base64 character set // False Otherwise
if ((*c < 0x2b) || (*c > 0x7a)) return false ; if ((*c = pBase64[*c - 0x2b]) == 0x7f) return false ;
return true ; }
/* ** Base-64 functions */
void Base64Encode (hzChain& Encoded, const char* pRaw) { // Category: Codec // // Encode 7-Bit ASCII in the input chain to Base64 in the output chain. // // Arguments: 1) Encoded The chain to contain the encoded data // 2) pRaw The chain containing the 7-Bit ASCII data to encode // // Returns: None
_hzfunc("Base64Encode(char*)") ;
const char* r ; // Raw input chain iterator int32_t A ; // A is top 6 bits of byte 1 of 3 shifted down by 2 int32_t B ; // B is low 2 bits of byte 2 of 3 shifted up by 4 and top 4 bits of 'b' shifted down by 4 int32_t C ; // C is low 4 bits of byte 3 of 3 shifted up by 2 and top 2 bits of 'c' shifted down by 6 int32_t D ; // D is low 6 bits of byte 3 int32_t nSeg = 0 ; // Newline marker uchar a ; // 1st byte of 3-byte segment uchar b ; // 2nd byte of 3-byte segment uchar c ; // 3rd byte of 3-byte segment uchar bits ; // Count of bits in segment (at end can be less than 3) char buf [8] ; // Export encoded set of 4 bytes
Encoded.Clear() ; if (!pRaw || !pRaw[0]) return ;
for (r = pRaw ; *r ; r++) { // Fill the 3 bytes of source
a = b = c = bits = 0 ; a = *r ; r++ ; bits++ ; if (*r) { b = *r ; r++ ; bits++ ; if (*r) { c = *r ; bits++ ; } }
// Then convert to 4 bytes. A = B = C = D = 0 ; A = ((a & 0xfc) >> 2) ; B = ((a & 0x03) << 4) ; B |= ((b & 0xf0) >> 4) ; C = ((b & 0x0f) << 2) ; C |= ((c & 0xc0) >> 6) ; D = c & 0x3f ;
buf[0] = bits ? s_base64_array[A] : '=' ; buf[1] = bits ? s_base64_array[B] : '=' ; buf[2] = bits > 1 ? s_base64_array[C] : '=' ; buf[3] = bits > 2 ? s_base64_array[D] : '=' ; buf[4] = 0 ;
Encoded += buf ;
nSeg++ ; if (nSeg == 19) { Encoded += "\r\n" ; nSeg = 0 ; } } }
void Base64Encode (hzChain& Encoded, const hzString& Raw) { // Category: Codec // // Encode 7-Bit ASCII in the input chain to Base64 in the output chain. // // Arguments: 1) Encoded The chain to contain the encoded data // 2) Raw The chain containing the 7-Bit ASCII data to encode // // Returns: None
_hzfunc("Base64Encode(hzString)") ;
const char* r ; // Raw input chain iterator int32_t A ; // A is top 6 bits of byte 1 of 3 shifted down by 2 int32_t B ; // B is low 2 bits of byte 2 of 3 shifted up by 4 and top 4 bits of 'b' shifted down by 4 int32_t C ; // C is low 4 bits of byte 3 of 3 shifted up by 2 and top 2 bits of 'c' shifted down by 6 int32_t D ; // D is low 6 bits of byte 3 int32_t nSeg = 0 ; // Newline marker uchar a ; // 1st byte of 3-byte segment uchar b ; // 2nd byte of 3-byte segment uchar c ; // 3rd byte of 3-byte segment uchar bits ; // Count of bits in segment (at end can be less than 3) char buf [8] ; // Export encoded set of 4 bytes
Encoded.Clear() ; if (!Raw) return ;
for (r = *Raw ; *r ; r++) { // Fill the 3 bytes of source
a = b = c = bits = 0 ; a = *r ; r++ ; bits++ ; if (*r) { b = *r ; r++ ; bits++ ; if (*r) { c = *r ; bits++ ; } }
// Then convert to 4 bytes. A = B = C = D = 0 ; A = ((a & 0xfc) >> 2) ; B = ((a & 0x03) << 4) ; B |= ((b & 0xf0) >> 4) ; C = ((b & 0x0f) << 2) ; C |= ((c & 0xc0) >> 6) ; D = c & 0x3f ;
buf[0] = bits ? s_base64_array[A] : '=' ; buf[1] = bits ? s_base64_array[B] : '=' ; buf[2] = bits > 1 ? s_base64_array[C] : '=' ; buf[3] = bits > 2 ? s_base64_array[D] : '=' ; buf[4] = 0 ;
Encoded += buf ;
nSeg++ ; if (nSeg == 19) { Encoded += "\r\n" ; nSeg = 0 ; } } }
void Base64Encode (hzChain& Encoded, const hzChain& Raw) { // Category: Codec // // Encode 7-Bit ASCII in the input chain to Base64 in the output chain. // // Arguments: 1) Encoded The chain to contain the encoded data // 2) Raw The chain containing the 7-Bit ASCII data to encode // // Returns: None
_hzfunc("Base64Encode(hzChain)") ;
chIter r ; // Raw input chain iterator int32_t A ; // A is top 6 bits of byte 1 of 3 shifted down by 2 int32_t B ; // B is low 2 bits of byte 2 of 3 shifted up by 4 and top 4 bits of 'b' shifted down by 4 int32_t C ; // C is low 4 bits of byte 3 of 3 shifted up by 2 and top 2 bits of 'c' shifted down by 6 int32_t D ; // D is low 6 bits of byte 3 int32_t nSeg = 0 ; // Newline marker uchar a ; // 1st byte of 3-byte segment uchar b ; // 2nd byte of 3-byte segment uchar c ; // 3rd byte of 3-byte segment uchar bits ; // Count of bits in segment (at end can be less than 3) char buf [8] ; // Export encoded set of 4 bytes
for (r = Raw ; !r.eof() ; r++) { // Fill the 3 bytes of source
a = b = c = bits = 0 ; a = *r ; r++ ; bits++ ; if (!r.eof()) { b = *r ; r++ ; bits++ ; if (!r.eof()) { c = *r ; bits++ ; } }
// Then convert to 4 bytes. A = B = C = D = 0 ; A = ((a & 0xfc) >> 2) ; B = ((a & 0x03) << 4) ; B |= ((b & 0xf0) >> 4) ; C = ((b & 0x0f) << 2) ; C |= ((c & 0xc0) >> 6) ; D = c & 0x3f ;
buf[0] = bits ? s_base64_array[A] : '=' ; buf[1] = bits ? s_base64_array[B] : '=' ; buf[2] = bits > 1 ? s_base64_array[C] : '=' ; buf[3] = bits > 2 ? s_base64_array[D] : '=' ; buf[4] = 0 ;
Encoded += buf ;
nSeg++ ; if (nSeg == 19) { Encoded += "\r\n" ; nSeg = 0 ; } } }
hzEcode Base64Encode (hzChain& Encoded, const char* dir, const char* fname) { // Category: Codec // // Encode the contents of the file with the supplied path, from 7-Bit ASCII to Base64. The encoded data is then in a hzChain instance. // // Arguments: 1) Encoded The chain to contain the encoded data // 2) dir The directory of the file containing the 7-Bit ASCII data to encode // 3) fname The file name within the directory // // Returns: E_ARGUMENT If either the directory or filename are not supplied // E_NOTFOUND If the filepath specified does not exist as a directory entry of any kind // E_TYPE If the filepath names a directory entry that is not a file // E_NODATA If the filepath is a file but empty // E_OPENFAIL If the file specified could not be opened for reading // E_OK If the input stream was opened and the content encoded
_hzfunc("Base64Encode(file)") ;
std::ifstream is ; // Input file stream
hzChain Z ; // To store unencoded input file hzString Path ; // Full pathname of file hzEcode rc ; // Return code
if (!dir || !dir[0]) return hzerr(E_ARGUMENT, "No directory supplied") ;
if (!fname || !fname[0]) return hzerr(E_ARGUMENT, "No filename supplied") ;
Path = dir ; Path += "/" ; Path += fname ;
rc = OpenInputStrm(is, *Path) ;
if (rc == E_OK) { Z << is ; is.close() ; Base64Encode(Encoded, Z) ; }
return rc ; }
/* ** Function Set: Base64Decode ** ** Decode a Base64 string to a 7-Bit ASCII string */
hzEcode Base64Decode (hzChain& Decoded, const char* s) { // Category: Codec // // Decode a Base64 string to a 7-Bit ASCII string // // Arguments: 1) Decoded The decoded string (in hzChain) // 2) s The Base64 data to decode (as char string) // // Returns: Instance of hzString by value being the decoded data
_hzfunc("Base64Decode(cstr)") ;
const char* i ; // Cstr iterator int32_t nBytes ; // Length of input string int32_t val ; // Holds 24 bit value to be written as 3 bytes int32_t a ; // 1st value int32_t b ; // 2nd value int32_t c ; // 3rd value int32_t d ; // 4th value
// Clear the supplied result chain Decoded.Clear() ;
// Not valid unless the string is an exact multiple of 4 bytes nBytes = strlen(s) ; if (nBytes % 4) return hzerr(E_FORMAT, "Supplied string is not an exact multiple of 4 bytes in length") ;
// Loop through collecting sets of 4 chars and writing out sets of 3 chars
for (i = s ; *i ;) { a = _get6bit(*i) ; i++ ; b = _get6bit(*i) ; i++ ; c = _get6bit(*i) ; i++ ; d = _get6bit(*i) ; i++ ;
if (a == 101 || b == 101 || c == 101 || d == 101) return E_FORMAT ;
val = 0 ; if (a < 100) val += (a << 18) ; if (b < 100) val += (b << 12) ; if (c < 100) val += (c << 6) ; if (d < 100) val += d ;
a = (val & 0xff0000) >> 16 ; b = (val & 0xff00) >> 8 ; c = val & 0xff ;
Decoded.AddByte(a) ; if (b) Decoded.AddByte(b) ; if (c) Decoded.AddByte(c) ;
if (*i == CHAR_NL) i++ ; if (*i == CHAR_CR) i++ ; }
return E_OK ; }
hzEcode Base64Decode (hzChain& Decoded, const hzString& str) { return Base64Decode(Decoded, *str) ; }
hzEcode Base64Decode (hzChain& Decoded, hzChain::Iter& ci) { // Category: Codec // // Decode base64 encoded source from the supplied chain iterator to the end of the source. // // This function is provided because bese64 encoded matter is often found partway into a chain (see email processing). By use of // this function a separate step of copying the partial chain is avoided // // Arguments: 1) Decoded Chain to contain result of decode operation // 2) ci Chain iterator into encoded data // // Returns: E_FORMAT If the input chain contains unexpected sequences // E_OK If the input was decoded
_hzfunc("Base64Decode(chIter)") ;
chIter zi ; // Iterator int32_t val ; // Holds 24 bit value to be written as 3 bytes int32_t a ; // Input 1st value int32_t b ; // Input 2nd value int32_t c ; // Input 3rd value int32_t d ; // Input 4th value
Decoded.Clear() ;
// Loop through collecting sets of 4 chars and writing out sets of 3 chars
zi = ci ; for (; !zi.eof() ;) { if (*zi == CHAR_CR) { zi++ ; continue ; } if (*zi == CHAR_NL) { zi++ ; continue ; }
a = _get6bit(*zi) ; zi++ ; b = _get6bit(*zi) ; zi++ ; c = _get6bit(*zi) ; zi++ ; d = _get6bit(*zi) ; zi++ ;
if (a == 101 || b == 101 || c == 101 || d == 101) return E_FORMAT ;
val = 0 ; if (a < 100) val += (a << 18) ; if (b < 100) val += (b << 12) ; if (c < 100) val += (c << 6) ; if (d < 100) val += d ;
a = (val & 0xff0000) >> 16 ; b = (val & 0xff00) >> 8 ; c = val & 0xff ;
Decoded.AddByte(a) ; if (b) Decoded.AddByte(b) ; if (c) Decoded.AddByte(c) ; }
return E_OK ; }
hzEcode Base64Decode (hzChain& Decoded, const hzChain& Raw) { // Category: Codec // // Decode base64 encoded source // // Arguments: 1) Decoded The decoded output // 2) Raw The encoded input // // Returns: E_FORMAT If the input chain contains unexpected sequences // E_OK If the input was decoded
_hzfunc("Base64Decode(hzChain)") ;
hzChain::Iter zi ; // Chain iterator (needed for call to BaseDecode(hzChain&,hzChain&)
zi = Raw ;
return Base64Decode(Decoded, zi) ; }
hzEcode Base64Decode (hzString& Decoded, const char* pRaw) { hzChain Z ; // Temp chain hzEcode rc ; // Return code
Decoded.Clear() ; rc = Base64Decode(Z, pRaw) ; if (rc == E_OK) Decoded = Z ; return rc ; }
hzEcode Base64Decode (hzString& Decoded, const hzString& raw) { hzChain Z ; // Temp chain hzEcode rc ; // Return code
Decoded.Clear() ; rc = Base64Decode(Z, raw) ; if (rc == E_OK) Decoded = Z ; return rc ; }
hzEcode Base64Decode (hzString& Decoded, const hzChain& raw) { hzChain Z ; // Temp chain hzEcode rc ; // Return code
Decoded.Clear() ; rc = Base64Decode(Z, raw) ; if (rc == E_OK) Decoded = Z ; return rc ; }
hzEcode Base64Decode (hzString& Decoded, hzChain::Iter& raw) { hzChain Z ; // Temp chain hzEcode rc ; // Return code
Decoded.Clear() ; rc = Base64Decode(Z, raw) ; if (rc == E_OK) Decoded = Z ; return rc ; }
/* ** SECTION 3: Quoted-Printable CODEC */
hzEcode QPDecode (hzString& Decoded, const char* pRaw) { // Category: Codec // // Convert a QP encoded cstr, back to it's original form. // // Arguments: 1) Decoded The hzString reference that will contain the result. Any pre-existing contents of this are cleared at the outset. // 2) pRaw The encoded cstr. // // Returns: E_NODATA If the encoded cstr is empty // E_FORMAT If there is an error in conversion // E_OK If the operation is successful
_hzfunc("QPDecode") ;
hzChain R ; // Result const char* i ; // Iterator int32_t val ; // Holds 24 bit value to be written as 3 bytes
if (!pRaw || !pRaw[0]) return E_NODATA ;
// Interate the input. On the occurence of '=', the next two bytes are hex for the actual char. i = pRaw ; for (; *i ;) { if (*i == '=') { i++ ; if (*i == CHAR_CR || *i == CHAR_NL) { // Just skip to next line if (*i == CHAR_CR) i++ ; if (*i == CHAR_NL) i++ ;
continue ; }
if (!IsHex(*i)) return E_FORMAT ; val = _get1hex(*i) ;
i++ ; if (!IsHex(*i)) return E_FORMAT ; val *= 16 ; val += _get1hex(*i) ;
R.AddByte(val) ; i++ ; continue ; }
R.AddByte(*i) ; i++ ; }
Decoded = R ; //threadLog("decoded=[%s]\n", *Decoded) ; return E_OK ; }
hzEcode QPDecode (hzChain& Decoded, const hzChain& Raw) { // Category: Codec // // Convert a hzChain whose content is presumed to encoded using the Quoted-Printable method, back to it's original form. // // Arguments: 1) Decoded The hzChain reference that will contain the result. Any pre-existing contents of this are cleared at the outset. // 2) Raw The encoded hzChain. This is not altered by this operation. // // Returns: E_NODATA If the encoded chain is empty // E_FORMAT If there is an error in conversion // E_OK If the operation is successful
_hzfunc("QPDecode") ;
chIter zi ; // Iterator int32_t val ; // Holds 24 bit value to be written as 3 bytes
Decoded.Clear() ; if (!Raw.Size()) return E_NODATA ;
// Interate the input. On the occurence of '=', the next two bytes are hex for the actual char. zi = Raw ; for (; !zi.eof() ;) { if (*zi == '=') { zi++ ; if (*zi == CHAR_CR || *zi == CHAR_NL) { // Just skip to next line if (*zi == CHAR_CR) zi++ ; if (*zi == CHAR_NL) zi++ ;
continue ; }
if (zi.eof() || !IsHex(*zi)) return E_FORMAT ; val = _get1hex(*zi) ;
zi++ ; if (zi.eof() || !IsHex(*zi)) return E_FORMAT ; val *= 16 ; val += _get1hex(*zi) ;
Decoded.AddByte(val) ; zi++ ; continue ; }
Decoded.AddByte(*zi) ; zi++ ; }
return E_OK ; }
hzEcode CharsetStringDecode (hzString& Decoded, const hzString& raw) { // Perform QP or Base64 decoding on strings in which the form of encoding used, is indicated in the string itself. The indicators are of the general form of =?charset?ecoding?, // e.g. =?utf-8?q? (QP) or =?utf-8?b? (Base64). The decoding is applied to all chars in the string that are enclosed by such an indicator and a terminator (either a 0, or a ?= // sequence). // // This function does not actually care about charsets. It applies either QP or Base64 decoding to all chars found between the starting sequence (e.g. =?utf-8?q?), upto the // terminator (either a 0 or a ?= sequence).
_hzfunc(__func__) ;
const char* i ; // Iterator const char* j ; // Aux iterator char* x ; // Output iterator char* limit ; // Limit of buffer char* outBuf ; // Output buffer int32_t val ; // Holds 24 bit value to be written as 3 bytes int32_t a ; // Input 1st value int32_t b ; // Input 2nd value int32_t c ; // Input 3rd value int32_t d ; // Input 4th value
Decoded.Clear() ; if (!raw) return E_OK ;
x = outBuf = new char[raw.Length() + 4] ; limit = outBuf + (raw.Length() + 3) ; memset(outBuf, 0, raw.Length() + 4) ;
for (i = *raw ; *i ; i++) { if (*i == CHAR_EQUAL && i[1] == CHAR_QUERY) { for (j = i + 2 ; *j && *j != CHAR_QUERY ; j++) ; if (j[0] == CHAR_QUERY && j[2] == CHAR_QUERY) { if (j[1] == 'b' || j[1] == 'B') { // Use Base64 for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; }
a = _get6bit(*i) ; i++ ; b = _get6bit(*i) ; i++ ; c = _get6bit(*i) ; i++ ; d = _get6bit(*i) ; i++ ;
if (a == 101 || b == 101 || c == 101 || d == 101) return E_FORMAT ;
val = 0 ; if (a < 100) val += (a << 18) ; if (b < 100) val += (b << 12) ; if (c < 100) val += (c << 6) ; if (d < 100) val += d ;
a = (val & 0xff0000) >> 16 ; b = (val & 0xff00) >> 8 ; c = val & 0xff ;
if (a && x != limit) *x++ = a ; if (b && x != limit) *x++ = b ; if (c && x != limit) *x++ = c ; } } else if (j[1] == 'q' || j[1] == 'Q') { // Use QP for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; }
if (*i == CHAR_EQUAL && IsHex(i[1]) && IsHex(i[2])) { i++ ; val = _get1hex(*i) ; i++ ; val *= 16 ; val += _get1hex(*i) ; if (val && x != limit) *x++ = val ; continue ; } if (*i && x != limit) *x++ = *i ; } } else { // Don't decode but copy all enclosed chars to the output for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; } if (*i && x != limit) *x++ = *i ; } } continue ; } // Drop through }
if (*i && x != limit) *x++ = *i ; } if (*i && x != limit) *x = 0 ;
Decoded = outBuf ; delete outBuf ; return E_OK ; }
#if 0 hzEcode CharsetStringDecode (hzString& Decoded, hzChain::Iter& raw) { // Perform QP or Base64 decoding on strings in which the form of encoding used, is indicated in the string itself. The indicators are of the general form of =?charset?ecoding?, // e.g. =?utf-8?q? (QP) or =?utf-8?b? (Base64). The decoding is applied to all chars in the string that are enclosed by such an indicator and a terminator (either a 0, or a ?= // sequence). // // This function does not actually care about charsets. It applies either QP or Base64 decoding to all chars found between the starting sequence (e.g. =?utf-8?q?), upto the // terminator (either a 0 or a ?= sequence).
_hzfunc(__func__) ;
chIter zi ; // Iterator const char* i ; // Iterator const char* j ; // Aux iterator char* x ; // Output iterator char* outBuf ; // Output buffer int32_t val ; // Holds 24 bit value to be written as 3 bytes int32_t a ; // Input 1st value int32_t b ; // Input 2nd value int32_t c ; // Input 3rd value int32_t d ; // Input 4th value
Decoded.Clear() ; if (!raw) return E_OK ;
x = outBuf = new char[raw.Length()] ;
zi = raw ; if (zi.eof()) return E_OK ;
for (i = *raw ; *i ; i++) { if (*i == '=') { if (i[1] == '?') { for (j = i + 2 ; *j && *j != CHAR_QUERY ; j++) ; if (j[0] == CHAR_QUERY && j[2] == CHAR_QUERY) { if (j[1] == 'b' || j[1] == 'B') { // Use Base64 for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; }
a = _get6bit(*i) ; i++ ; b = _get6bit(*i) ; i++ ; c = _get6bit(*i) ; i++ ; d = _get6bit(*i) ; i++ ;
if (a == 101 || b == 101 || c == 101 || d == 101) return E_FORMAT ;
val = 0 ; if (a < 100) val += (a << 18) ; if (b < 100) val += (b << 12) ; if (c < 100) val += (c << 6) ; if (d < 100) val += d ;
a = (val & 0xff0000) >> 16 ; b = (val & 0xff00) >> 8 ; c = val & 0xff ;
*x++ = a ; if (b) *x++ = b ; if (c) *x++ = c ; } } else if (j[1] == 'q' || j[1] == 'Q') { // Use QP for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; }
if (*i == CHAR_EQUAL && IsHex(i[1]) && IsHex(i[2])) { i++ ; val = _get1hex(*i) ; i++ ; val *= 16 ; val += _get1hex(*i) ; *x++ = val ; continue ; } *x++ = *i ; } } else { // Don't decode but copy all enclosed chars to the output for (i = j + 3 ; *i ; i++) { if (i[0] == CHAR_QUERY && i[1] == CHAR_EQUAL) { i += 2 ; break ; } *x++ = *i ; } } continue ; } // Drop through } // Drop through }
*x++ = *i ; } *x = 0 ;
Decoded = outBuf ; delete outBuf ; return E_OK ; } #endif
/* ** SECTION 4: gzip encoding/decoding */ hzEcode Gzip (hzChain& gzipped, const hzChain& orig) { // Category: Codec // // Perform a gzip compression operation on the supplied chain. // // Arguments: 1) gzipped The hzChain reference that will contain the result. Any pre-existing contents of this are cleared at the outset. // 2) orig The original hzChain. This is not altered by this operation. // // Returns: E_NODATA If the original is empty // E_NOINIT If there is an error in conversion // E_OK If the operation is successful
_hzfunc(__func__) ;
chIter zi ; // Chain iterator for input z_stream defstream; // The zlib struct char* tmp ; // A string to convert chain to contiguous memory char* buf ; // Buffer to construct gzipped content int32_t err ; // Return code from init
gzipped.Clear() ; if (!orig.Size()) return E_NODATA ;
// Deflate original data defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL;
// setup tmp as the input and buf as the compressed output tmp = new char[orig.Size()+1] ; buf = new char[orig.Size()] ;
// for (n = 0, zi = orig ; !zi.eof() ; n++, zi++) // tmp[n] = *zi ; // tmp[n] = 0 ; zi = orig ; zi.Write(tmp, orig.Size()) ; tmp[orig.Size()] = 0 ;
defstream.avail_in = (uInt) orig.Size() ; defstream.next_in = (Bytef*) tmp; defstream.avail_out = (uInt) orig.Size() ; defstream.next_out = (Bytef*) buf;
// Initialize the zlib deflation (i.e. compression) internals with deflateInit2(). // // The parameters are as follows: // // z_streamp strm - Pointer to a zstream struct // // int level - Compression level. Must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression. // // int method - Compression method. Only method supported is "Z_DEFLATED". // // int windowBits - Base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8-15. Add 16 to windowBits to write a simple // gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no mod // time (set to zero), no header crc, and the operating system will be set to 255 (unknown). // // int memLevel - Amount of memory allocated for internal compression state. 1 uses minimum memory but is slow and reduces compression ratio; 9 uses maximum memory for // optimal speed. Default value is 8. // // int strategy - Used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), or // Z_HUFFMAN_ONLY to force Huffman encoding only (no string match)
err = deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); if (err != Z_OK) return hzerr(E_NOINIT, "Could not run deflate process") ;
// the actual compression work. deflate(&defstream, Z_FINISH); deflateEnd(&defstream);
// for (n = 0 ; n < defstream.total_out ; n++) // gzipped.AddByte(buf[n]) ; gzipped.Append(buf, defstream.total_out) ; delete tmp ; delete buf ;
if (!gzipped.Size()) return hzerr(E_NODATA, "Input %d bytes but no output", orig.Size()) ;
return E_OK ; }
hzEcode Gunzip (hzChain& orig, const hzChain& gzipped) { // Category: Codec // // On the presumption that the supplied data is zipped by gzip, this functions writes the date to a temporary file, calls 'gunzip' via a system call on this file and reads in // the unziped data. The temporary file and it's unziped associate are then unlinked. // // Arguments: 1) orig The chain to be populated with the unzipped data // 2) gzipped The chain containing the original (zipped) data // // Returns: E_NODATA If there is nothing to do // E_WRITEFAIL If the original data could not be written out to the temporary file // E_SYSERROR If the gunzip command could not be found or failed to process the data // E_READFIAL If the unzipped data could not be read back from the temporary file // E_OK If the operation was successful // // Note: Do not unzip files that contain multiple files and/or accross mutiple directories. It won't work and will leave a mess!
_hzfunc(__func__) ;
z_stream infstream ; // Input chIter zi ; // Chain iterator char* tmp ; // Zipped buffer char* buf ; // Unzipped buffer uint32_t n ; // Buffer iterator
tmp = new char[gzipped.Size()+1] ; buf = new char[20480] ;
for (n = 0, zi = gzipped ; !zi.eof() ; n++, zi++) tmp[n] = *zi ;
infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; infstream.opaque = Z_NULL;
// setup "b" as the input and "c" as the compressed output infstream.avail_in = (uInt) gzipped.Size() ; //((char*)defstream.next_out - b); // size of input infstream.next_in = (Bytef*)tmp ; // input char array infstream.avail_out = 20480 ; // (uInt)sizeof(c); // size of output infstream.next_out = (Bytef*)buf ; // output char array
// the actual DE-compression work. if (inflateInit2(&infstream, 31) != Z_OK) return E_NOINIT ;
inflate(&infstream, Z_NO_FLUSH); inflateEnd(&infstream);
for (n = 0 ; n < infstream.total_out ; n++) orig.AddByte(buf[n]) ; delete tmp ; delete buf ;
return E_OK ; }
/* ** SECTION 5: SHA512 Digest */
#if 0 hzEcode hzSHA512::CalcString (const hzString S) { _hzfunc("hzSHA512::CalcString") ;
SHA512_CTX sha512 ; // The calculation area
SHA512_Init(&sha512) ; SHA512_Update(&sha512, *S, S.Length()) ; SHA512_Final(m_Hash, &sha512) ;
memset(m_Hash, 0, SHA512_DIGEST_LENGTH) ; threadLog("Result %s\n", m_Hash) ;
return E_OK ; }
hzEcode hzSHA512::CalcChain (const hzChain& Z) { _hzfunc("hzSHA512::CalcString") ;
chIter zi ; SHA512_CTX sha512 ; // The calculation area int32_t nBytes ; // Bytes retrieved from chain uchar* pBuf ; // Operating buffer
memset(m_Hash, 0, SHA512_DIGEST_LENGTH) ; SHA512_Init(&sha512) ; pBuf = new uchar[2048] ; zi = Z ;
for (;;) { nBytes = zi.Write(pBuf, 2048) ; if (!nBytes) break ; zi += nBytes ;
SHA512_Update(&sha512, pBuf, nBytes) ; }
SHA512_Final(m_Hash, &sha512) ; delete[] pBuf ;
return E_OK ; }
const char* hzSHA512::Txt (void) const { _hzfunc("hzSHA512::Txt") ;
char* buf ; // Output buffer (allocated from the ...) int32_t i ; // Hash iterator int32_t n ; // Output iterator int32_t val ; // Value
buf = _thisfn.ScratchPad(132) ;
for (i = 0 ; i <= SHA512_DIGEST_LENGTH ; i++) { val = (m_Hash[i] & 0xf0) << 8 ; buf[n++] = val > 9 ? 'A' + val - 9 : '0' + val ; val = m_Hash[i] & 0x0f ; buf[n++] = val > 9 ? 'A' + val - 9 : '0' + val ; } buf[n] = 0 ;
return buf ; } #endif
/* ** Rotate amounts used in the algorithm */
static uint32_t s_sin_vals[] = { // Please note the following legal notice. This table is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // This array comprises 64 numbers such that the Ith value in the array is equal to the integer part of 4294967296 times abs(sin(I)) where I is in radians. // This is as prescribed in RFC1321.
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, } ;
static uchar s_sin_oset[] = { // Please note the following legal notice. This table is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, } ;
static uchar s_sin_shft[] = { // Please note the following legal notice. This table is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, } ;
class _md5_unit { // Please note the following legal notice. This class is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
public: uint32_t len ; uint32_t state[4] ; uint32_t resv ;
_md5_unit (void) { state[0] = 0x67452301 ; state[1] = 0xefcdab89 ; state[2] = 0x98badcfe ; state[3] = 0x10325476 ; } } ;
//_md5_unit *nil ;
//void _md5_encode (uchar* out, _md5_unit& md5Unit) //uint32_t* in, uint32_t len) void _md5_encode (uchar* out, uint32_t* in, uint32_t len) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // Encodes input. Assumes len is xple of 4 // // Arguments: 1) out Pointer into output buffer // 2) in Pointer into input buffer // 3) len Buffer length // // Returns: None
_hzfunc(__func__) ;
uint32_t x ; // Interim value uint32_t n ; // Counter
for (n = 0 ; n < len ; n++) { x = *in++ ; *out++ = x ; *out++ = x >> 8 ; *out++ = x >> 16 ; *out++ = x >> 24 ; } }
void _md5_decode (uint32_t* out, uchar* in, uint32_t len) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // Decodes input. Assumes len is xple of 4 // // Arguments: 1) out Pointer into output buffer // 2) in Pointer into input buffer // 3) len Buffer length // // Returns: None
_hzfunc(__func__) ;
uchar* e ; // Input limiter
for (e = in + len ; in < e ; in += 4) *out++ = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24) ; }
void _xlate_md5 (uchar* workBuf, uint32_t len, uchar* digest, _md5_unit& md5Unit) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // Perform MD5 translation // // Arguments: 1) p Pointer // 2) len Length of // 3) digest Pointer to the // 4) s Pointer to MD5 unit // // Returns: Pointer to an MD5 unit
_hzfunc(__func__) ;
uint32_t a ; // Part a of 32-bit interim value uint32_t b ; // Part b of 32-bit interim value uint32_t c ; // Part c of 32-bit interim value uint32_t d ; // Part d of 32-bit interim value uint32_t tmp ; // For variable rotation uint32_t i ; // Remainder uint32_t done ; // Process complete uchar* pWork ; // Pointer into working buffer uchar* end ; // Work limit uint32_t x[16] ;
md5Unit.len += len ;
pWork = workBuf ; i = len & 0x3f ; done = 0 ;
if (i || len == 0) { done = 1 ;
// Pad the input if (i < 56) i = 56 - i ; else i = 120 - i ; if (i > 0) { memset(pWork + len, 0, i) ; pWork[len] = 0x80 ; } len += i ;
// Append the count x[0] = md5Unit.len<<3 ; x[1] = md5Unit.len>>29 ; _md5_encode(pWork + len, x, 4) ; }
// Do the process for (end = pWork + len ; pWork < end ; pWork += 64) { a = md5Unit.state[0] ; b = md5Unit.state[1] ; c = md5Unit.state[2] ; d = md5Unit.state[3] ;
_md5_decode(x, pWork, 64) ; for(i = 0 ; i < 64 ; i++) { switch(i>>4) { case 0: a += (b & c) | (~b & d) ; break ; case 1: a += (b & d) | (c & ~d) ; break ; case 2: a += b ^ c ^ d ; break ; case 3: a += c ^ (b | ~d) ; break ; }
a += x[s_sin_oset[i]] + s_sin_vals[i] ; a = (a << s_sin_shft[i]) | (a >> (32 - s_sin_shft[i])) ; a += b ; // rotate variables tmp = d ; d = c ; c = b ; b = a ; a = tmp ; }
md5Unit.state[0] += a ; md5Unit.state[1] += b ; md5Unit.state[2] += c ; md5Unit.state[3] += d ; }
// return result if (done && digest) { _md5_encode(workBuf, (uint32_t*) &(md5Unit.state), 4) ; memcpy(digest, workBuf, 16) ; } return ; }
hzMD5::hzMD5 (void) { Clear() ; }
void hzMD5::Clear (void) { m_Parts[0] = m_Parts[1] = m_Parts[2] = m_Parts[3] = 0 ; }
bool hzMD5::IsNull (void) const { return m_Parts[0] == 0 && m_Parts[1] == 0 && m_Parts[2] == 0 && m_Parts[3] == 0 ? true : false ; }
hzMD5& hzMD5::operator= (const char* pMd5) { const char* i ; // Input iterator uint64_t val ; // Value of part uint32_t x ; // Outer loop counter (MD5 parts) uint32_t n ; // Inner loop counter (input bytes)
m_Parts[0] = m_Parts[1] = m_Parts[2] = m_Parts[3] = 0 ; if (!pMd5 || pMd5[0] == 0) return *this ;
for (x = 0 ; x < 4 ; x++) { for (val = 0, i = pMd5, n = 0 ; *i && n < 8 ; i++, n++) { val *= 16 ;
if (*i >= '0' && *i <= '9') val += (*i - '0') ; else if (*i >= 'A' && *i <= 'F') { val += 10 ; val += (*i - 'A') ; } else if (*i >= 'a' && *i <= 'f') { val += 10 ; val += (*i - 'a') ; } else break ; }
if (n < 8) { // Incorrect length break ; }
m_Parts[x] = val ; }
if (x < 4) m_Parts[0] = m_Parts[1] = m_Parts[2] = m_Parts[3] = 0 ; return *this ; }
hzMD5& hzMD5::operator= (const hzString& S) { if (S.Length() == 32) operator=(*S) ; else m_Parts[0] = m_Parts[1] = m_Parts[2] = m_Parts[3] = 0 ;
return *this ; }
bool hzMD5::operator== (const hzMD5& op) const { return m_Parts[0] == op.m_Parts[0] && m_Parts[1] == op.m_Parts[1] && m_Parts[2] == op.m_Parts[2] && m_Parts[3] == op.m_Parts[3] ? true : false ; }
bool hzMD5::operator!= (const hzMD5& op) const { return m_Parts[0] == op.m_Parts[0] && m_Parts[1] == op.m_Parts[1] && m_Parts[2] == op.m_Parts[2] && m_Parts[3] == op.m_Parts[3] ? false : true ; }
const char* hzMD5::Txt (void) const { // Category: Codec // // Present MD5 as a string // // Arguments: None // Returns: Instance of hzString with the MD5 as 32-char hex
_hzfunc("hzMD5::Txt") ;
char* pBuf ; // Working buffer
pBuf = _thisfn.ScratchPad(40) ;
sprintf(pBuf, "%08x%08x%08x%08x", m_Parts[0], m_Parts[1], m_Parts[2], m_Parts[3]) ; return pBuf ; }
hzEcode hzMD5::CalcMD5File (const char* filepath) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // Calculate the MD5 digest for the supplied file // // Arguments: 1) filepath The file to be hashed // // Returns: E_ARGUMENT If the filepath is not supplied // E_NOTFOUND If the filepath specified does not exist as a directory entry of any kind // E_TYPE If the filepath names a directory entry that is not a file // E_NODATA If the filepath is a file but empty // E_OPENFAIL If the file specified could not be opened for reading // E_OK If this MD5 value is calculated
_hzfunc("hzMD5::CalcMD5(file)") ;
ifstream is ; // Input stream _md5_unit md5Unit ; // MD5 encoding unit uchar* workBuf ; // Working data buffer int32_t n ; // Buffer limit hzEcode rc ; // Return code
rc = OpenInputStrm(is, filepath) ; if (rc != E_OK) return rc ;
n = 0 ; workBuf = new uchar[8196] ;
for (;;) { is.read((char*) (workBuf + n), 4096) ; if (!is.gcount()) break ;
n += is.gcount() ; if (n & 0x3f) continue ;
//s = _xlate_md5(workBuf, n, 0, md5Unit) ; _xlate_md5(workBuf, n, 0, md5Unit) ; n = 0 ; } //_xlate_md5(workBuf, n, m_md5val, md5Unit) ; _xlate_md5(workBuf, n, (uchar*) m_Parts, md5Unit) ;
delete [] workBuf ; is.close() ;
return E_OK ; }
hzEcode hzMD5::CalcMD5 (const hzChain& Z) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm // // Calculate the MD5 digest for the supplied file // // Arguments: 1) filepath The file to be hashed // // Returns: E_NODATA If the input chain is empty // E_OK If this MD5 value is calculated
_hzfunc("hzMD5::CalcMD5(hzChain)") ;
_md5_unit md5Unit ; // MD5 encoding unit chIter zi ; // Input chain iterator uchar* buf ; // Working data buffer uint32_t nBytes ; // No of bytes extracted from input chain
if (!this) hzexit(E_CORRUPT, "No instance") ;
if (!Z.Size()) return E_NODATA ;
zi = Z ; //s = nil ; nBytes = 0 ; buf = new uchar[8196] ;
for (;;) { nBytes = zi.Write(buf, 4096) ; if (!nBytes) break ;
zi += nBytes ; _xlate_md5(buf, nBytes, 0, md5Unit) ; } _xlate_md5(buf, nBytes, (uchar*) m_Parts, md5Unit) ;
delete [] buf ; return E_OK ; }
hzEcode hzMD5::CalcMD5 (const char* cstr) { // Category: Codec // // Please note the following legal notice. This function is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. // // Calculate the MD5 digest for the supplied null terminated string. // // Argument: cstr The string to be hashed // // Returns: E_ARGUMENT If no input cstr is supplied // E_OK If this MD5 value is calculated
_hzfunc("hzMD5::CalcMD5(cstr)") ;
_md5_unit md5Unit ; // MD5 encoding unit uchar* buf ; // Working data buffer uint32_t len ; // String length
if (!this) hzexit(E_CORRUPT, "No instance") ;
if (!cstr || !cstr[0]) return E_NODATA ;
len = strlen(cstr) ;
//s = nil ; buf = new uchar[(len * 2) + 4] ; strcpy((char*) buf, cstr) ;
_xlate_md5(buf, len, (uchar*) m_Parts, md5Unit) ;
delete [] buf ; return E_OK ; }