Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
	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;
}
Пример #6
0
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();
    }
}
Пример #7
0
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();
    }
}
Пример #8
0
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.");
    }
Пример #9
0
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.");
    }
Пример #10
0
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;
}
Пример #12
0
	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");
		}
	}
Пример #13
0
	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");
		}
	}