예제 #1
0
void X509Certificate_OpenSSL::write
	(utility::outputStream& os, const Format format) const
{
	BIO* membio = 0;
	int dataSize = 0;
	unsigned char* out = 0;

	if (format == FORMAT_DER)
	{	
		if ((dataSize = i2d_X509(m_data->cert, &out)) < 0)
			goto err;

		os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
		os.flush();
		OPENSSL_free(out);
	}
	else if (format == FORMAT_PEM)
	{
		membio = BIO_new(BIO_s_mem());
		BIO_set_close(membio, BIO_CLOSE);

		if (!PEM_write_bio_X509(membio, m_data->cert))
			goto pem_err;

		dataSize = BIO_get_mem_data(membio, &out);
		os.write(reinterpret_cast <utility::stream::value_type*>(out), dataSize);
		os.flush();
		BIO_vfree(membio);
	}
	else
	{
		throw vmime::exceptions::unsupported_certificate_type("Unknown cert type");
	}

	return; // #### Early Return ####

pem_err:
	{
		if (membio)
			BIO_vfree(membio);
	}

err:
	{
		char errstr[256];
		long ec = ERR_get_error();
		ERR_error_string(ec, errstr);
		throw vmime::exceptions::certificate_exception(
			"OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr));
	}
}
void charsetConverter_Win::convert(utility::inputStream& in, utility::outputStream& out)
{
    char s8_Buffer[32000];

    string s_In, s_Out;
    while (!in.eof())
    {
        size_t len = in.read(s8_Buffer, sizeof(s8_Buffer));
        s_In.append(s8_Buffer, len);
    }

    convert(s_In, s_Out);

    out.write(s_Out.data(), s_Out.length());
}
예제 #3
0
void maildirMessage::extractImpl(utility::outputStream& os, utility::progressListener* progress,
	const size_t start, const size_t length, const size_t partialStart, const size_t partialLength,
	const bool /* peek */) const
{
	shared_ptr <const maildirFolder> folder = m_folder.lock();

	shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();

	const utility::file::path path = folder->getMessageFSPath(m_num);
	shared_ptr <utility::file> file = fsf->create(path);

	shared_ptr <utility::fileReader> reader = file->getFileReader();
	shared_ptr <utility::inputStream> is = reader->getInputStream();

	is->skip(start + partialStart);

	byte_t buffer[8192];
	size_t remaining = (partialLength == static_cast <size_t>(-1)
		? length : std::min(partialLength, length));

	const size_t total = remaining;
	size_t current = 0;

	if (progress)
		progress->start(total);

	while (!is->eof() && remaining > 0)
	{
		const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer)));

		remaining -= read;
		current += read;

		os.write(buffer, read);

		if (progress)
			progress->progress(current, total);
	}

	if (progress)
		progress->stop(total);

	// TODO: mark as read unless 'peek' is set
}
예제 #4
0
void X509Certificate::write
	(utility::outputStream& os, const Format format) const
{
	size_t dataSize = 0;
	gnutls_x509_crt_fmt fmt = GNUTLS_X509_FMT_DER;

	switch (format)
	{
	case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break;
	case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break;
	}

	gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize);

	std::vector <byte_t> data(dataSize);

	gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize);

	os.write(reinterpret_cast <utility::stream::value_type*>(&data[0]), dataSize);
}
예제 #5
0
size_t POP3Response::readResponseImpl
	(string& firstLine, utility::outputStream& os,
	 utility::progressListener* progress, const size_t predictedSize)
{
	size_t current = 0, total = predictedSize;

	string temp;
	bool codeDone = false;

	if (progress)
		progress->start(total);

	if (m_timeoutHandler)
		m_timeoutHandler->resetTimeOut();

	utility::inputStreamSocketAdapter sis(*m_socket);
	utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n");
	utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n");
	utility::dotFilteredInputStream dfis(sfis2);   // "\n.." --> "\n."

	utility::inputStream& is = dfis;

	while (!is.eof())
	{
		// Check whether the time-out delay is elapsed
		if (m_timeoutHandler && m_timeoutHandler->isTimeOut())
		{
			if (!m_timeoutHandler->handleTimeOut())
				throw exceptions::operation_timed_out();
		}

		// Receive data from the socket
		byte_t buffer[65536];
		const size_t read = is.read(buffer, sizeof(buffer));

		if (read == 0)   // buffer is empty
		{
			if (m_socket->getStatus() & socket::STATUS_WANT_WRITE)
			{
				m_socket->waitForWrite();
			}
			else if (m_socket->getStatus() & socket::STATUS_WANT_READ)
			{
				m_socket->waitForRead();
			}
			else
			{
				// Input stream needs more bytes to continue, but there
				// is enough data into socket buffer. Do not waitForRead(),
				// just retry read()ing on the stream.
			}

			continue;
		}

		// We have received data: reset the time-out counter
		if (m_timeoutHandler)
			m_timeoutHandler->resetTimeOut();

		// Notify progress
		current += read;

		if (progress)
		{
			total = std::max(total, current);
			progress->progress(current, total);
		}

		// If we don't have extracted the response code yet
		if (!codeDone)
		{
			vmime::utility::stringUtils::appendBytesToString(temp, buffer, read);

			string responseData;

			if (stripFirstLine(temp, responseData, &firstLine) == true)
			{
				PDBG0( "firstLine: %s", firstLine.c_str() );
				if (getResponseCode(firstLine) != CODE_OK)
					throw exceptions::command_error("?", firstLine);

				codeDone = true;

				os.write(responseData.data(), responseData.length());
				temp.clear();

				continue;
			}
		}
		else
		{
			// Inject the data into the output stream
			os.write(buffer, read);
		}
	}

	if (progress)
		progress->stop(total);

	return current;
}
예제 #6
0
void charsetConverter::convert(utility::inputStream& in, utility::outputStream& out)
{
	if (m_desc == NULL)
		throw exceptions::charset_conv_error("Cannot initialize converter.");

	const iconv_t cd = *static_cast <iconv_t*>(m_desc);

	char inBuffer[32768];
	char outBuffer[32768];
	size_t inPos = 0;

	bool prevIsInvalid = false;

	while (true)
	{
		// Fullfill the buffer
		size_t inLength = static_cast <size_t>(in.read(inBuffer + inPos, sizeof(inBuffer) - inPos) + inPos);
		size_t outLength = sizeof(outBuffer);

		const char* inPtr = inBuffer;
		char* outPtr = outBuffer;

		// Convert input bytes
		if (iconv(cd, ICONV_HACK(&inPtr), &inLength,
			      &outPtr, &outLength) == static_cast <size_t>(-1))
		{
			// Illegal input sequence or input sequence has no equivalent
			// sequence in the destination charset.
			if (prevIsInvalid)
			{
				// Write successfully converted bytes
				out.write(outBuffer, sizeof(outBuffer) - outLength);

				// Output a special character to indicate we don't known how to
				// convert the sequence at this position
				out.write("?", 1);

				// Skip a byte and leave unconverted bytes in the input buffer
				std::copy(const_cast <char*>(inPtr + 1), inBuffer + sizeof(inBuffer), inBuffer);
				inPos = inLength - 1;
			}
			else
			{
				// Write successfully converted bytes
				out.write(outBuffer, sizeof(outBuffer) - outLength);

				// Leave unconverted bytes in the input buffer
				std::copy(const_cast <char*>(inPtr), inBuffer + sizeof(inBuffer), inBuffer);
				inPos = inLength;

				if (errno != E2BIG)
					prevIsInvalid = true;
			}
		}
		else
		{
			// Write successfully converted bytes
			out.write(outBuffer, sizeof(outBuffer) - outLength);

			inPos = 0;
			prevIsInvalid = false;
		}

		// Check for end of data
		if (in.eof() && inPos == 0)
			break;
	}
}
예제 #7
0
void charsetConverter_icu::convert
	(utility::inputStream& in, utility::outputStream& out, status* st)
{
	UErrorCode err = U_ZERO_ERROR;

	ucnv_reset(m_from);
	ucnv_reset(m_to);

	if (st)
		new (st) status();

	// From buffers
	byte_t cpInBuffer[16]; // stream data put here
	const size_t outSize = ucnv_getMinCharSize(m_from) * sizeof(cpInBuffer) * sizeof(UChar);
	std::vector <UChar> uOutBuffer(outSize); // Unicode chars end up here

	// To buffers
	// converted (char) data end up here
	const size_t cpOutBufferSz = ucnv_getMaxCharSize(m_to) * outSize;
	std::vector <char> cpOutBuffer(cpOutBufferSz);

	// Tell ICU what to do when encountering an illegal byte sequence
	if (m_options.silentlyReplaceInvalidSequences)
	{
		// Set replacement chars for when converting from Unicode to codepage
		icu::UnicodeString substString(m_options.invalidSequence.c_str());
		ucnv_setSubstString(m_to, substString.getTerminatedBuffer(), -1, &err);

		if (U_FAILURE(err))
			throw exceptions::charset_conv_error("[ICU] Error when setting substitution string.");
	}
	else
	{
		// Tell ICU top stop (and return an error) on illegal byte sequences
		ucnv_setToUCallBack
			(m_from, UCNV_TO_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);

		if (U_FAILURE(err))
			throw exceptions::charset_conv_error("[ICU] Error when setting ToU callback.");

		ucnv_setFromUCallBack
			(m_to, UCNV_FROM_U_CALLBACK_STOP, UCNV_SUB_STOP_ON_ILLEGAL, NULL, NULL, &err);

		if (U_FAILURE(err))
			throw exceptions::charset_conv_error("[ICU] Error when setting FromU callback.");
	}

	// Input data available
	while (!in.eof())
	{
		// Read input data into buffer
		size_t inLength = in.read(cpInBuffer, sizeof(cpInBuffer));

		// Beginning of read data
		const char* source = reinterpret_cast <const char*>(&cpInBuffer[0]);
		const char* sourceLimit = source + inLength; // end + 1

		UBool flush = in.eof();  // is this last run?

		UErrorCode toErr;

		// Loop until all source has been processed
		do
		{
			// Set up target pointers
			UChar* target = &uOutBuffer[0];
			UChar* targetLimit = &target[0] + outSize;

			toErr = U_ZERO_ERROR;
			ucnv_toUnicode(m_from, &target, targetLimit,
			               &source, sourceLimit, NULL, flush, &toErr);

			if (st)
				st->inputBytesRead += (source - reinterpret_cast <const char*>(&cpInBuffer[0]));

			if (toErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(toErr))
			{
				if (toErr == U_INVALID_CHAR_FOUND ||
				    toErr == U_TRUNCATED_CHAR_FOUND ||
				    toErr == U_ILLEGAL_CHAR_FOUND)
				{
					// Error will be thrown later (*)
				}
				else
				{
					throw exceptions::charset_conv_error("[ICU] Error converting to Unicode from " + m_source.getName());
				}
			}

			// The Unicode source is the buffer just written and the limit
			// is where the previous conversion stopped (target is moved in the conversion)
			const UChar* uSource = &uOutBuffer[0];
			UChar* uSourceLimit = &target[0];
			UErrorCode fromErr;

			// Loop until converted chars are fully written
			do
			{
				char* cpTarget = &cpOutBuffer[0];
				const char* cpTargetLimit = &cpOutBuffer[0] + cpOutBufferSz;

				fromErr = U_ZERO_ERROR;

				// Write converted bytes (Unicode) to destination codepage
				ucnv_fromUnicode(m_to, &cpTarget, cpTargetLimit,
				                 &uSource, uSourceLimit, NULL, flush, &fromErr);

				if (st)
				{
					// Decrement input bytes count by the number of input bytes in error
					char errBytes[16];
					int8_t errBytesLen = sizeof(errBytes);
					UErrorCode errBytesErr = U_ZERO_ERROR;

	 				ucnv_getInvalidChars(m_from, errBytes, &errBytesLen, &errBytesErr);

					st->inputBytesRead -= errBytesLen;
					st->outputBytesWritten += cpTarget - &cpOutBuffer[0];
				}

				// (*) If an error occurred while converting from input charset, throw it now
				if (toErr == U_INVALID_CHAR_FOUND ||
				    toErr == U_TRUNCATED_CHAR_FOUND ||
				    toErr == U_ILLEGAL_CHAR_FOUND)
				{
					throw exceptions::illegal_byte_sequence_for_charset();
				}

				if (fromErr != U_BUFFER_OVERFLOW_ERROR && U_FAILURE(fromErr))
				{
					if (fromErr == U_INVALID_CHAR_FOUND ||
					    fromErr == U_TRUNCATED_CHAR_FOUND ||
					    fromErr == U_ILLEGAL_CHAR_FOUND)
					{
						throw exceptions::illegal_byte_sequence_for_charset();
					}
					else
					{
						throw exceptions::charset_conv_error("[ICU] Error converting from Unicode to " + m_dest.getName());
					}
				}

				// Write to destination stream
				out.write(&cpOutBuffer[0], (cpTarget - &cpOutBuffer[0]));

			} while (fromErr == U_BUFFER_OVERFLOW_ERROR);

		} while (toErr == U_BUFFER_OVERFLOW_ERROR);
	}
}