void KviHttpRequest::slotSocketDisconnected() { switch(m_eProcessingType) { case WholeFile: // happens always emit binaryData(*m_p->pBuffer); break; case Blocks: // an unprocessed block ?.. should never happened.. but well :D if(m_p->pBuffer->size() > 0) emit binaryData(*m_p->pBuffer); break; case Lines: if(m_p->pBuffer->size() > 0) { // something left in the buffer and has no trailing LF KviCString tmp((const char *)(m_p->pBuffer->data()),m_p->pBuffer->size()); emit data(tmp); } break; case StoreToFile: // same as above... should never happen.. but well :D if(m_p->pFile && m_p->pBuffer->size() > 0) m_p->pFile->write((const char *)(m_p->pBuffer->data()),m_p->pBuffer->size()); break; default: // nothing... just make gcc happy break; } resetInternalStatus(); m_szLastError = __tr2qs("Success"); emit terminated(true); }
void DomainConfigTdpControl_001::createConfigTdpControlSet(UIntN domainIndex) { // Build TDPL table UInt32 dataLength = 0; DptfMemory binaryData(Constants::DefaultBufferSize); m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_PROC_CTDP_POINT_LIST, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); std::vector<ConfigTdpControl> controls = BinaryParse::processorTdplObject(dataLength, binaryData); binaryData.deallocate(); checkHWConfigTdpSupport(controls, domainIndex); // If any lock bit is set, we only provide 1 cTDP level to the policies. if (m_configTdpLock) { while (controls.size() > 1) { controls.pop_back(); } } m_configTdpControlSet = new ConfigTdpControlSet(controls); }
nsresult CryptoBuffer::ToJwkBase64(nsString& aBase64) { // Shortcut for the empty octet string if (Length() == 0) { aBase64.Truncate(); return NS_OK; } // Perform the actual base64 encode nsCString base64; nsDependentCSubstring binaryData((const char*) Elements(), (const char*) (Elements() + Length())); nsresult rv = Base64Encode(binaryData, base64); NS_ENSURE_SUCCESS(rv, rv); // Strip padding base64.Trim("="); // Translate to the URL-safe charset base64.ReplaceChar('+', '-'); base64.ReplaceChar('/', '_'); if (base64.FindCharInSet("+/", 0) != kNotFound) { return NS_ERROR_FAILURE; } CopyASCIItoUTF16(base64, aBase64); return NS_OK; }
void PNGFile::encode(const std::string &filename, const std::string &key) { boost::nowide::ifstream File(filename.c_str(), std::ios::in | std::ios::binary); if (!File) { throw std::invalid_argument("Cannot open " + filename); } std::string extension = getExtension(filename); uint32_t dataSize = static_cast<uint32_t>(fileSize(filename)); std::vector<uint8_t> binaryData(dataSize); File.read(reinterpret_cast<char *>(binaryData.data()), dataSize); this->encode(binaryData, extension, key); }
nsresult nsStructuredCloneContainer::GetDataAsBase64(nsAString &aOut) { NS_ENSURE_STATE(mData); aOut.Truncate(); nsCAutoString binaryData(reinterpret_cast<char*>(mData), mSize); nsCAutoString base64Data; nsresult rv = nsXPConnect::Base64Encode(binaryData, base64Data); NS_ENSURE_SUCCESS(rv, rv); aOut.Assign(NS_ConvertASCIItoUTF16(base64Data)); return NS_OK; }
void DomainCoreControl_001::createCoreControlLpoPreferenceIfNeeded(UIntN domainIndex) { if (m_coreControlLpoPreference == nullptr) { Bool useDefault = false; UInt32 dataLength = 0; DptfMemory binaryData(Constants::DefaultBufferSize); try { m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_PROC_CURRENT_LOGICAL_PROCESSOR_OFFLINING, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); } catch (...) { m_participantServicesInterface->writeMessageWarning( ParticipantMessage(FLF, "CLPO not found. Using defaults.")); useDefault = true; } if (useDefault == false) { try { m_coreControlLpoPreference = BinaryParse::processorClpoObject(dataLength, binaryData); } catch (...) { m_participantServicesInterface->writeMessageWarning( ParticipantMessage(FLF, "Could not parse CLPO data. Using defaults.")); DELETE_MEMORY_TC(m_coreControlLpoPreference); useDefault = true; } } if (useDefault == true) { m_coreControlLpoPreference = new CoreControlLpoPreference(true, 0, Percentage(.50), CoreControlOffliningMode::Smt, CoreControlOffliningMode::Core); } binaryData.deallocate(); } }
void DomainPowerControl_001::initializePowerControlDynamicCapsSetIfNull(UIntN domainIndex) { if (m_powerControlDynamicCaps == nullptr) { UInt32 dataLength = 0; DptfMemory binaryData(Constants::DefaultBufferSize); m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_RAPL_POWER_CONTROL_CAPABILITIES, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); PowerControlDynamicCapsSet dynamicCapsSetFromControl(BinaryParse::processorPpccObject(dataLength, binaryData)); m_powerControlDynamicCaps = new PowerControlDynamicCapsSet(getAdjustedDynamicCapsBasedOnConfigTdpMaxLimit( dynamicCapsSetFromControl)); binaryData.deallocate(); validatePowerControlDynamicCapsSet(); } }
void DomainPerformanceControl_003::createPerformanceControlSet(UIntN domainIndex) { UInt32 dataLength = 0; DptfMemory binaryData(Constants::DefaultBufferSize); //Build GFX performance table m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_PERF_SUPPORT_STATES, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); m_performanceControlSet = new PerformanceControlSet(BinaryParse::processorGfxPstates(dataLength, binaryData)); if (m_performanceControlSet->getCount() == 0) { throw dptf_exception("GFX P-state set is empty. \ Impossible if we support performance controls."); }
void DomainDisplayControl_001::createDisplayControlSet(UIntN domainIndex) { // _BCL Table UInt32 dataLength = 0; DptfMemory binaryData(Constants::DefaultBufferSize); try { m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_DISPLAY_BRIGHTNESS_LEVELS, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); } catch (buffer_too_small e) { binaryData.deallocate(); binaryData.allocate(e.getNeededBufferSize(), true); m_participantServicesInterface->primitiveExecuteGet( esif_primitive_type::GET_DISPLAY_BRIGHTNESS_LEVELS, ESIF_DATA_BINARY, binaryData, binaryData.getSize(), &dataLength, domainIndex); } std::vector<DisplayControl> controls = BinaryParse::displayBclObject(dataLength, binaryData); if (controls.size() == 0) { binaryData.deallocate(); throw dptf_exception("P-state set is empty. \ Impossible if we support performance controls."); }
void KviHttpRequest::processData(KviDataBuffer * data) { // unsigned char obuffer[BUFFER_SIZE]; if(m_bChunkedTransferEncoding && m_bIgnoreRemainingData) { // In chunked transfer encoding mode there may be additional headers // after the last chunk of data. We simply ignore them. return; } if(!m_bHeaderProcessed) { // time to process the header m_p->pBuffer->append(*data); int idx = m_p->pBuffer->find((const unsigned char *)"\r\n\r\n",4); if(idx == -1) { // header not complete if(m_p->pBuffer->size() > 4096) { resetInternalStatus(); m_szLastError = __tr2qs("Header too long: exceeded 4096 bytes"); emit terminated(false); } return; } KviCString szHeader((const char *)(m_p->pBuffer->data()),idx); m_p->pBuffer->remove(idx + 4); if(!processHeader(szHeader)) return; m_bHeaderProcessed = true; if(m_eProcessingType == StoreToFile) { if(!openFile())return; } m_uReceivedSize = m_p->pBuffer->size(); // here the header is complete and the eventual remaining data is in m_p->pBuffer. data has been already used. } else { // header already processed m_uReceivedSize += data->size(); // here the header is complete and some data *might* be already in m_p->pBuffer. data is unused yet. // Optimisation: If the transfer is NOT chunked (so we don't have to parse it) // and the requested processing type is either Blocks or StoreToFile // then we just can avoid to copy the data to m_p->pBuffer. // This is a good optimisation since for large files we can save allocating // space for and moving megabytes of data... if((!m_bChunkedTransferEncoding) && ((m_eProcessingType == Blocks) || (m_eProcessingType == StoreToFile))) { switch(m_eProcessingType) { case Blocks: emit binaryData(*data); break; case StoreToFile: m_p->pFile->write((const char *)(data->data()),data->size()); break; default: break; } if(((m_uTotalSize > 0) && (m_uReceivedSize > m_uTotalSize)) || ((m_uMaxContentLength > 0) && (m_uReceivedSize > m_uMaxContentLength))) { resetInternalStatus(); m_szLastError=__tr2qs("The amount of received data exceeds expected length"); emit terminated(false); } return; } // need to append to m_p->pBuffer and process it m_p->pBuffer->append(*data); } // we're processing data in m_p->pBuffer here if(m_bChunkedTransferEncoding) { // The transfer encoding is chunked: the buffer contains // chunks of data with an initial header composed // of a hexadecimal length, an optional bullshit and a single CRLF // The transfer terminates when we read a last chunk of size 0 // that may be followed by optional headers... // This sux :) while(m_p->pBuffer->size() > 0) // <-- note that we may exit from this loop also for other conditions (there is a goto below) { // we process chunks of parts of chunks at a time. if(m_uRemainingChunkSize > 0) { // process the current chunk data unsigned int uProcessSize = m_uRemainingChunkSize; if(uProcessSize > (unsigned int)m_p->pBuffer->size())uProcessSize = m_p->pBuffer->size(); m_uRemainingChunkSize -= uProcessSize; switch(m_eProcessingType) { case Blocks: if((unsigned int)m_p->pBuffer->size() == uProcessSize) { // avoid copying to a new buffer emit binaryData(*m_p->pBuffer); } else { // must copy KviDataBuffer tmp(uProcessSize,m_p->pBuffer->data()); emit binaryData(tmp); m_p->pBuffer->remove(uProcessSize); } break; case Lines: if((unsigned int)m_p->pBuffer->size() == uProcessSize) { // avoid copying to a new buffer emitLines(m_p->pBuffer); } else { // must copy KviDataBuffer tmp(uProcessSize,m_p->pBuffer->data()); emitLines(&tmp); m_p->pBuffer->remove(uProcessSize); } break; case StoreToFile: m_p->pFile->write((const char *)(m_p->pBuffer->data()),uProcessSize); m_p->pBuffer->remove(uProcessSize); break; default: // nothing.. just make gcc happy break; } // now either the buffer is empty or there is another chunk header: continue looping } else { // We're looking for the beginning of a chunk now. // Note that we might be at the end of a previous chunk that has a CRLF terminator // we need to skip it. int crlf = m_p->pBuffer->find((const unsigned char *)"\r\n",2); if(crlf != -1) { if(crlf == 0) { // This is a plain CRLF at the beginning of the buffer BEFORE a chunk header. // It comes from the previous chunk terminator. Skip it. m_p->pBuffer->remove(2); } else { // got a chunk header KviCString szHeader((const char *)(m_p->pBuffer->data()),crlf); szHeader.cutFromFirst(' '); // now szHeader should contain a hexadecimal chunk length... (why the hell it is hex and not decimal ????) QString szHexHeader = szHeader.ptr(); bool bOk; m_uRemainingChunkSize = szHexHeader.toLong(&bOk,16); if(!bOk) { resetInternalStatus(); m_szLastError = __tr2qs("Protocol error: invalid chunk size"); emit terminated(false); return; } m_p->pBuffer->remove(crlf+2); if(m_uRemainingChunkSize == 0) { // this is the last chunk of data. It may be followed by optional headers // but we actually don't need them (since we're surely not in HEAD mode) m_bIgnoreRemainingData = true; m_p->pBuffer->clear(); goto check_stream_length; } } // the rest is valid data of a non-zero chunk: continue looping } else { // chunk header not complete if(m_p->pBuffer->size() > 4096) { resetInternalStatus(); m_szLastError = __tr2qs("Chunk header too long: exceeded 4096 bytes"); emit terminated(false); return; } goto check_stream_length; } } } } else { // the transfer encoding is not chunked: m_p->pBuffer contains only valid data switch(m_eProcessingType) { case Blocks: if(m_p->pBuffer->size() > 0)emit binaryData(*m_p->pBuffer); m_p->pBuffer->clear(); break; case Lines: if(m_p->pBuffer->size() > 0)emitLines(m_p->pBuffer); break; case StoreToFile: m_p->pFile->write((const char *)(m_p->pBuffer->data()),m_p->pBuffer->size()); m_p->pBuffer->clear(); break; default: // nothing.. just make gcc happy break; } } check_stream_length: if(((m_uTotalSize > 0) && (m_uReceivedSize > m_uTotalSize)) || ((m_uMaxContentLength > 0) && (m_uReceivedSize > m_uMaxContentLength))) { resetInternalStatus(); m_szLastError=__tr2qs("The amount of received data exceeds expected length"); emit terminated(false); } return; }
bool SFB::Audio::AddAPETagToDictionary(CFMutableDictionaryRef dictionary, std::vector<std::shared_ptr<AttachedPicture>>& attachedPictures, const TagLib::APE::Tag *tag) { if(nullptr == dictionary || nullptr == tag) return false; if(tag->isEmpty()) return true; SFB::CFMutableDictionary additionalMetadata(0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for(auto iterator : tag->itemListMap()) { auto item = iterator.second; if(item.isEmpty()) continue; if(TagLib::APE::Item::Text == item.type()) { SFB::CFString key(item.key().toCString(true), kCFStringEncodingUTF8); SFB::CFString value(item.toString().toCString(true), kCFStringEncodingUTF8); if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUM"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kAlbumTitleKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ARTIST"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kArtistKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMARTIST"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kAlbumArtistKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPOSER"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kComposerKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("GENRE"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kGenreKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DATE"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kReleaseDateKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DESCRIPTION"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kCommentKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TITLE"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kTitleKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKNUMBER"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kTrackNumberKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TRACKTOTAL"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kTrackTotalKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPILATION"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kCompilationKey, CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCNUMBER"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kDiscNumberKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("DISCTOTAL"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kDiscTotalKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("LYRICS"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kLyricsKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("BPM"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kBPMKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("RATING"), kCFCompareCaseInsensitive)) AddIntToDictionary(dictionary, Metadata::kRatingKey, CFStringGetIntValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ISRC"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kISRCKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MCN"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kMCNKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MUSICBRAINZ_ALBUMID"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kMusicBrainzReleaseIDKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("MUSICBRAINZ_TRACKID"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kMusicBrainzRecordingIDKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("TITLESORT"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kTitleSortOrderKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMTITLESORT"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kAlbumTitleSortOrderKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ARTISTSORT"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kArtistSortOrderKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("ALBUMARTISTSORT"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kAlbumArtistSortOrderKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("COMPOSERSORT"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kComposerSortOrderKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("GROUPING"), kCFCompareCaseInsensitive)) CFDictionarySetValue(dictionary, Metadata::kGroupingKey, value); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_REFERENCE_LOUDNESS"), kCFCompareCaseInsensitive)) AddDoubleToDictionary(dictionary, Metadata::kReferenceLoudnessKey, CFStringGetDoubleValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_GAIN"), kCFCompareCaseInsensitive)) AddDoubleToDictionary(dictionary, Metadata::kTrackGainKey, CFStringGetDoubleValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_TRACK_PEAK"), kCFCompareCaseInsensitive)) AddDoubleToDictionary(dictionary, Metadata::kTrackPeakKey, CFStringGetDoubleValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_GAIN"), kCFCompareCaseInsensitive)) AddDoubleToDictionary(dictionary, Metadata::kAlbumGainKey, CFStringGetDoubleValue(value)); else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("REPLAYGAIN_ALBUM_PEAK"), kCFCompareCaseInsensitive)) AddDoubleToDictionary(dictionary, Metadata::kAlbumPeakKey, CFStringGetDoubleValue(value)); #if 0 else if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("METADATA_BLOCK_PICTURE"), kCFCompareCaseInsensitive)) { // Handle embedded pictures for(auto blockIterator : item.values()) { auto encodedBlock = blockIterator.data(TagLib::String::UTF8); // Decode the Base-64 encoded data auto decodedBlock = TagLib::DecodeBase64(encodedBlock); // Create the picture TagLib::FLAC::Picture picture; picture.parse(decodedBlock); SFB::CFData data((const UInt8 *)picture.data().data(), picture.data().size()); SFB::CFString description = nullptr; if(!picture.description().isNull()) description(picture.description().toCString(true), kCFStringEncodingUTF8); attachedPictures.push_back(std::make_shared<AttachedPicture>(data, (AttachedPicture::Type)picture.type(), description)); } } #endif // Put all unknown tags into the additional metadata else CFDictionarySetValue(additionalMetadata, key, value); } else if(TagLib::APE::Item::Binary == item.type()) { SFB::CFString key(item.key().toCString(true), kCFStringEncodingUTF8); // From http://www.hydrogenaudio.org/forums/index.php?showtopic=40603&view=findpost&p=504669 /* <length> 32 bit <flags with binary bit set> 32 bit <field name> "Cover Art (Front)"|"Cover Art (Back)" 0x00 <description> UTF-8 string (needs to be a file name to be recognized by AudioShell - meh) 0x00 <cover data> binary */ if(kCFCompareEqualTo == CFStringCompare(key, CFSTR("Cover Art (Front)"), kCFCompareCaseInsensitive) || kCFCompareEqualTo == CFStringCompare(key, CFSTR("Cover Art (Back)"), kCFCompareCaseInsensitive)) { auto binaryData = item.binaryData(); size_t pos = binaryData.find('\0'); if(TagLib::ByteVector::npos() != pos && 3 < binaryData.size()) { SFB::CFData data((const UInt8 *)binaryData.mid(pos + 1).data(), (CFIndex)(binaryData.size() - pos - 1)); SFB::CFString description(TagLib::String(binaryData.mid(0, pos), TagLib::String::UTF8).toCString(true), kCFStringEncodingUTF8); attachedPictures.push_back(std::make_shared<AttachedPicture>(data, kCFCompareEqualTo == CFStringCompare(key, CFSTR("Cover Art (Front)"), kCFCompareCaseInsensitive) ? AttachedPicture::Type::FrontCover : AttachedPicture::Type::BackCover, description)); } } } } if(CFDictionaryGetCount(additionalMetadata)) CFDictionarySetValue(dictionary, Metadata::kAdditionalMetadataKey, additionalMetadata); return true; }
void PNGFile::decode(std::vector<uint8_t> &data, std::string &extension, const std::string &key) const { if (pixels.empty()) { throw std::runtime_error("Trying to extract data from an empty PNG"); } if (key.empty()) { throw std::runtime_error("An empty key was given"); } uint32_t dataSize = 0; uint8_t extensionSize = 0; std::array<uint8_t, 4> t = PNGStego::Encryption::hashKey<4, 150000>(key, iv); uint32_t offsetSeed = 0; for (int i = 0; i < 4; ++i) { offsetSeed <<= 8; offsetSeed += t[i]; } PNGStego::zeroMemory(t.data(), t.size()); boost::random::mt19937 gen(offsetSeed); boost::random::uniform_int_distribution<uint16_t> offset(PNG_MIN_OFFSET, PNG_MAX_OFFSET); PNGStego::zeroMemory(&offsetSeed, sizeof(offsetSeed)); int PixelPos = 0; for (int i = 0; i < 8 * EXTENSION_BYTES; ++i) { extensionSize |= ((pixels[PixelPos].blue & 1) << i); PixelPos += offset(gen); } for (int i = 0; i < 8 * SIZE_BYTES; ++i) { dataSize |= ((pixels[PixelPos].blue & 1) << i); PixelPos += offset(gen); } if (dataSize <= capacity(offsetSeed)) { std::vector<uint8_t> binaryData(dataSize); if (outputFn) outputFn("Extracting data..."); for (size_t i = 0; i < dataSize * 8; ++i) { if (pixels[PixelPos].blue & 1) binaryData[i / 8] |= (1 << (i % 8)); else binaryData[i / 8] &= ~(1 << (i % 8)); PixelPos += offset(gen); } if (outputFn) outputFn("Decrypting data..."); binaryData = Encryption::decrypt(binaryData, key, iv, salt); if (outputFn) outputFn("Decompressing data..."); binaryData = PNGStego::bzip2::decompress(binaryData); if (extensionSize) { extension = std::string(binaryData.begin(), binaryData.begin() + extensionSize); } else { extension = std::string(""); } data = std::vector<uint8_t>(binaryData.begin() + extensionSize, binaryData.end()); PNGStego::zeroMemory(binaryData.data(), binaryData.capacity()); } else { // Basically, if dataSize happens to be larger than the result of capacity() // then something's not right, so we throw an exception. throw std::runtime_error("Corrupted header"); } }
void PNGFile::encode(const std::vector<uint8_t> &data, const std::string &extension, const std::string &key) { if (pixels.empty()) { throw std::runtime_error("Trying to encode data into an empty PNG"); } if (key.empty()) { throw std::invalid_argument("An empty key was given"); } if (!CSPRNG) { throw std::runtime_error("CSPRNG is not set."); } uint8_t extensionSize = static_cast<uint8_t>(extension.length()); std::vector<uint8_t> binaryData(stringToVector(extension)); binaryData.resize(extensionSize + data.size()); std::copy(data.begin(), data.end(), binaryData.begin() + extensionSize); iv.resize(IV_BYTES); this->CSPRNG(iv.data(), iv.size()); std::array<uint8_t, 4> t = PNGStego::Encryption::hashKey<4, 150000>(key, iv); uint32_t offsetSeed = 0; for (int i = 0; i < 4; ++i) { offsetSeed <<= 8; offsetSeed += t[i]; } PNGStego::zeroMemory(t.data(), t.size()); if (outputFn) outputFn("Compressing data..."); binaryData = PNGStego::bzip2::compress(binaryData); uint32_t dataSize = static_cast<uint32_t>(binaryData.size()); dataSize += (TAG_SIZE * 2); if (dataSize <= capacity(offsetSeed)) { boost::random::mt19937 gen(offsetSeed); boost::random::uniform_int_distribution<uint16_t> offset(PNG_MIN_OFFSET, PNG_MAX_OFFSET); PNGStego::zeroMemory(&offsetSeed, sizeof(offsetSeed)); if (outputFn) outputFn("Encrypting data..."); salt.resize(SALT_BYTES); this->CSPRNG(salt.data(), salt.size()); this->WriteSalt(); this->WriteIV(); binaryData = Encryption::encrypt(binaryData, key, iv, salt); dataSize = static_cast<uint32_t>(binaryData.size()); if (outputFn) outputFn("Embedding data..."); int PixelPos = 0; for (int i = 0; i < 8 * EXTENSION_BYTES; ++i) { if (extensionSize & (1 << i)) { pixels[PixelPos].blue |= 1; } else { pixels[PixelPos].blue &= ~1; } PixelPos += offset(gen); } for (int i = 0; i < 8 * SIZE_BYTES; ++i) { if (dataSize & (1 << i)) { pixels[PixelPos].blue |= 1; } else { pixels[PixelPos].blue &= ~1; } PixelPos += offset(gen); } for (size_t i = 0; i < dataSize * 8; ++i) { if (binaryData[i / 8] & (1 << (i % 8))) pixels[PixelPos].blue |= 1; else pixels[PixelPos].blue &= ~1; PixelPos += offset(gen); } } else { throw std::runtime_error("The image can't contain data that large"); } }