Ejemplo n.º 1
0
int
BEmailMessage::Priority()
{
	int priorityNumber;
	const char *priorityString;

	/* The usual values are a number from 1 to 5, or one of three words:
	X-Priority: 1 and/or X-MSMail-Priority: High
	X-Priority: 3 and/or X-MSMail-Priority: Normal
	X-Priority: 5 and/or X-MSMail-Priority: Low
	Also plain Priority: is "normal", "urgent" or "non-urgent", see RFC 1327. */

	priorityString = HeaderField("Priority");
	if (priorityString == NULL)
		priorityString = HeaderField("X-Priority");
	if (priorityString == NULL)
		priorityString = HeaderField("X-Msmail-Priority");
	if (priorityString == NULL)
		return 3;
	priorityNumber = atoi (priorityString);
	if (priorityNumber != 0) {
		if (priorityNumber > 5)
			priorityNumber = 5;
		if (priorityNumber < 1)
			priorityNumber = 1;
		return priorityNumber;
	}
	if (strcasecmp (priorityString, "Low") == 0
		|| strcasecmp (priorityString, "non-urgent") == 0)
		return 5;
	if (strcasecmp (priorityString, "High") == 0
		|| strcasecmp (priorityString, "urgent") == 0)
		return 1;
	return 3;
}
Ejemplo n.º 2
0
void BMIMEMultipartMailContainer::SetBoundary(const char *boundary) {
	free ((void *) _boundary);
	_boundary = NULL;
	if (boundary != NULL)
		_boundary = strdup(boundary);

	BMessage structured;
	HeaderField("Content-Type",&structured);

	if (_boundary == NULL)
		structured.RemoveName("boundary");
	else if (structured.ReplaceString("boundary",_boundary) != B_OK)
		structured.AddString("boundary",_boundary);

	SetHeaderField("Content-Type",&structured);
}
Ejemplo n.º 3
0
status_t BMIMEMultipartMailContainer::SetToRFC822(BPositionIO *data, size_t length, bool copy_data)
{
	typedef enum LookingForEnum {
		FIRST_NEWLINE,
		INITIAL_DASHES,
		BOUNDARY_BODY,
		LAST_NEWLINE,
		MAX_LOOKING_STATES
	} LookingFor;

	ssize_t     amountRead;
	ssize_t     amountToRead;
	ssize_t     boundaryLength;
	char        buffer [4096];
	ssize_t     bufferIndex;
	off_t       bufferOffset;
	ssize_t     bufferSize;
	BMessage    content_type;
	const char *content_type_string;
	bool        finalBoundary = false;
	bool        finalComponentCompleted = false;
	int         i;
	off_t       lastBoundaryOffset;
	LookingFor  state;
	off_t       startOfBoundaryOffset;
	off_t       topLevelEnd;
	off_t       topLevelStart;

	// Clear out old components.  Maybe make a MakeEmpty method?

	for (i = _components_in_code.CountItems(); i-- > 0;)
		delete (BMailComponent *)_components_in_code.RemoveItem(i);

	for (i = _components_in_raw.CountItems(); i-- > 0;)
		delete (message_part *)_components_in_raw.RemoveItem(i);

	// Start by reading the headers and getting the boundary string.

	_io_data = data;
	topLevelStart = data->Position();
	topLevelEnd = topLevelStart + length;

	BMailComponent::SetToRFC822(data,length);

	HeaderField("Content-Type",&content_type);
	content_type_string = content_type.FindString("unlabeled");
	if (content_type_string == NULL ||
		strncasecmp(content_type_string,"multipart",9) != 0)
		return B_BAD_TYPE;

	if (!content_type.HasString("boundary"))
		return B_BAD_TYPE;
	free ((void *) _boundary);
	_boundary = strdup(content_type.FindString("boundary"));
	boundaryLength = strlen(_boundary);
	if (boundaryLength > (ssize_t) sizeof (buffer) / 2)
		return B_BAD_TYPE; // Boundary is way too long, should be max 70 chars.

	//	Find container parts by scanning through the given portion of the file
	//	for the boundary marker lines.  The stuff between the header and the
	//	first boundary is ignored, the same as the stuff after the last
	//	boundary.  The rest get stored away as our sub-components.  See RFC2046
	//	section 5.1 for details.

	bufferOffset = data->Position(); // File offset of the start of the buffer.
	bufferIndex = 0; // Current position we are examining in the buffer.
	bufferSize = 0; // Amount of data actually in the buffer, not including NUL.
	startOfBoundaryOffset = -1;
	lastBoundaryOffset = -1;
	state = INITIAL_DASHES; // Starting just after a new line so don't search for it.
	while (((bufferOffset + bufferIndex < topLevelEnd)
		|| (state == LAST_NEWLINE /* No EOF test in LAST_NEWLINE state */))
		&& !finalComponentCompleted)
	{
		// Refill the buffer if the remaining amount of data is less than a
		// boundary's worth, plus four dashes and two CRLFs.
		if (bufferSize - bufferIndex < boundaryLength + 8)
		{
			// Shuffle the remaining bit of data in the buffer over to the front.
			if (bufferSize - bufferIndex > 0)
				memmove (buffer, buffer + bufferIndex, bufferSize - bufferIndex);
			bufferOffset += bufferIndex;
			bufferSize = bufferSize - bufferIndex;
			bufferIndex = 0;

			// Fill up the rest of the buffer with more data.  Also leave space
			// for a NUL byte just past the last data in the buffer so that
			// simple string searches won't go off past the end of the data.
			amountToRead = topLevelEnd - (bufferOffset + bufferSize);
			if (amountToRead > (ssize_t) sizeof (buffer) - 1 - bufferSize)
				amountToRead = sizeof (buffer) - 1 - bufferSize;
			if (amountToRead > 0) {
				amountRead = data->Read (buffer + bufferSize, amountToRead);
				if (amountRead < 0)
					return amountRead;
				bufferSize += amountRead;
			}
			buffer [bufferSize] = 0; // Add an end of string NUL byte.
		}

		// Search for whatever parts of the boundary we are currently looking
		// for in the buffer.  It starts with a newline (officially CRLF but we
		// also accept just LF for off-line e-mail files), followed by two
		// hyphens or dashes "--", followed by the unique boundary string
		// specified earlier in the header, followed by two dashes "--" for the
		// final boundary (or zero dashes for intermediate boundaries),
		// followed by white space (possibly including header style comments in
		// brackets), and then a newline.

		switch (state) {
			case FIRST_NEWLINE:
				// The newline before the boundary is considered to be owned by
				// the boundary, not part of the previous MIME component.
				startOfBoundaryOffset = bufferOffset + bufferIndex;
				if (buffer[bufferIndex] == '\r' && buffer[bufferIndex + 1] == '\n') {
					bufferIndex += 2;
					state = INITIAL_DASHES;
				} else if (buffer[bufferIndex] == '\n') {
					bufferIndex += 1;
					state = INITIAL_DASHES;
				} else
					bufferIndex++;
				break;

			case INITIAL_DASHES:
				if (buffer[bufferIndex] == '-' && buffer[bufferIndex + 1] == '-') {
					bufferIndex += 2;
					state = BOUNDARY_BODY;
				} else
					state = FIRST_NEWLINE;
				break;

			case BOUNDARY_BODY:
				if (strncmp (buffer + bufferIndex, _boundary, boundaryLength) != 0) {
					state = FIRST_NEWLINE;
					break;
				}
				bufferIndex += boundaryLength;
				finalBoundary = false;
				if (buffer[bufferIndex] == '-' && buffer[bufferIndex + 1] == '-') {
					bufferIndex += 2;
					finalBoundary = true;
				}
				state = LAST_NEWLINE;
				break;

			case LAST_NEWLINE:
				// Just keep on scanning until the next new line or end of file.
				if (buffer[bufferIndex] == '\r' && buffer[bufferIndex + 1] == '\n')
					bufferIndex += 2;
				else if (buffer[bufferIndex] == '\n')
					bufferIndex += 1;
				else if (buffer[bufferIndex] != 0 /* End of file is like a newline */) {
					// Not a new line or end of file, just skip over
					// everything.  White space or not, we don't really care.
					bufferIndex += 1;
					break;
				}
				// Got to the end of the boundary line and maybe now have
				// another component to add.
				if (lastBoundaryOffset >= 0) {
					_components_in_raw.AddItem (new message_part (lastBoundaryOffset, startOfBoundaryOffset));
					_components_in_code.AddItem (NULL);
				}
				// Next component's header starts just after the boundary line.
				lastBoundaryOffset = bufferOffset + bufferIndex;
				if (finalBoundary)
					finalComponentCompleted = true;
				state = FIRST_NEWLINE;
				break;

			default: // Should not happen.
				state = FIRST_NEWLINE;
		}
	}

	// Some bad MIME encodings (usually spam, or damaged files) don't put on
	// the trailing boundary.  Dump whatever is remaining into a final
	// component if there wasn't a trailing boundary and there is some data
	// remaining.

	if (!finalComponentCompleted
		&& lastBoundaryOffset >= 0 && lastBoundaryOffset < topLevelEnd) {
		_components_in_raw.AddItem (new message_part (lastBoundaryOffset, topLevelEnd));
		_components_in_code.AddItem (NULL);
	}

	// If requested, actually read the data inside each component, otherwise
	// only the positions in the BPositionIO are recorded.

	if (copy_data) {
		for (i = 0; GetComponent(i, true /* parse_now */) != NULL; i++) {}
	}
	
	data->Seek (topLevelEnd, SEEK_SET);
	return B_OK;
}
Ejemplo n.º 4
0
const char *
BEmailMessage::Date()
{
	return HeaderField("Date");
}
Ejemplo n.º 5
0
const char *
BEmailMessage::Subject()
{
	return HeaderField("Subject");
}
Ejemplo n.º 6
0
const char *
BEmailMessage::CC()
{
	return HeaderField("Cc");
		// Note case of CC is "Cc" in our internal headers.
}
Ejemplo n.º 7
0
const char *
BEmailMessage::ReplyTo()
{
	return HeaderField("Reply-To");
}
Ejemplo n.º 8
0
const char *
BEmailMessage::From()
{
	return HeaderField("From");
}
Ejemplo n.º 9
0
const char *
BEmailMessage::To()
{
	return HeaderField("To");
}