void ZStreamWPos_String::Imp_Write(const void* iSource, size_t iCount, size_t* oCountWritten) { size_t neededSpace = ZStream::sClampedSize(fPosition + iCount); if (fString.size() < neededSpace) { try { fString.resize(neededSpace); } catch (...) {} } if (size_t countToWrite = ZStream::sClampedSize(iCount, fString.size(), fPosition)) { sMemCopy(&fString.at(fPosition), iSource, countToWrite); fPosition += countToWrite; if (oCountWritten) *oCountWritten = countToWrite; } else if (oCountWritten) { *oCountWritten = 0; } }
void ZStreamW_Memory::Imp_Write(const void* iSource, size_t iCount, size_t* oCountWritten) { sMemCopy(fAddress, iSource, iCount); fAddress += iCount; if (oCountWritten) *oCountWritten = iCount; }
void ZStreamR_Memory::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { sMemCopy(oDest, fAddress, iCount); fAddress += iCount; if (oCountRead) *oCountRead = iCount; }
void ZStrimU_StreamUTF8Buffered::Imp_ReadUTF32(UTF32* oDest, size_t iCount, size_t* oCount) { // Optimize the common case -- single CU, with data in the buffer. if (iCount == 1 && fFeedOut < fFeedIn) { *oDest = fBuffer[fFeedOut++]; if (oCount) *oCount = 1; return; } UTF32* localDest = oDest; while (iCount) { if (fFeedOut < fFeedIn) { const size_t countWritten = min(iCount, fFeedIn - fFeedOut); sMemCopy(localDest, &fBuffer[fFeedOut], countWritten * sizeof(UTF32)); fFeedOut += countWritten; localDest += countWritten; iCount -= countWritten; } else { size_t countToRead; UTF32* utf32Buffer; if (fFeedOut) { // Remember the last CP in fBuffer[0] fBuffer[0] = fBuffer[fFeedOut - 1]; // Start writing to &fBuffer[1] utf32Buffer = &fBuffer[1]; countToRead = fBufferCount - 1; fFeedIn = 1; fFeedOut = 1; } else { utf32Buffer = &fBuffer[0]; countToRead = fBufferCount; fFeedIn = 0; fFeedOut = 0; } size_t utf8Read; fStreamR.Read(&fBuffer_UTF8[0], countToRead, &utf8Read); if (not utf8Read) break; size_t destCU; spUTF8ToUTF32(&fBuffer_UTF8[0], utf8Read, utf32Buffer, countToRead, destCU); fFeedIn += destCU; } } if (oCount) *oCount = localDest - oDest; }
void ZStreamRPos_Memory::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { size_t countToCopy = ZStream::sClampedSize(iCount, fSize, fPosition); sMemCopy(oDest, fAddress + fPosition, countToCopy); fPosition += countToCopy; if (oCountRead) *oCountRead = countToCopy; }
PixelDescRep_Indexed::PixelDescRep_Indexed(const RGBA* iColors, uint32* iPixvals, size_t iCount, bool iStripAlpha) : fCheckedAlpha(true), fHasAlpha(false) { ZAssertStop(kDebug_PixmapNS, iCount <= 256); ZAssertStopf(1, iStripAlpha, ("This constructor is only used when stripping alpha")); Pixval2RGBA_Indexed::fPixvals = nullptr; RGBA2Pixval_Indexed::fPixvals = nullptr; fReverseLookup = nullptr; vector<RGBA> vectorColors; vector<uint32> vectorPixvals; for (size_t x = 0; x < iCount; ++x) { vector<uint32>::iterator insertIter = lower_bound(vectorPixvals.begin(), vectorPixvals.end(), iPixvals[x]); insertIter = vectorPixvals.insert(insertIter, iPixvals[x]); vectorColors.insert( vectorColors.begin() + (insertIter - vectorPixvals.begin()), iColors[x]); } fCount = iCount; fColors = new RGBA[iCount]; try { Pixval2RGBA_Indexed::fPixvals = new uint32[iCount]; RGBA2Pixval_Indexed::fPixvals = Pixval2RGBA_Indexed::fPixvals; } catch (...) { delete fColors; throw; } sMemCopy(fColors, &vectorColors[0], iCount * sizeof(RGBA)); sMemCopy(Pixval2RGBA_Indexed::fPixvals, &vectorPixvals[0], iCount * sizeof(uint32)); // Set the alpha value to be completely opaque. for (size_t x = 0; x < iCount; ++x) sAlpha(fColors[x]) = 1.0; }
void ZStreamWPos_Memory::Imp_Write(const void* iSource, size_t iCount, size_t* oCountWritten) { size_t countToCopy = ZStream::sClampedSize(iCount, fCapacity, fPosition); sMemCopy(fAddress + fPosition, iSource, countToCopy); fPosition += countToCopy; if (fSize < fPosition) fSize = fPosition; if (oCountWritten) *oCountWritten = countToCopy; }
void ZStreamRPos_PageBuffered::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { char* localDest = reinterpret_cast<char*>(oDest); iCount = ZStream::sClampedSize(iCount, fStreamReal.GetSize(), fPosition); while (iCount) { // Do we have the offset in our buffers? Buffer* buffer_Found = fBuffer_Head; while (buffer_Found) { if (buffer_Found->fStartPosition <= fPosition && buffer_Found->fStartPosition + fBufferSize > fPosition) { break; } buffer_Found = buffer_Found->fNext; } if (buffer_Found == nullptr) { buffer_Found = fBuffer_Tail; buffer_Found->fStartPosition = fPosition - (fPosition % fBufferSize); fStreamReal.SetPosition(buffer_Found->fStartPosition); fStreamReal.Read(buffer_Found->fData, fBufferSize, nullptr); } size_t offsetInBuffer = fPosition % fBufferSize; size_t copySize = min(iCount, fBufferSize - offsetInBuffer); sMemCopy(localDest, buffer_Found->fData + offsetInBuffer, copySize); iCount -= copySize; fPosition += copySize; localDest += copySize; if (fBuffer_Head != buffer_Found) { // Move buffer_Found to the head of the list by removing it if (buffer_Found->fPrev) buffer_Found->fPrev->fNext = buffer_Found->fNext; if (buffer_Found->fNext) buffer_Found->fNext->fPrev = buffer_Found->fPrev; if (fBuffer_Head == buffer_Found) fBuffer_Head = buffer_Found->fNext; if (fBuffer_Tail == buffer_Found) fBuffer_Tail = buffer_Found->fPrev; // and inserting it buffer_Found->fPrev = nullptr; buffer_Found->fNext = fBuffer_Head; fBuffer_Head->fPrev = buffer_Found; fBuffer_Head = buffer_Found; } } if (oCountRead) *oCountRead = localDest - reinterpret_cast<char*>(oDest); }
PixelDescRep_Indexed::PixelDescRep_Indexed(const RGBA* iColors, uint32* iPixvals, size_t iCount) : fCheckedAlpha(false) { ZAssertStop(kDebug_PixmapNS, iCount <= 256); Pixval2RGBA_Indexed::fPixvals = nullptr; RGBA2Pixval_Indexed::fPixvals = nullptr; fReverseLookup = nullptr; vector<RGBA> vectorColors; vector<uint32> vectorPixvals; for (size_t x = 0; x < iCount; ++x) { vector<uint32>::iterator insertIter = lower_bound(vectorPixvals.begin(), vectorPixvals.end(), iPixvals[x]); insertIter = vectorPixvals.insert(insertIter, iPixvals[x]); vectorColors.insert( vectorColors.begin() + (insertIter - vectorPixvals.begin()), iColors[x]); } fCount = iCount; fColors = new RGBA[iCount]; try { Pixval2RGBA_Indexed::fPixvals = new uint32[iCount]; RGBA2Pixval_Indexed::fPixvals = Pixval2RGBA_Indexed::fPixvals; } catch (...) { delete fColors; throw; } sMemCopy(fColors, &vectorColors[0], iCount * sizeof(RGBA)); sMemCopy(Pixval2RGBA_Indexed::fPixvals, &vectorPixvals[0], iCount * sizeof(uint32)); }
PixelDescRep_Indexed::PixelDescRep_Indexed(const RGBA* iColors, size_t iCount) : fCheckedAlpha(false) { ZAssertStop(kDebug_PixmapNS, iCount <= 256); Pixval2RGBA_Indexed::fPixvals = nullptr; RGBA2Pixval_Indexed::fPixvals = nullptr; fReverseLookup = nullptr; fCount = iCount; fColors = new RGBA[iCount]; sMemCopy(fColors, iColors, iCount * sizeof(RGBA)); }
void ZStreamRPos_String::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { if (size_t countToRead = ZStream::sClampedSize(iCount, fString.size(), fPosition)) { sMemCopy(oDest, &fString.at(fPosition), countToRead); fPosition += countToRead; if (oCountRead) *oCountRead = countToRead; } else if (oCountRead) { *oCountRead = 0; } }
PixelDescRep_Indexed::PixelDescRep_Indexed(const RGBA* iColors, size_t iCount, bool iStripAlpha) : fCheckedAlpha(true), fHasAlpha(false) { ZAssertStop(kDebug_PixmapNS, iCount <= 256); ZAssertStopf(1, iStripAlpha, "This constructor is only used when stripping alpha"); Pixval2RGBA_Indexed::fPixvals = nullptr; RGBA2Pixval_Indexed::fPixvals = nullptr; fReverseLookup = nullptr; fCount = iCount; fColors = new RGBA[iCount]; sMemCopy(fColors, iColors, iCount * sizeof(RGBA)); // Set the alpha value to be completely opaque. for (size_t x = 0; x < iCount; ++x) sAlpha(fColors[x]) = 1.0; }
void ZStreamR_Boundary::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { if (not fBuffer) { fStreamSource.Read(oDest, iCount, oCountRead); } else { const size_t boundarySize = fBoundary.size(); uint8* localDest = reinterpret_cast<uint8*>(oDest); while (iCount) { if (fDataEnd > fDataStart) { size_t countToMove = min(fDataEnd - fDataStart, iCount); sMemCopy(localDest, fBuffer + fDataStart, countToMove); fDataStart += countToMove; localDest += countToMove; iCount -= countToMove; } else { if (fHitBoundary) break; // Shuffle existing stuff to beginning of buffer. sMemMove(fBuffer, fBuffer + fDataEnd, boundarySize - fDataEnd); // Top up the tail. size_t countRead; fStreamSource.Read(fBuffer + boundarySize - fDataEnd, fDataEnd, &countRead); if (countRead < fDataEnd) { // The source stream has gone empty without our having already seen the // boundary. Shuffle the data we do have so the last byte aligns with // the end of the buffer. sMemMove(fBuffer + fDataEnd - countRead, fBuffer, boundarySize - (fDataEnd - countRead)); // The first returnable byte is at fDataStart, and the last is at // the end of the buffer. fDataStart = fDataEnd - countRead; fDataEnd = boundarySize; if (countRead == 0) { // We read nothing at all, so fDataStart will equal fDataEnd, // which will be the end of the buffer. And we should bail. break; } } else { // Do Boyer-Moore search on the full buffer. int xx; for (xx = boundarySize - 1; xx >= 0 && fBuffer[xx] == fBoundary[xx]; --xx) {} if (xx < 0) { // We found the boundary. fHitBoundary = true; fDataStart = boundarySize; fDataEnd = boundarySize; } else { // We didn't find the boundary. The shift distance is precisely the number // of bytes at the start of the buffer that *cannot* match the boundary, // which are bytes that can be returned as our output. fDataStart = 0; fDataEnd = fDistance[fBuffer[boundarySize - 1]]; } } } } if (oCountRead) *oCountRead = localDest - reinterpret_cast<uint8*>(oDest); } }
void ZStreamRWPos_PageBuffered::Imp_Write(const void* iSource, size_t iCount, size_t* oCountWritten) { const char* localSource = reinterpret_cast<const char*>(iSource); while (iCount) { // Do we have the offset in our buffers? Buffer* buffer_Found = fBuffer_Head; while (buffer_Found) { if (buffer_Found->fStartPosition <= fPosition && buffer_Found->fStartPosition + fBufferSize > fPosition) { break; } buffer_Found = buffer_Found->fNext; } size_t offsetInBuffer = fPosition % fBufferSize; if (buffer_Found == nullptr) { // We didn't find a buffer encompassing the position if (fBuffer_Tail->fDirty) { fStreamReal.SetPosition(fBuffer_Tail->fStartPosition); fStreamReal.Write(fBuffer_Tail->fData, min(uint64(fBufferSize), fStreamReal.GetSize() - fBuffer_Tail->fStartPosition)); } buffer_Found = fBuffer_Tail; buffer_Found->fStartPosition = fPosition - offsetInBuffer; size_t countToFillBuffer = min(uint64(fBufferSize), fStreamReal.GetSize() - buffer_Found->fStartPosition); if (offsetInBuffer || iCount < countToFillBuffer) { // We need to read the original data because we're either not going to write // starting at the beginning of the buffer, or we're not going to overwrite // the entire valid contents of the buffer (or both). fStreamReal.SetPosition(buffer_Found->fStartPosition); fStreamReal.Read(buffer_Found->fData, countToFillBuffer); } } size_t copySize = min(iCount, fBufferSize - offsetInBuffer); sMemCopy(buffer_Found->fData + offsetInBuffer, localSource, copySize); buffer_Found->fDirty = true; iCount -= copySize; fPosition += copySize; localSource += copySize; if (fBuffer_Head != buffer_Found) { // Move buffer_Found to the head of the list by removing it if (buffer_Found->fPrev) buffer_Found->fPrev->fNext = buffer_Found->fNext; if (buffer_Found->fNext) buffer_Found->fNext->fPrev = buffer_Found->fPrev; if (fBuffer_Head == buffer_Found) fBuffer_Head = buffer_Found->fNext; if (fBuffer_Tail == buffer_Found) fBuffer_Tail = buffer_Found->fPrev; // and inserting it buffer_Found->fPrev = nullptr; buffer_Found->fNext = fBuffer_Head; fBuffer_Head->fPrev = buffer_Found; fBuffer_Head = buffer_Found; } } if (oCountWritten) *oCountWritten = localSource - reinterpret_cast<const char*>(iSource); }
void ZStreamRWCon_SSL_Win::Imp_Write(const void* iSource, size_t iCount, size_t* oCountWritten) { ZAcqMtx acq(fMtx_W); if (oCountWritten) *oCountWritten = 0; SecPkgContext_StreamSizes theSizes; if (FAILED(spPSFT->QueryContextAttributesA( &fCtxtHandle, SECPKG_ATTR_STREAM_SIZES, &theSizes))) { // QueryContextAttributesA really shouldn't ever fail. ZAssert(false); return; } // Local buffer that will hold the message header, cyphertext and message trailer vector<char> buffer(theSizes.cbHeader + min(iCount, size_t(theSizes.cbMaximumMessage)) + theSizes.cbTrailer, '\0'); // Encryption happens in-place, copy the plaintext to the appropriate offset of the buffer. const size_t countToEncrypt = min(iCount, size_t(theSizes.cbMaximumMessage)); sMemCopy(&buffer[theSizes.cbHeader], iSource, countToEncrypt); SecBuffer outSB[4]; outSB[0].cbBuffer = theSizes.cbHeader; outSB[0].pvBuffer = &buffer[0]; outSB[0].BufferType = SECBUFFER_STREAM_HEADER; outSB[1].cbBuffer = countToEncrypt; outSB[1].pvBuffer = &buffer[theSizes.cbHeader]; outSB[1].BufferType = SECBUFFER_DATA; outSB[2].cbBuffer = theSizes.cbTrailer; outSB[2].pvBuffer = &buffer[theSizes.cbHeader + countToEncrypt]; outSB[2].BufferType = SECBUFFER_STREAM_TRAILER; outSB[3].BufferType = SECBUFFER_EMPTY; SecBufferDesc outSBD; outSBD.pBuffers = outSB; outSBD.cBuffers = 4; outSBD.ulVersion = SECBUFFER_VERSION; SECURITY_STATUS result = spPSFT->EncryptMessage(&fCtxtHandle, 0, &outSBD, 0); if (SUCCEEDED(result)) { if (spWriteFully(outSB[0], fStreamW) && spWriteFully(outSB[1], fStreamW) && spWriteFully(outSB[2], fStreamW)) { if (oCountWritten) *oCountWritten = countToEncrypt; return; } } fSendOpen = false; }
void ZStreamRWCon_SSL_Win::Imp_Read(void* oDest, size_t iCount, size_t* oCountRead) { ZAcqMtx acq(fMtx_R); char* localDest = static_cast<char*>(oDest); while (iCount) { if (fBufferPlain.size()) { // We've got some data to return. size_t countToRead = min(iCount, fBufferPlain.size()); deque<char>::iterator begin = fBufferPlain.begin(); deque<char>::iterator end = begin + countToRead; std::copy(begin, end, static_cast<char*>(localDest)); fBufferPlain.erase(begin, end); localDest += countToRead; iCount -= countToRead; } if (localDest != oDest) { // We've somehow managed to read some data, just above or down // below, and so can bail from the loop. break; } if (not fReceiveOpen) break; // We pass four buffers. inSB[0] references the available encrypted // data. inSB[1] through inSB[3] are marked as being empty, and may // be modified by DecryptMessage. SecBuffer inSB[4]; inSB[0].cbBuffer = fBufferEnc.size(); inSB[0].pvBuffer = ZUtil_STL::sFirstOrNil(fBufferEnc); inSB[0].BufferType = SECBUFFER_DATA; inSB[1].BufferType = SECBUFFER_EMPTY; inSB[2].BufferType = SECBUFFER_EMPTY; inSB[3].BufferType = SECBUFFER_EMPTY; SecBufferDesc inSBD; inSBD.cBuffers = 4; inSBD.pBuffers = inSB; inSBD.ulVersion = SECBUFFER_VERSION; SECURITY_STATUS scRet = spPSFT->DecryptMessage(&fCtxtHandle, &inSBD, 0, nullptr); if (scRet == SEC_E_INCOMPLETE_MESSAGE || (FAILED(scRet) && fBufferEnc.empty())) { // fBufferEnc holds an incomplete chunk, DecryptMessage needs // more data before it can do the decrypt. if (not spReadMore(fBufferEnc, fStreamR)) { // We couldn't read any more encrypted data. Mark // our receive as being closed. fReceiveOpen = false; } continue; } if (scRet == SEC_I_CONTEXT_EXPIRED) { // SSL-level disconnect has been sent by the other side. fReceiveOpen = false; continue; } if (scRet == SEC_I_RENEGOTIATE) { // We need to re-handshake. if (not this->pHandshake()) { fReceiveOpen = false; fSendOpen = false; } continue; } if (FAILED(scRet)) { // We failed for some other reason. fReceiveOpen = false; continue; } // If DecryptMessage did any work, inSB[0] through inSB[2] will now reference // the header, decrypted data and trailer. inSB[3] will indicate how many // bytes at the end of fBufferEnc were unused by this decrypt, and so // must be preserved for subsequent use. // This assignment of information to buffers is only something I've determined // by inspection, so for safety we walk through them to find the two we care // about -- the decrypted data and any unused encrypted data. SecBuffer* decrypted = nullptr; SecBuffer* encrypted = nullptr; // Pickup any decrypted data for (size_t x = 0; x < 4; ++x) { if (inSB[x].BufferType == SECBUFFER_DATA && ! decrypted) decrypted = &inSB[x]; if (inSB[x].BufferType == SECBUFFER_EXTRA && ! encrypted) encrypted = &inSB[x]; } // The decryption happens in-place, ie in fBufferEnc. Therefore // we must copy out the decrypted data before munging fBufferEnc to // reference only the unused data. if (decrypted) { // Copy some decrypted data to our destination. const size_t countToCopy = std::min(iCount, size_t(decrypted->cbBuffer)); sMemCopy(localDest, decrypted->pvBuffer, countToCopy); localDest += countToCopy; iCount -= countToCopy; // Anything remaining we put in fBufferPlain, which must be // empty otherwise we wouldn't have got to this point. const char* data = static_cast<const char*>(decrypted->pvBuffer); fBufferPlain.insert(fBufferPlain.begin(), data + countToCopy, data + decrypted->cbBuffer); } if (encrypted) { // There is some unused data, move it to the front of fBufferEnc, // and resize fBufferEnc to reference only that data. sMemMove(&fBufferEnc[0], encrypted->pvBuffer, encrypted->cbBuffer); fBufferEnc.resize(encrypted->cbBuffer); } else { // There was no unused data. fBufferEnc.clear(); } } if (oCountRead) *oCountRead = localDest - static_cast<char*>(oDest); }