Beispiel #1
0
status_t
ParseFilter::ProcessMailMessage(BPositionIO **data, BEntry */*entry*/, BMessage *headers,
	BPath */*folder*/, const char */*uid*/)
{
	char byte;
	(*data)->ReadAt(0,&byte, 1);
	(*data)->Seek(SEEK_SET, 0);

	status_t status = parse_header(*headers, **data);
	if (status < B_OK)
		return status;

	//
	// add pseudo-header THREAD, that contains the subject
	// minus stuff in []s (added by mailing lists) and
	// Re: prefixes, added by mailers when you reply.
	// This will generally be the "thread subject".
	//
	BString string;
	string.SetTo(headers->FindString("Subject"));
	SubjectToThread(string);
	headers->AddString("THREAD", string.String());

	// name
	if (headers->FindString(fNameField.String(), 0, &string) == B_OK) {
		extract_address_name(string);
		headers->AddString("NAME", string);
	}

	// header length
	headers->AddInt32(B_MAIL_ATTR_HEADER, (int32)((*data)->Position()));
	// What about content length?  If we do that, we have to D/L the
	// whole message...
	//--NathanW says let the disk consumer do that
	
	(*data)->Seek(0, SEEK_SET);
	return B_OK;
}
BMailFilterAction
HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file,
	BMessage& attributes)
{
	file.Seek(0, SEEK_SET);

	// TODO: attributes.AddInt32(B_MAIL_ATTR_CONTENT, length);
	attributes.AddInt32(B_MAIL_ATTR_ACCOUNT_ID, fAccountID);
	attributes.AddString(B_MAIL_ATTR_ACCOUNT, fAccountName);

	BString header;
	off_t size;
	if (file.GetSize(&size) == B_OK) {
		char* buffer = header.LockBuffer(size);
		if (buffer == NULL)
			return B_NO_MEMORY;

		ssize_t bytesRead = file.Read(buffer, size);
		if (bytesRead < 0)
			return bytesRead;
		if (bytesRead != size)
			return B_IO_ERROR;

		header.UnlockBuffer(size);
	}

	for (int i = 0; gDefaultFields[i].rfc_name; ++i) {
		BString target;
		status_t status = extract_from_header(header,
			gDefaultFields[i].rfc_name, target);
		if (status != B_OK)
			continue;

		switch (gDefaultFields[i].attr_type){
			case B_STRING_TYPE:
				sanitize_white_space(target);
				attributes.AddString(gDefaultFields[i].attr_name, target);
				break;

			case B_TIME_TYPE:
			{
				time_t when;
				when = ParseDateWithTimeZone(target);
				if (when == -1)
					when = time(NULL); // Use current time if it's undecodable.
				attributes.AddData(B_MAIL_ATTR_WHEN, B_TIME_TYPE, &when,
					sizeof(when));
				break;
			}
		}
	}

	BString senderName = _ExtractName(attributes.FindString(B_MAIL_ATTR_FROM));
	attributes.AddString(B_MAIL_ATTR_NAME, senderName);

	// Generate a file name for the incoming message.  See also
	// Message::RenderTo which does a similar thing for outgoing messages.
	BString name = attributes.FindString(B_MAIL_ATTR_SUBJECT);
	SubjectToThread(name); // Extract the core subject words.
	if (name.Length() <= 0)
		name = "No Subject";
	attributes.AddString(B_MAIL_ATTR_THREAD, name);

	// Convert the date into a year-month-day fixed digit width format, so that
	// sorting by file name will give all the messages with the same subject in
	// order of date.
	time_t dateAsTime = 0;
	const time_t* datePntr;
	ssize_t dateSize;
	char numericDateString[40];
	struct tm timeFields;

	if (attributes.FindData(B_MAIL_ATTR_WHEN, B_TIME_TYPE,
			(const void**)&datePntr, &dateSize) == B_OK)
		dateAsTime = *datePntr;
	localtime_r(&dateAsTime, &timeFields);
	snprintf(numericDateString, sizeof(numericDateString),
		"%04d%02d%02d%02d%02d%02d",
		timeFields.tm_year + 1900, timeFields.tm_mon + 1, timeFields.tm_mday,
		timeFields.tm_hour, timeFields.tm_min, timeFields.tm_sec);
	name << " " << numericDateString;

	BString workerName = attributes.FindString(B_MAIL_ATTR_FROM);
	extract_address_name(workerName);
	name << " " << workerName;

	name.Truncate(222);	// reserve space for the unique number

	// Get rid of annoying characters which are hard to use in the shell.
	name.ReplaceAll('/', '_');
	name.ReplaceAll('\'', '_');
	name.ReplaceAll('"', '_');
	name.ReplaceAll('!', '_');
	name.ReplaceAll('<', '_');
	name.ReplaceAll('>', '_');
	_RemoveExtraWhitespace(name);
	_RemoveLeadingDots(name);
		// Avoid files starting with a dot.

	if (!attributes.HasString(B_MAIL_ATTR_STATUS))
		attributes.AddString(B_MAIL_ATTR_STATUS, "New");

	_SetType(attributes, B_PARTIAL_MAIL_TYPE);

	ref.set_name(name.String());

	return B_MOVE_MAIL_ACTION;
}
Beispiel #3
0
status_t
BEmailMessage::RenderTo(BDirectory *dir, BEntry *msg)
{
	time_t currentTime;
	char numericDateString [40];
	struct tm timeFields;
	BString worker;

	// Generate a file name for the outgoing message.  See also
	// FolderFilter::ProcessMailMessage which does something similar for
	// incoming messages.

	BString name = Subject();
	SubjectToThread (name); // Extract the core subject words.
	if (name.Length() <= 0)
		name = "No Subject";
	if (name[0] == '.')
		name.Prepend ("_"); // Avoid hidden files, starting with a dot.

	// Convert the date into a year-month-day fixed digit width format, so that
	// sorting by file name will give all the messages with the same subject in
	// order of date.
	time (&currentTime);
	localtime_r (&currentTime, &timeFields);
	sprintf (numericDateString, "%04d%02d%02d%02d%02d%02d",
		timeFields.tm_year + 1900,
		timeFields.tm_mon + 1,
		timeFields.tm_mday,
		timeFields.tm_hour,
		timeFields.tm_min,
		timeFields.tm_sec);
	name << " " << numericDateString;

	worker = From();
	extract_address_name(worker);
	name << " " << worker;

	name.Truncate(222);	// reserve space for the uniquer

	// Get rid of annoying characters which are hard to use in the shell.
	name.ReplaceAll('/','_');
	name.ReplaceAll('\'','_');
	name.ReplaceAll('"','_');
	name.ReplaceAll('!','_');
	name.ReplaceAll('<','_');
	name.ReplaceAll('>','_');
	while (name.FindFirst("  ") >= 0) // Remove multiple spaces.
		name.Replace("  " /* Old */, " " /* New */, 1024 /* Count */);

	int32 uniquer = time(NULL);
	worker = name;

	int32 tries = 30;
	bool exists;
	while ((exists = dir->Contains(worker.String())) && --tries > 0) {
		srand(rand());
		uniquer += (rand() >> 16) - 16384;

		worker = name;
		worker << ' ' << uniquer;
	}

	if (exists)
		printf("could not create mail! (should be: %s)\n", worker.String());

	BFile file;
	status_t status = dir->CreateFile(worker.String(), &file);
	if (status < B_OK)
		return status;

	if (msg != NULL)
		msg->SetTo(dir,worker.String());

	return RenderToRFC822(&file);
}