/// if we pack, compress, encode on the way in, that means, therefore, we /// need to decode, uncompress, then unpack on our way out. Right? /// /// This function will base64-DECODE the string contents, then uncompress them using /// zlib, and then unpack the result using whatever is the default packer (MsgPack, Protobuf, etc). /// /// I originally added compression because message sizes were too big. Now I'm adding packing, /// to solve any issues of binary compatibility across various platforms. // bool OTASCIIArmor::GetAndUnpackString(OTString & strData, bool bLineBreaks) const //bLineBreaks=true { size_t outSize = 0; uint8_t * pData = NULL; strData.Release(); if (GetLength() < 1) { return true; } // -------------------------------------------------------------- pData = OTCrypto::It()->Base64Decode(this->Get(), &outSize, bLineBreaks); // pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0)); if (pData) { std::string str_decoded( pData, pData+outSize ); delete [] pData; pData=NULL; std::string str_uncompressed = decompress_string( str_decoded ); // --------------------------------------- // PUT THE PACKED BUFFER HERE, AND UNPACK INTO strData // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up. OT_ASSERT(NULL != pBuffer); OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // This will make sure buffer is deleted later. pBuffer->SetData(reinterpret_cast<const uint8_t *>(str_uncompressed.data()), str_uncompressed.size()); // ----------------------------- OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING)); OT_ASSERT(NULL != pOTDBString); OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // clean up this string. bool bUnpacked = pPacker->Unpack(*pBuffer, *pOTDBString); // ---------------------- if (false == bUnpacked) { OTLog::Error("Failed unpacking string in OTASCIIArmor::GetAndUnpackString.\n"); return false; } // -------------------------------------------------------- // This enforces the null termination. (using the 2nd parameter as nEnforcedMaxLength) strData.Set(pOTDBString->m_string.c_str(), static_cast<uint32_t> (pOTDBString->m_string.length())); return true; } else { OTLog::Error("OTASCIIArmor::GetAndUnpackString: NULL pData while base64-decoding pData.\n"); return false; } }
// This function will base64 ENCODE theData, // and then Set() that as the string contents. // Additionally it will pack and compress the data! // bool OTASCIIArmor::SetAndPackData(const OTData & theData, bool bLineBreaks/*=true*/) { char * pString = NULL; Release(); if (theData.GetSize() < 1) return true; // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. // Here I use the default storage context to create the object (the blob.) // I also originally created OTASCIIArmor::GetPacker() using OTDB_DEFAULT_PACKER, // so I know everything is compatible. // OTDB::Blob * pBlob = dynamic_cast<OTDB::Blob *>(OTDB::CreateObject(OTDB::STORED_OBJ_BLOB)); OT_ASSERT(NULL != pBlob); // Beyond this point, responsible to delete pBlob. OTCleanup<OTDB::Blob> theBlobAngel(*pBlob); // make sure memory is cleaned up. // ---------------------------- pBlob->m_memBuffer.assign(static_cast<const unsigned char *>(theData.GetPointer()), static_cast<const unsigned char *>(theData.GetPointer())+theData.GetSize()); OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pBlob); // Now we PACK our data before compressing/encoding it. if (NULL == pBuffer) { OTLog::Error("Failed packing data in OTASCIIArmor::SetAndPackData. \n"); return false; } OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up. // -------------------------------------------------------- const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData()); const size_t theSize = pBuffer->GetSize(); if (NULL != pUint) pString = OTCrypto::It()->Base64Encode(pUint, static_cast<int>(theSize), bLineBreaks); // pString = OT_base64_encode(pUint, static_cast<int> (theSize), (bLineBreaks ? 1 : 0)); else { OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackData.\n"); return false; } // ------------------------------------- if (NULL != pString) { Set(pString); delete [] pString; pString=NULL; return true; } else { OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackData.\n"); return false; } }
// This function will base64 DECODE the string contents // and return them as binary in theData // Additionally it will decompress and unpack the data! // bool OTASCIIArmor::GetAndUnpackData(OTData & theData, bool bLineBreaks) const //linebreaks=true { size_t outSize = 0; uint8_t * pData = NULL; theData.Release(); if (GetLength() < 1) return true; // -------------------------------------------------------------- // pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0)); if (pData) { // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up. OT_ASSERT(NULL != pBuffer); OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure buffer is deleted. pBuffer->SetData(static_cast<const unsigned char*>(pData), outSize); delete [] pData; pData=NULL; // ----------------------------- OTDB::Blob * pBlob = dynamic_cast<OTDB::Blob *>(OTDB::CreateObject(OTDB::STORED_OBJ_BLOB)); OT_ASSERT(NULL != pBlob); OTCleanup<OTDB::Blob> theBlobAngel(*pBlob); // clean up this blob. bool bUnpacked = pPacker->Unpack(*pBuffer, *pBlob); // ---------------------- if (false == bUnpacked) { OTLog::Error("Failed unpacking data in OTASCIIArmor::GetAndUnpackData.\n"); delete [] pData; pData=NULL; return false; } // -------------------------------------------------------- theData.Assign(pBlob->m_memBuffer.data(), pBlob->m_memBuffer.size()); delete [] pData; pData=NULL; return true; } else { OTLog::Error("Error while base64_decoding in OTASCIIArmor::GetAndUnpackData.\n"); return false; } }
bool OTASCIIArmor::GetAndUnpackStringMap(std::map<std::string, std::string> & the_map, bool bLineBreaks/*=true*/) const { size_t outSize = 0; uint8_t * pData = NULL; the_map.clear(); if (GetLength() < 1) return true; // -------------------------------------------------------------- // pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0)); if (pData) { // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up. OT_ASSERT(NULL != pBuffer); OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure buffer is deleted. pBuffer->SetData(static_cast<const unsigned char*>(pData), outSize); delete [] pData; pData=NULL; // ----------------------------- OTDB::StringMap * pStringMap = dynamic_cast<OTDB::StringMap *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING_MAP)); OT_ASSERT(NULL != pStringMap); OTCleanup<OTDB::StringMap> theMapAngel(*pStringMap); // clean up this map. bool bUnpacked = pPacker->Unpack(*pBuffer, *pStringMap); // ---------------------- if (false == bUnpacked) { OTLog::Error("Failed unpacking data in OTASCIIArmor::GetAndUnpackStringMap.\n"); delete [] pData; pData=NULL; return false; } // ----------------------------- the_map = pStringMap->the_map; // ----------------------------- delete [] pData; pData=NULL; return true; } else { OTLog::Error("Error while base64_decoding in OTASCIIArmor::GetAndUnpackStringMap.\n"); return false; } }
/// This function first Packs the incoming string, using whatever is the default packer. (MsgPack or Protobuf). /// Then it Compresses the packed binary data using zlib. (ezcompress.) /// Then it Base64-Encodes the compressed binary and sets it as a string on THIS OBJECT. /// /// I added these pieces 1-by-1 over time. At first the messages were too long, so I started compressing them. /// Then they were not binary compatible across various platforms, so I added the packing. // bool OTASCIIArmor::SetAndPackString(const OTString & strData, bool bLineBreaks) //=true { Release(); if (strData.GetLength() < 1) return true; // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. // Here I use the default storage context to create the object (the blob.) // I also originally created OTASCIIArmor::GetPacker() using OTDB_DEFAULT_PACKER, // so I know everything is compatible. // OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING)); OT_ASSERT(NULL != pOTDBString); // Beyond this point, responsible to delete pString. OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // make sure memory is cleaned up. // ----------------------------- const uint32_t theStringSize32 = strData.GetLength(); const size_t theStringSize = theStringSize32; // might need a cast here. // todo make sure this will handle sizes as big as I need. pOTDBString->m_string.assign(strData.Get(), // const char * theStringSize); OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pOTDBString); // Now we PACK our string before compressing/encoding it. if (NULL == pBuffer) { OTLog::Error("Failed packing string in OTASCIIArmor::SetAndPackString. \n"); return false; } OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up. // -------------------------------------------------------- const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData()); const size_t theSize = pBuffer->GetSize(); // -------------------------------------------------------- char * pString = NULL; // Set up source buffer and destination buffer long nDestLen = DEFAULT_BUFFER_SIZE_EASYZLIB; // todo stop hardcoding numbers (but this one is OK I think.) const long lSourcelen = static_cast<long> (theSize); unsigned char* pSource = new unsigned char[lSourcelen+10]; // for safety unsigned char* pDest = new unsigned char[nDestLen +10]; // for safety OT_ASSERT(NULL != pSource); OT_ASSERT(NULL != pDest); OTPassword::zeroMemory(pSource, lSourcelen+10); OTPassword::zeroMemory(pDest, nDestLen +10); // void * OTPassword::safe_memcpy(void * dest, // uint32_t dest_size, // const // void * src, // uint32_t src_length, // bool bZeroSource/*=false*/) // if true, sets the source buffer to zero after copying is done. OTPassword::safe_memcpy(pSource, lSourcelen, pUint, static_cast<uint32_t>(theSize)); // Now we are compressing first before base64-encoding (for strings, anyway) int nErr = ezcompress( pDest, &nDestLen, pSource, lSourcelen ); // If the destination buffer wasn't the right size the first time around, // then we re-allocate it to the right size (which we now know) and try again... if ( nErr == EZ_BUF_ERROR ) { delete [] pDest; pDest = new unsigned char [nDestLen+10]; // enough room now OT_ASSERT(NULL != pDest); OTPassword::zeroMemory(pDest, nDestLen+10); nErr = ezcompress( pDest, &nDestLen, pSource, lSourcelen ); } // Clean this up... delete [] pSource; pSource = NULL; // Still errors? if ( nErr == EZ_BUF_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("Error allocating memory in OTASCIIArmor::SetAndPackString\n"); } else if ( nErr == EZ_STREAM_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG( "pDest is NULL in OTASCIIArmor::SetAndPackString\n"); } else if ( nErr == EZ_DATA_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("corrupted pSrc passed to ezuncompress OTASCIIArmor::SetAndPackString\n"); } else if ( nErr == EZ_MEM_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("Out of memory in OTASCIIArmor::SetAndPackString\n"); } OT_ASSERT_MSG(pDest != NULL, "pDest NULL in OTASCIIArmor::SetAndPackString\n"); // Success if (0 < nDestLen) { // Now let's base-64 encode it... pString = OTCrypto::It()->Base64Encode((const uint8_t*)pDest, nDestLen, bLineBreaks); // pString = OT_base64_encode((const uint8_t*)pDest, nDestLen, (bLineBreaks ? 1 : 0)); delete [] pDest; pDest = NULL; if (pString) { Set(pString); delete [] pString; pString=NULL; return true; } else { OTLog::Error("pString NULL in OTASCIIArmor::SetAndPackString\n"); } } else { OTLog::Error("nDestLen 0 in OTASCIIArmor::SetAndPackString\n"); } if (pDest) delete [] pDest; pDest = NULL; return false; }
/// if we pack, compress, encode on the way in, that means, therefore, we /// need to decode, uncompress, then unpack on our way out. Right? /// /// This function will base64-DECODE the string contents, then uncompress them using /// zlib, and then unpack the result using whatever is the default packer (MsgPack, Protobuf, etc). /// /// I originally added compression because message sizes were too big. Now I'm adding packing, /// to solve any issues of binary compatibility across various platforms. // bool OTASCIIArmor::GetAndUnpackString(OTString & strData, bool bLineBreaks) const //bLineBreaks=true { size_t outSize = 0; uint8_t * pData = NULL; strData.Release(); if (GetLength() < 1) { return true; } // -------------------------------------------------------------- pData = OTCrypto::It()->Base64Decode(this->Get(), &outSize, bLineBreaks); // pData = OT_base64_decode(Get(), &outSize, (bLineBreaks ? 1 : 0)); if (pData) { // ------------------------------------------- // EASY ZLIB // long nDestLen = DEFAULT_BUFFER_SIZE_EASYZLIB; // todo stop hardcoding numbers (but this one is OK I think.) unsigned char* pDest = new unsigned char [nDestLen+10]; // For safety. OT_ASSERT(NULL != pDest); int nErr = ezuncompress( pDest, &nDestLen, pData, static_cast<long> (outSize) ); if ( nErr == EZ_BUF_ERROR ) { delete [] pDest; pDest = new unsigned char [nDestLen]; // enough room now OT_ASSERT(NULL != pDest); nErr = ezuncompress( pDest, &nDestLen, pData, static_cast<long> (outSize) ); } // Now we're done with this memory, let's free it. delete [] pData; pData=NULL; // ---------------------------------------- if ( nErr == EZ_BUF_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("Buffer error in OTASCIIArmor::GetAndUnpackString\n"); } else if ( nErr == EZ_STREAM_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("pDest is NULL in OTASCIIArmor::GetAndUnpackString\n"); } else if ( nErr == EZ_DATA_ERROR ) { delete [] pDest; pDest = NULL; OTLog::vError("corrupted pSrc passed to ezuncompress OTASCIIArmor::GetAndUnpackString, size: %d\n", outSize); OT_FAIL; } else if ( nErr == EZ_MEM_ERROR ) { delete [] pDest; pDest = NULL; OT_FAIL_MSG("Out of memory in OTASCIIArmor::GetAndUnpackString\n"); } // --------------------------------------- // PUT THE PACKED BUFFER HERE, AND UNPACK INTO strData // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. OTDB::PackedBuffer * pBuffer = pPacker->CreateBuffer(); // Need to clean this up. OT_ASSERT(NULL != pBuffer); OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // This will make sure buffer is deleted later. const size_t theDestLen = nDestLen; pBuffer->SetData(pDest, // const unsigned char * theDestLen); delete [] pDest; pDest=NULL; // ----------------------------- OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING)); OT_ASSERT(NULL != pOTDBString); OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // clean up this string. bool bUnpacked = pPacker->Unpack(*pBuffer, *pOTDBString); // ---------------------- if (false == bUnpacked) { OTLog::Error("Failed unpacking string in OTASCIIArmor::GetAndUnpackString.\n"); return false; } // -------------------------------------------------------- // This enforces the null termination. (using the 2nd parameter as nEnforcedMaxLength) strData.Set(pOTDBString->m_string.c_str(), static_cast<uint32_t> (pOTDBString->m_string.length())); return true; } else { OTLog::Error("OTASCIIArmor::GetAndUnpackString: NULL pData while base64-decoding pData.\n"); return false; } }
bool OTASCIIArmor::SetAndPackStringMap(const std::map<std::string, std::string> & the_map, bool bLineBreaks/*=true*/) { char * pString = NULL; Release(); if (the_map.size() < 1) return true; // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. // Here I use the default storage context to create the object (the string map.) // I also originally created OTASCIIArmor::GetPacker() using OTDB_DEFAULT_PACKER, // so I know everything is compatible. // OTDB::StringMap * pStringMap = dynamic_cast<OTDB::StringMap *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING_MAP)); OT_ASSERT(NULL != pStringMap); // Beyond this point, responsible to delete pStringMap. OTCleanup<OTDB::StringMap> theMapAngel(*pStringMap); // make sure memory is cleaned up. // ----------------------------- pStringMap->the_map = the_map; // ----------------------------- OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pStringMap); // Now we PACK our data before compressing/encoding it. if (NULL == pBuffer) { OTLog::Error("Failed packing data in OTASCIIArmor::SetAndPackStringMap. \n"); return false; } OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up. // -------------------------------------------------------- const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData()); const size_t theSize = pBuffer->GetSize(); if (NULL != pUint) pString = OT_base64_encode(pUint, theSize, (bLineBreaks ? 1 : 0)); else { OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackStringMap.\n"); return false; } // ------------------------------------- if (NULL != pString) { Set(pString); delete [] pString; pString=NULL; return true; } else { OTLog::Error("Error while base64_encoding in OTASCIIArmor::SetAndPackStringMap.\n"); return false; } }
/// This function first Packs the incoming string, using whatever is the default packer. (MsgPack or Protobuf). /// Then it Compresses the packed binary data using zlib. (ezcompress.) /// Then it Base64-Encodes the compressed binary and sets it as a string on THIS OBJECT. /// /// I added these pieces 1-by-1 over time. At first the messages were too int64_t, so I started compressing them. /// Then they were not binary compatible across various platforms, so I added the packing. // bool OTASCIIArmor::SetAndPackString(const OTString & strData, bool bLineBreaks) //=true { Release(); if (strData.GetLength() < 1) return true; // -------------------------------------------------------- OTDB::OTPacker * pPacker = OTASCIIArmor::GetPacker(); // No need to check for failure, since this already ASSERTS. No need to cleanup either. // Here I use the default storage context to create the object (the blob.) // I also originally created OTASCIIArmor::GetPacker() using OTDB_DEFAULT_PACKER, // so I know everything is compatible. // OTDB::OTDBString * pOTDBString = dynamic_cast<OTDB::OTDBString *>(OTDB::CreateObject(OTDB::STORED_OBJ_STRING)); OT_ASSERT(NULL != pOTDBString); // Beyond this point, responsible to delete pString. OTCleanup<OTDB::OTDBString> theStringAngel(*pOTDBString); // make sure memory is cleaned up. // ----------------------------- const uint32_t theStringSize32 = strData.GetLength(); const size_t theStringSize = theStringSize32; // might need a cast here. // todo make sure this will handle sizes as big as I need. pOTDBString->m_string.assign(strData.Get(), // const char * theStringSize); OTDB::PackedBuffer * pBuffer = pPacker->Pack(*pOTDBString); // Now we PACK our string before compressing/encoding it. if (NULL == pBuffer) { OTLog::Error("Failed packing string in OTASCIIArmor::SetAndPackString. \n"); return false; } OTCleanup<OTDB::PackedBuffer> theBufferAngel(*pBuffer); // make sure memory is cleaned up. // -------------------------------------------------------- std::string str_packed(reinterpret_cast<const char *>(pBuffer->GetData()), pBuffer->GetSize()); std::string str_compressed = compress_string( str_packed ); // Success if (str_compressed.size()) { // Now let's base-64 encode it... // TODO: remove static cast, add check for longer than 'int32_t' length? (da2ce7) char * pString = OTCrypto::It()->Base64Encode((const uint8_t*)(str_compressed.data()), static_cast<int32_t>(str_compressed.size()), bLineBreaks); if (pString) { Set(pString); delete [] pString; pString=NULL; return true; } else { OTLog::vError("OTASCIIArmor::%s: pString NULL.\n", __FUNCTION__); } } else { OTLog::vError("OTASCIIArmor::%s: nDestLen 0.\n", __FUNCTION__); } return false; }