* mail_util.h was not self-contained.

* Added a few missing breaks in MailProtocolThread::MessageReceived()!
* Minor coding style update.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42808 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2011-10-08 18:41:20 +00:00
parent a1b98367ae
commit 0c7f804cec
4 changed files with 487 additions and 495 deletions
+5 -3
View File
@@ -1,4 +1,5 @@
/* /*
* Copyright 2011, Haiku, Inc. All rights reserved.
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/ */
#ifndef ZOIDBERG_GARGOYLE_MAIL_UTIL_H #ifndef ZOIDBERG_GARGOYLE_MAIL_UTIL_H
@@ -10,9 +11,10 @@
#include <stdio.h> #include <stdio.h>
#include <Node.h> #include <DataIO.h>
#include <E-mail.h> #include <E-mail.h>
#include <Message.h>
#include <Node.h>
// TODO: this should only be preserved for gcc2 compatibility // TODO: this should only be preserved for gcc2 compatibility
@@ -60,7 +62,7 @@ ssize_t utf8_to_rfc2047(char **bufp, ssize_t length,uint32 charset, char encodin
// Unidentified charsets and conversion errors cause // Unidentified charsets and conversion errors cause
// the offending text to be skipped. // the offending text to be skipped.
void FoldLineAtWhiteSpaceAndAddCRLF (BString &string); void FoldLineAtWhiteSpaceAndAddCRLF(BString &string);
// Insert CRLF at various spots in the given string (before white space) so // Insert CRLF at various spots in the given string (before white space) so
// that the line length is mostly under 78 bytes. Also makes sure there is a // that the line length is mostly under 78 bytes. Also makes sure there is a
// CRLF at the very end. // CRLF at the very end.
+20 -20
View File
@@ -1,6 +1,7 @@
/* /*
* Copyright 2011, Haiku, Inc. All rights reserved. * Copyright 2011, Haiku, Inc. All rights reserved.
* Copyright 2011, Clemens Zeidler <[email protected]> * Copyright 2011, Clemens Zeidler <[email protected]>
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -17,10 +18,9 @@
struct mail_header_field { struct mail_header_field {
const char *rfc_name; const char* rfc_name;
const char* attr_name;
const char *attr_name; type_code attr_type;
type_code attr_type;
// currently either B_STRING_TYPE and B_TIME_TYPE // currently either B_STRING_TYPE and B_TIME_TYPE
}; };
@@ -65,7 +65,7 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
file->Seek(0, SEEK_SET); file->Seek(0, SEEK_SET);
BMessage attributes; BMessage attributes;
// TODO attributes.AddInt32(B_MAIL_ATTR_CONTENT, length); // TODO: attributes.AddInt32(B_MAIL_ATTR_CONTENT, length);
attributes.AddInt32(B_MAIL_ATTR_ACCOUNT_ID, fAccountID); attributes.AddInt32(B_MAIL_ATTR_ACCOUNT_ID, fAccountID);
attributes.AddString(B_MAIL_ATTR_ACCOUNT, fAccountName); attributes.AddString(B_MAIL_ATTR_ACCOUNT, fAccountName);
@@ -83,6 +83,7 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
gDefaultFields[i].rfc_name, target); gDefaultFields[i].rfc_name, target);
if (status != B_OK) if (status != B_OK)
continue; continue;
switch (gDefaultFields[i].attr_type){ switch (gDefaultFields[i].attr_type){
case B_STRING_TYPE: case B_STRING_TYPE:
attributes.AddString(gDefaultFields[i].attr_name, target); attributes.AddString(gDefaultFields[i].attr_name, target);
@@ -111,8 +112,9 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
if (name.Length() <= 0) if (name.Length() <= 0)
name = "No Subject"; name = "No Subject";
attributes.AddString(B_MAIL_ATTR_THREAD, name); attributes.AddString(B_MAIL_ATTR_THREAD, name);
// Avoid hidden files, starting with a dot.
if (name[0] == '.') if (name[0] == '.')
name.Prepend ("_"); // Avoid hidden files, starting with a dot. name.Prepend ("_");
// Convert the date into a year-month-day fixed digit width format, so that // 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 // sorting by file name will give all the messages with the same subject in
@@ -120,23 +122,20 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
time_t dateAsTime = 0; time_t dateAsTime = 0;
const time_t* datePntr; const time_t* datePntr;
ssize_t dateSize; ssize_t dateSize;
char numericDateString [40]; char numericDateString[40];
struct tm timeFields; struct tm timeFields;
if (attributes.FindData(B_MAIL_ATTR_WHEN, B_TIME_TYPE, if (attributes.FindData(B_MAIL_ATTR_WHEN, B_TIME_TYPE,
(const void**)&datePntr, &dateSize) == B_OK) (const void**)&datePntr, &dateSize) == B_OK)
dateAsTime = *datePntr; dateAsTime = *datePntr;
localtime_r(&dateAsTime, &timeFields); localtime_r(&dateAsTime, &timeFields);
sprintf(numericDateString, "%04d%02d%02d%02d%02d%02d", snprintf(numericDateString, sizeof(numericDateString),
timeFields.tm_year + 1900, "%04d%02d%02d%02d%02d%02d",
timeFields.tm_mon + 1, timeFields.tm_year + 1900, timeFields.tm_mon + 1, timeFields.tm_mday,
timeFields.tm_mday, timeFields.tm_hour, timeFields.tm_min, timeFields.tm_sec);
timeFields.tm_hour,
timeFields.tm_min,
timeFields.tm_sec);
name << " " << numericDateString; name << " " << numericDateString;
BString worker = attributes.FindString("MAIL:from"); BString worker = attributes.FindString(B_MAIL_ATTR_FROM);
extract_address_name(worker); extract_address_name(worker);
name << " " << worker; name << " " << worker;
@@ -149,8 +148,9 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
name.ReplaceAll('!', '_'); name.ReplaceAll('!', '_');
name.ReplaceAll('<', '_'); name.ReplaceAll('<', '_');
name.ReplaceAll('>', '_'); name.ReplaceAll('>', '_');
while (name.FindFirst(" ") >= 0) // Remove multiple spaces. // Remove multiple spaces.
name.Replace(" " /* Old */, " " /* New */, 1024 /* Count */); while (name.FindFirst(" ") >= 0)
name.Replace(" ", " ", 1024);
worker = name; worker = name;
int32 identicalNumber = 1; int32 identicalNumber = 1;
@@ -162,10 +162,10 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
worker << "_" << identicalNumber; worker << "_" << identicalNumber;
status = _SetFileName(ref, worker); status = _SetFileName(ref, worker);
} }
if (status < B_OK) if (status < B_OK) {
printf("FolderFilter::ProcessMailMessage: could not rename mail (%s)! " printf("FolderFilter::ProcessMailMessage: could not rename mail (%s)! "
"(should be: %s)\n",strerror(status), worker.String()); "(should be: %s)\n",strerror(status), worker.String());
else { } else {
entry_ref to(ref.device, ref.directory, worker); entry_ref to(ref.device, ref.directory, worker);
fMailProtocol.FileRenamed(ref, to); fMailProtocol.FileRenamed(ref, to);
} }
+130 -118
View File
@@ -1,7 +1,7 @@
/* BMailProtocol - the base class for protocol filters /*
** * Copyright 2011, Haiku, Inc. All rights reserved.
** Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/ */
#include <stdio.h> #include <stdio.h>
@@ -35,56 +35,65 @@
using std::map; using std::map;
const uint32 kMsgSyncMessages = '&SyM';
const uint32 kMsgDeleteMessage = '&DeM';
const uint32 kMsgAppendMessage = '&ApM';
const uint32 kMsgMoveFile = '&MoF';
const uint32 kMsgDeleteFile = '&DeF';
const uint32 kMsgFileRenamed = '&FiR';
const uint32 kMsgFileDeleted = '&FDe';
const uint32 kMsgInit = '&Ini';
const uint32 kMsgSendMessage = '&SeM';
MailFilter::MailFilter(MailProtocol& protocol, AddonSettings* settings) MailFilter::MailFilter(MailProtocol& protocol, AddonSettings* settings)
: :
fMailProtocol(protocol), fMailProtocol(protocol),
fAddonSettings(settings) fAddonSettings(settings)
{ {
} }
MailFilter::~MailFilter() MailFilter::~MailFilter()
{ {
} }
void void
MailFilter::HeaderFetched(const entry_ref& ref, BFile* file) MailFilter::HeaderFetched(const entry_ref& ref, BFile* file)
{ {
} }
void void
MailFilter::BodyFetched(const entry_ref& ref, BFile* file) MailFilter::BodyFetched(const entry_ref& ref, BFile* file)
{ {
} }
void void
MailFilter::MailboxSynced(status_t status) MailFilter::MailboxSynced(status_t status)
{ {
} }
void void
MailFilter::MessageReadyToSend(const entry_ref& ref, BFile* file) MailFilter::MessageReadyToSend(const entry_ref& ref, BFile* file)
{ {
} }
void void
MailFilter::MessageSent(const entry_ref& ref, BFile* file) MailFilter::MessageSent(const entry_ref& ref, BFile* file)
{ {
} }
// #pragma mark -
MailProtocol::MailProtocol(BMailAccountSettings* settings) MailProtocol::MailProtocol(BMailAccountSettings* settings)
: :
fMailNotifier(NULL), fMailNotifier(NULL),
@@ -379,6 +388,9 @@ MailProtocol::_LoadFilter(AddonSettings* filterSettings)
} }
// #pragma mark -
InboundProtocol::InboundProtocol(BMailAccountSettings* settings) InboundProtocol::InboundProtocol(BMailAccountSettings* settings)
: :
MailProtocol(settings) MailProtocol(settings)
@@ -389,7 +401,7 @@ InboundProtocol::InboundProtocol(BMailAccountSettings* settings)
InboundProtocol::~InboundProtocol() InboundProtocol::~InboundProtocol()
{ {
} }
@@ -408,6 +420,9 @@ InboundProtocol::MarkMessageAsRead(const entry_ref& ref, read_flags flag)
} }
// #pragma mark -
OutboundProtocol::OutboundProtocol(BMailAccountSettings* settings) OutboundProtocol::OutboundProtocol(BMailAccountSettings* settings)
: :
MailProtocol(settings) MailProtocol(settings)
@@ -418,15 +433,11 @@ OutboundProtocol::OutboundProtocol(BMailAccountSettings* settings)
OutboundProtocol::~OutboundProtocol() OutboundProtocol::~OutboundProtocol()
{ {
} }
const uint32 kMsgMoveFile = '&MoF'; // #pragma mark -
const uint32 kMsgDeleteFile = '&DeF';
const uint32 kMsgFileRenamed = '&FiR';
const uint32 kMsgFileDeleted = '&FDe';
const uint32 kMsgInit = '&Ini';
MailProtocolThread::MailProtocolThread(MailProtocol* protocol) MailProtocolThread::MailProtocolThread(MailProtocol* protocol)
@@ -448,48 +459,50 @@ void
MailProtocolThread::MessageReceived(BMessage* message) MailProtocolThread::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgInit: case kMsgInit:
fMailProtocol->SetProtocolThread(this); fMailProtocol->SetProtocolThread(this);
break; break;
case kMsgMoveFile: case kMsgMoveFile:
{ {
entry_ref file; entry_ref file;
message->FindRef("file", &file); message->FindRef("file", &file);
entry_ref dir; entry_ref dir;
message->FindRef("directory", &dir); message->FindRef("directory", &dir);
BDirectory directory(&dir); BDirectory directory(&dir);
fMailProtocol->MoveMessage(file, directory); fMailProtocol->MoveMessage(file, directory);
break; break;
} }
case kMsgDeleteFile: case kMsgDeleteFile:
{ {
entry_ref file; entry_ref file;
message->FindRef("file", &file); message->FindRef("file", &file);
fMailProtocol->DeleteMessage(file); fMailProtocol->DeleteMessage(file);
break; break;
} }
case kMsgFileRenamed: case kMsgFileRenamed:
{ {
entry_ref from; entry_ref from;
message->FindRef("from", &from); message->FindRef("from", &from);
entry_ref to; entry_ref to;
message->FindRef("to", &to); message->FindRef("to", &to);
fMailProtocol->FileRenamed(from, to); fMailProtocol->FileRenamed(from, to);
} break;
}
case kMsgFileDeleted: case kMsgFileDeleted:
{ {
node_ref node; node_ref node;
message->FindInt32("device",&node.device); message->FindInt32("device",&node.device);
message->FindInt64("node", &node.node); message->FindInt64("node", &node.node);
fMailProtocol->FileDeleted(node); fMailProtocol->FileDeleted(node);
} break;
}
default: default:
BLooper::MessageReceived(message); BLooper::MessageReceived(message);
} }
} }
@@ -538,9 +551,7 @@ MailProtocolThread::TriggerFileDeleted(const node_ref& node)
} }
const uint32 kMsgSyncMessages = '&SyM'; // #pragma mark -
const uint32 kMsgDeleteMessage = '&DeM';
const uint32 kMsgAppendMessage = '&ApM';
InboundProtocolThread::InboundProtocolThread(InboundProtocol* protocol) InboundProtocolThread::InboundProtocolThread(InboundProtocol* protocol)
@@ -562,57 +573,58 @@ void
InboundProtocolThread::MessageReceived(BMessage* message) InboundProtocolThread::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgSyncMessages: case kMsgSyncMessages:
{ {
status_t status = fProtocol->SyncMessages(); status_t status = fProtocol->SyncMessages();
_NotiyMailboxSynced(status); _NotiyMailboxSynced(status);
break;
}
case kMsgFetchBody:
{
entry_ref ref;
message->FindRef("ref", &ref);
status_t status = fProtocol->FetchBody(ref);
BMessenger target;
if (message->FindMessenger("target", &target) != B_OK)
break; break;
}
BMessage message(kMsgBodyFetched); case kMsgFetchBody:
message.AddInt32("status", status); {
message.AddRef("ref", &ref); entry_ref ref;
target.SendMessage(&message); message->FindRef("ref", &ref);
break; status_t status = fProtocol->FetchBody(ref);
}
case kMsgMarkMessageAsRead: BMessenger target;
{ if (message->FindMessenger("target", &target) != B_OK)
entry_ref ref; break;
message->FindRef("ref", &ref);
read_flags read = (read_flags)message->FindInt32("read");
fProtocol->MarkMessageAsRead(ref, read);
break;
}
case kMsgDeleteMessage: BMessage message(kMsgBodyFetched);
{ message.AddInt32("status", status);
entry_ref ref; message.AddRef("ref", &ref);
message->FindRef("ref", &ref); target.SendMessage(&message);
fProtocol->DeleteMessage(ref); break;
break; }
}
case kMsgAppendMessage: case kMsgMarkMessageAsRead:
{ {
entry_ref ref; entry_ref ref;
message->FindRef("ref", &ref); message->FindRef("ref", &ref);
fProtocol->AppendMessage(ref); read_flags read = (read_flags)message->FindInt32("read");
break; fProtocol->MarkMessageAsRead(ref, read);
} break;
}
default: case kMsgDeleteMessage:
MailProtocolThread::MessageReceived(message); {
entry_ref ref;
message->FindRef("ref", &ref);
fProtocol->DeleteMessage(ref);
break;
}
case kMsgAppendMessage:
{
entry_ref ref;
message->FindRef("ref", &ref);
fProtocol->AppendMessage(ref);
break;
}
default:
MailProtocolThread::MessageReceived(message);
break;
} }
} }
@@ -671,7 +683,7 @@ InboundProtocolThread::_NotiyMailboxSynced(status_t status)
} }
const uint32 kMsgSendMessage = '&SeM'; // #pragma mark -
OutboundProtocolThread::OutboundProtocolThread(OutboundProtocol* protocol) OutboundProtocolThread::OutboundProtocolThread(OutboundProtocol* protocol)
@@ -693,22 +705,22 @@ void
OutboundProtocolThread::MessageReceived(BMessage* message) OutboundProtocolThread::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case kMsgSendMessage: case kMsgSendMessage:
{ {
std::vector<entry_ref> mails; std::vector<entry_ref> mails;
for (int32 i = 0; ;i++) { for (int32 i = 0; ;i++) {
entry_ref ref; entry_ref ref;
if (message->FindRef("ref", i, &ref) != B_OK) if (message->FindRef("ref", i, &ref) != B_OK)
break; break;
mails.push_back(ref); mails.push_back(ref);
}
size_t size = message->FindInt32("size");
fProtocol->SendMessages(mails, size);
break;
} }
size_t size = message->FindInt32("size");
fProtocol->SendMessages(mails, size);
break;
}
default: default:
MailProtocolThread::MessageReceived(message); MailProtocolThread::MessageReceived(message);
} }
} }
+332 -354
View File
@@ -1,15 +1,10 @@
/* mail util - header parsing /*
** * Copyright 2011, Haiku, Inc. All rights reserved.
** Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved. * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
*/ */
#include <UTF8.h> #include <mail_util.h>
#include <Message.h>
#include <String.h>
#include <Locker.h>
#include <DataIO.h>
#include <List.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -18,27 +13,30 @@
#include <regex.h> #include <regex.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <List.h>
#include <Locker.h>
#include <parsedate.h> #include <parsedate.h>
#include <String.h>
#include <UTF8.h>
#include <mail_encoding.h> #include <mail_encoding.h>
#include <mail_util.h>
#include <CharacterSet.h> #include <CharacterSet.h>
#include <CharacterSetRoster.h> #include <CharacterSetRoster.h>
using namespace BPrivate; using namespace BPrivate;
#define CRLF "\r\n" #define CRLF "\r\n"
struct CharsetConversionEntry struct CharsetConversionEntry {
{
const char *charset; const char *charset;
uint32 flavor; uint32 flavor;
}; };
extern const CharsetConversionEntry mail_charsets [] = extern const CharsetConversionEntry mail_charsets[] = {
{
// In order of authority, so when searching for the name for a particular // In order of authority, so when searching for the name for a particular
// numbered conversion, start at the beginning of the array. // numbered conversion, start at the beginning of the array.
{"iso-8859-1", B_ISO1_CONVERSION}, // MIME STANDARD {"iso-8859-1", B_ISO1_CONVERSION}, // MIME STANDARD
@@ -86,239 +84,16 @@ extern const CharsetConversionEntry mail_charsets [] =
}; };
status_t static int32 gLocker = 0;
write_read_attr(BNode& node, read_flags flag) static size_t gNsub = 1;
{ static re_pattern_buffer gRe;
if (node.WriteAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32)) static re_pattern_buffer *gRebuf = NULL;
< 0) static unsigned char gTranslation[256];
return B_ERROR;
#if R5_COMPATIBLE
// manage the status string only if it currently has a "read" status
BString currentStatus;
if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &currentStatus) == B_OK) {
if (currentStatus.ICompare("New") != 0
&& currentStatus.ICompare("Read") != 0
&& currentStatus.ICompare("Seen") != 0)
return B_OK;
}
const char* statusString = (flag == B_READ) ? "Read"
: (flag == B_SEEN) ? "Seen" : "New";
if (node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString,
strlen(statusString)) < 0)
return B_ERROR;
#endif
return B_OK;
}
status_t static int
read_read_attr(BNode& node, read_flags& flag) handle_non_rfc2047_encoding(char **buffer, size_t *bufferLength,
{ size_t *sourceLength)
if (node.ReadAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32))
== sizeof(int32))
return B_OK;
#if R5_COMPATIBLE
BString statusString;
if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &statusString) == B_OK) {
if (statusString.ICompare("New"))
flag = B_UNREAD;
else
flag = B_READ;
return B_OK;
}
#endif
return B_ERROR;
}
// The next couple of functions are our wrapper around convert_to_utf8 and
// convert_from_utf8 so that they can also convert from UTF-8 to UTF-8 by
// specifying the B_MAIL_UTF8_CONVERSION constant as the conversion operation. It
// also lets us add new conversions, like B_MAIL_US_ASCII_CONVERSION.
_EXPORT status_t mail_convert_to_utf8 (
uint32 srcEncoding,
const char *src,
int32 *srcLen,
char *dst,
int32 *dstLen,
int32 *state,
char substitute)
{
int32 copyAmount;
char *originalDst = dst;
status_t returnCode = -1;
if (srcEncoding == B_MAIL_UTF8_CONVERSION) {
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
memcpy (dst, src, copyAmount);
*srcLen = copyAmount;
*dstLen = copyAmount;
returnCode = B_OK;
} else if (srcEncoding == B_MAIL_US_ASCII_CONVERSION) {
int32 i;
unsigned char letter;
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
for (i = 0; i < copyAmount; i++) {
letter = *src++;
if (letter > 0x80U)
// Invalid, could also use substitute, but better to strip high bit.
*dst++ = letter - 0x80U;
else if (letter == 0x80U)
// Can't convert to 0x00 since that's NUL, which would cause problems.
*dst++ = substitute;
else
*dst++ = letter;
}
*srcLen = copyAmount;
*dstLen = copyAmount;
returnCode = B_OK;
} else
returnCode = convert_to_utf8 (srcEncoding, src, srcLen,
dst, dstLen, state, substitute);
if (returnCode == B_OK) {
// Replace spurious NUL bytes, which should normally not be in the
// output of the decoding (not normal UTF-8 characters, and no NULs are
// in our usual input strings). They happen for some odd ISO-2022-JP
// byte pair combinations which are improperly handled by the BeOS
// routines. Like "\e$ByD\e(B" where \e is the ESC character $1B, the
// first ESC $ B switches to a Japanese character set, then the next
// two bytes "yD" specify a character, then ESC ( B switches back to
// the ASCII character set. The UTF-8 conversion yields a NUL byte.
int32 i;
for (i = 0; i < *dstLen; i++)
if (originalDst[i] == 0)
originalDst[i] = substitute;
}
return returnCode;
}
_EXPORT status_t mail_convert_from_utf8 (
uint32 dstEncoding,
const char *src,
int32 *srcLen,
char *dst,
int32 *dstLen,
int32 *state,
char substitute)
{
int32 copyAmount;
status_t errorCode;
int32 originalDstLen = *dstLen;
int32 tempDstLen;
int32 tempSrcLen;
if (dstEncoding == B_MAIL_UTF8_CONVERSION)
{
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
memcpy (dst, src, copyAmount);
*srcLen = copyAmount;
*dstLen = copyAmount;
return B_OK;
}
if (dstEncoding == B_MAIL_US_ASCII_CONVERSION)
{
int32 characterLength;
int32 dstRemaining = *dstLen;
unsigned char letter;
int32 srcRemaining = *srcLen;
// state contains the number of source bytes to skip, left over from a
// partial UTF-8 character split over the end of the buffer from last
// time.
if (srcRemaining <= *state) {
*state -= srcRemaining;
*dstLen = 0;
return B_OK;
}
srcRemaining -= *state;
src += *state;
*state = 0;
while (true) {
if (srcRemaining <= 0 || dstRemaining <= 0)
break;
letter = *src;
if (letter < 0x80)
characterLength = 1; // Regular ASCII equivalent code.
else if (letter < 0xC0)
characterLength = 1; // Invalid in-between data byte 10xxxxxx.
else if (letter < 0xE0)
characterLength = 2;
else if (letter < 0xF0)
characterLength = 3;
else if (letter < 0xF8)
characterLength = 4;
else if (letter < 0xFC)
characterLength = 5;
else if (letter < 0xFE)
characterLength = 6;
else
characterLength = 1; // 0xFE and 0xFF are invalid in UTF-8.
if (letter < 0x80)
*dst++ = *src;
else
*dst++ = substitute;
dstRemaining--;
if (srcRemaining < characterLength) {
// Character split past the end of the buffer.
*state = characterLength - srcRemaining;
srcRemaining = 0;
} else {
src += characterLength;
srcRemaining -= characterLength;
}
}
// Update with the amounts used.
*srcLen = *srcLen - srcRemaining;
*dstLen = *dstLen - dstRemaining;
return B_OK;
}
errorCode = convert_from_utf8 (dstEncoding, src, srcLen, dst, dstLen, state, substitute);
if (errorCode != B_OK)
return errorCode;
if (dstEncoding != B_JIS_CONVERSION)
return B_OK;
// B_JIS_CONVERSION (ISO-2022-JP) works by shifting between different
// character subsets. For E-mail headers (and other uses), it needs to be
// switched back to ASCII at the end (otherwise the last character gets
// lost or other weird things happen in the headers). Note that we can't
// just append the escape code since the convert_from_utf8 "state" will be
// wrong. So we append an ASCII letter and throw it away, leaving just the
// escape code. Well, it actually switches to the Roman character set, not
// ASCII, but that should be OK.
tempDstLen = originalDstLen - *dstLen;
if (tempDstLen < 3) // Not enough space remaining in the output.
return B_OK; // Sort of an error, but we did convert the rest OK.
tempSrcLen = 1;
errorCode = convert_from_utf8 (dstEncoding, "a", &tempSrcLen,
dst + *dstLen, &tempDstLen, state, substitute);
if (errorCode != B_OK)
return errorCode;
*dstLen += tempDstLen - 1 /* don't include the ASCII letter */;
return B_OK;
}
static int handle_non_rfc2047_encoding(char **buffer,size_t *bufferLength,size_t *sourceLength)
{ {
char *string = *buffer; char *string = *buffer;
int32 length = *sourceLength; int32 length = *sourceLength;
@@ -374,7 +149,230 @@ static int handle_non_rfc2047_encoding(char **buffer,size_t *bufferLength,size_t
} }
_EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen) // #pragma mark -
status_t
write_read_attr(BNode& node, read_flags flag)
{
if (node.WriteAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32))
< 0)
return B_ERROR;
// manage the status string only if it currently has a "read" status
BString currentStatus;
if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &currentStatus) == B_OK) {
if (currentStatus.ICompare("New") != 0
&& currentStatus.ICompare("Read") != 0
&& currentStatus.ICompare("Seen") != 0)
return B_OK;
}
const char* statusString = flag == B_READ ? "Read"
: flag == B_SEEN ? "Seen" : "New";
if (node.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, statusString,
strlen(statusString)) < 0)
return B_ERROR;
return B_OK;
}
status_t
read_read_attr(BNode& node, read_flags& flag)
{
if (node.ReadAttr(B_MAIL_ATTR_READ, B_INT32_TYPE, 0, &flag, sizeof(int32))
== sizeof(int32))
return B_OK;
BString statusString;
if (node.ReadAttrString(B_MAIL_ATTR_STATUS, &statusString) == B_OK) {
if (statusString.ICompare("New"))
flag = B_UNREAD;
else
flag = B_READ;
return B_OK;
}
return B_ERROR;
}
// The next couple of functions are our wrapper around convert_to_utf8 and
// convert_from_utf8 so that they can also convert from UTF-8 to UTF-8 by
// specifying the B_MAIL_UTF8_CONVERSION constant as the conversion operation.
// It also lets us add new conversions, like B_MAIL_US_ASCII_CONVERSION.
status_t
mail_convert_to_utf8(uint32 srcEncoding, const char *src, int32 *srcLen,
char *dst, int32 *dstLen, int32 *state, char substitute)
{
int32 copyAmount;
char *originalDst = dst;
status_t returnCode = -1;
if (srcEncoding == B_MAIL_UTF8_CONVERSION) {
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
memcpy (dst, src, copyAmount);
*srcLen = copyAmount;
*dstLen = copyAmount;
returnCode = B_OK;
} else if (srcEncoding == B_MAIL_US_ASCII_CONVERSION) {
int32 i;
unsigned char letter;
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
for (i = 0; i < copyAmount; i++) {
letter = *src++;
if (letter > 0x80U)
// Invalid, could also use substitute, but better to strip high bit.
*dst++ = letter - 0x80U;
else if (letter == 0x80U)
// Can't convert to 0x00 since that's NUL, which would cause problems.
*dst++ = substitute;
else
*dst++ = letter;
}
*srcLen = copyAmount;
*dstLen = copyAmount;
returnCode = B_OK;
} else
returnCode = convert_to_utf8 (srcEncoding, src, srcLen,
dst, dstLen, state, substitute);
if (returnCode == B_OK) {
// Replace spurious NUL bytes, which should normally not be in the
// output of the decoding (not normal UTF-8 characters, and no NULs are
// in our usual input strings). They happen for some odd ISO-2022-JP
// byte pair combinations which are improperly handled by the BeOS
// routines. Like "\e$ByD\e(B" where \e is the ESC character $1B, the
// first ESC $ B switches to a Japanese character set, then the next
// two bytes "yD" specify a character, then ESC ( B switches back to
// the ASCII character set. The UTF-8 conversion yields a NUL byte.
int32 i;
for (i = 0; i < *dstLen; i++)
if (originalDst[i] == 0)
originalDst[i] = substitute;
}
return returnCode;
}
status_t
mail_convert_from_utf8(uint32 dstEncoding, const char *src, int32 *srcLen,
char *dst, int32 *dstLen, int32 *state, char substitute)
{
int32 copyAmount;
status_t errorCode;
int32 originalDstLen = *dstLen;
int32 tempDstLen;
int32 tempSrcLen;
if (dstEncoding == B_MAIL_UTF8_CONVERSION) {
copyAmount = *srcLen;
if (*dstLen < copyAmount)
copyAmount = *dstLen;
memcpy (dst, src, copyAmount);
*srcLen = copyAmount;
*dstLen = copyAmount;
return B_OK;
}
if (dstEncoding == B_MAIL_US_ASCII_CONVERSION) {
int32 characterLength;
int32 dstRemaining = *dstLen;
unsigned char letter;
int32 srcRemaining = *srcLen;
// state contains the number of source bytes to skip, left over from a
// partial UTF-8 character split over the end of the buffer from last
// time.
if (srcRemaining <= *state) {
*state -= srcRemaining;
*dstLen = 0;
return B_OK;
}
srcRemaining -= *state;
src += *state;
*state = 0;
while (true) {
if (srcRemaining <= 0 || dstRemaining <= 0)
break;
letter = *src;
if (letter < 0x80)
characterLength = 1; // Regular ASCII equivalent code.
else if (letter < 0xC0)
characterLength = 1; // Invalid in-between data byte 10xxxxxx.
else if (letter < 0xE0)
characterLength = 2;
else if (letter < 0xF0)
characterLength = 3;
else if (letter < 0xF8)
characterLength = 4;
else if (letter < 0xFC)
characterLength = 5;
else if (letter < 0xFE)
characterLength = 6;
else
characterLength = 1; // 0xFE and 0xFF are invalid in UTF-8.
if (letter < 0x80)
*dst++ = *src;
else
*dst++ = substitute;
dstRemaining--;
if (srcRemaining < characterLength) {
// Character split past the end of the buffer.
*state = characterLength - srcRemaining;
srcRemaining = 0;
} else {
src += characterLength;
srcRemaining -= characterLength;
}
}
// Update with the amounts used.
*srcLen = *srcLen - srcRemaining;
*dstLen = *dstLen - dstRemaining;
return B_OK;
}
errorCode = convert_from_utf8(dstEncoding, src, srcLen, dst, dstLen, state,
substitute);
if (errorCode != B_OK)
return errorCode;
if (dstEncoding != B_JIS_CONVERSION)
return B_OK;
// B_JIS_CONVERSION (ISO-2022-JP) works by shifting between different
// character subsets. For E-mail headers (and other uses), it needs to be
// switched back to ASCII at the end (otherwise the last character gets
// lost or other weird things happen in the headers). Note that we can't
// just append the escape code since the convert_from_utf8 "state" will be
// wrong. So we append an ASCII letter and throw it away, leaving just the
// escape code. Well, it actually switches to the Roman character set, not
// ASCII, but that should be OK.
tempDstLen = originalDstLen - *dstLen;
if (tempDstLen < 3) // Not enough space remaining in the output.
return B_OK; // Sort of an error, but we did convert the rest OK.
tempSrcLen = 1;
errorCode = convert_from_utf8(dstEncoding, "a", &tempSrcLen,
dst + *dstLen, &tempDstLen, state, substitute);
if (errorCode != B_OK)
return errorCode;
*dstLen += tempDstLen - 1 /* don't include the ASCII letter */;
return B_OK;
}
ssize_t
rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
{ {
char *head, *tail; char *head, *tail;
char *charset, *encoding, *end; char *charset, *encoding, *end;
@@ -384,7 +382,7 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
return -1; return -1;
char *string = *bufp; char *string = *bufp;
//---------Handle *&&^%*&^ non-RFC compliant, 8bit mail //---------Handle *&&^%*&^ non-RFC compliant, 8bit mail
if (handle_non_rfc2047_encoding(bufp,bufLen,&strLen)) if (handle_non_rfc2047_encoding(bufp,bufLen,&strLen))
return strLen; return strLen;
@@ -434,25 +432,25 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
end += 2; end += 2;
// find the charset this text is in now // find the charset this text is in now
size_t cLen = encoding - 1 - charset; size_t cLen = encoding - 1 - charset;
bool base64encoded = toupper(*encoding) == 'B'; bool base64encoded = toupper(*encoding) == 'B';
uint32 convert_id = B_MAIL_NULL_CONVERSION; uint32 convertID = B_MAIL_NULL_CONVERSION;
char charset_string[cLen+1]; char charsetName[cLen + 1];
memcpy(charset_string, charset, cLen); memcpy(charsetName, charset, cLen);
charset_string[cLen] = '\0'; charsetName[cLen] = '\0';
if (strcasecmp(charset_string, "us-ascii") == 0) { if (strcasecmp(charsetName, "us-ascii") == 0) {
convert_id = B_MAIL_US_ASCII_CONVERSION; convertID = B_MAIL_US_ASCII_CONVERSION;
} else if (strcasecmp(charset_string, "utf-8") == 0) { } else if (strcasecmp(charsetName, "utf-8") == 0) {
convert_id = B_MAIL_UTF8_CONVERSION; convertID = B_MAIL_UTF8_CONVERSION;
} else { } else {
const BCharacterSet * cs = BCharacterSetRoster::FindCharacterSetByName(charset_string); const BCharacterSet* charSet
if (cs != NULL) { = BCharacterSetRoster::FindCharacterSetByName(charsetName);
convert_id = cs->GetConversionID(); if (charSet != NULL) {
convertID = charSet->GetConversionID();
} }
} }
if (convert_id == B_MAIL_NULL_CONVERSION) if (convertID == B_MAIL_NULL_CONVERSION) {
{
// unidentified charset // unidentified charset
// what to do? doing nothing skips the encoded text; // what to do? doing nothing skips the encoded text;
// but we should keep it: we copy it to the output. // but we should keep it: we copy it to the output.
@@ -469,7 +467,7 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
// decode text, get decoded length (reducing xforms) // decode text, get decoded length (reducing xforms)
srcLen = !base64encoded ? decode_qp(src, src, srcLen, 1) srcLen = !base64encoded ? decode_qp(src, src, srcLen, 1)
: decode_base64(src, src, srcLen); : decode_base64(src, src, srcLen);
// allocate space for the converted text // allocate space for the converted text
int32 dstLen = end-string + *bufLen-strLen; int32 dstLen = end-string + *bufLen-strLen;
@@ -480,9 +478,9 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
// //
// do the conversion // do the conversion
// //
ret = mail_convert_to_utf8(convert_id, src, &cvLen, dst, &dstLen, &convState); ret = mail_convert_to_utf8(convertID, src, &cvLen, dst, &dstLen,
if (ret != B_OK) &convState);
{ if (ret != B_OK) {
// what to do? doing nothing skips the encoded text // what to do? doing nothing skips the encoded text
// but we should keep it: we copy it to the output. // but we should keep it: we copy it to the output.
@@ -524,10 +522,8 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
continue; continue;
} }
*/ */
else else {
{ if (dstLen > end-string) {
if (dstLen > end-string)
{
// copy the string forward... // copy the string forward...
memmove(string+dstLen, end, strLen - (end-head) + 1); memmove(string+dstLen, end, strLen - (end-head) + 1);
strLen += string+dstLen - end; strLen += string+dstLen - end;
@@ -553,7 +549,9 @@ _EXPORT ssize_t rfc2047_to_utf8(char **bufp, size_t *bufLen, size_t strLen)
} }
_EXPORT ssize_t utf8_to_rfc2047 (char **bufp, ssize_t length, uint32 charset, char encoding) { ssize_t
utf8_to_rfc2047 (char **bufp, ssize_t length, uint32 charset, char encoding)
{
struct word { struct word {
BString originalWord; BString originalWord;
BString convertedWord; BString convertedWord;
@@ -748,16 +746,15 @@ _EXPORT ssize_t utf8_to_rfc2047 (char **bufp, ssize_t length, uint32 charset, ch
} }
//==================================================================== void
FoldLineAtWhiteSpaceAndAddCRLF(BString &string)
void FoldLineAtWhiteSpaceAndAddCRLF (BString &string)
{ {
int inputLength = string.Length(); int inputLength = string.Length();
int lineStartIndex; int lineStartIndex;
const int maxLineLength = 78; // Doesn't include CRLF. const int maxLineLength = 78; // Doesn't include CRLF.
BString output; BString output;
int splitIndex; int splitIndex;
int tempIndex; int tempIndex;
lineStartIndex = 0; lineStartIndex = 0;
while (true) { while (true) {
@@ -827,21 +824,18 @@ void FoldLineAtWhiteSpaceAndAddCRLF (BString &string)
} }
//==================================================================== ssize_t
readfoldedline(FILE *file, char **buffer, size_t *buflen)
_EXPORT ssize_t readfoldedline(FILE *file, char **buffer, size_t *buflen)
{ {
ssize_t len = buflen && *buflen ? *buflen : 0; ssize_t len = buflen && *buflen ? *buflen : 0;
char * buf = buffer && *buffer ? *buffer : NULL; char * buf = buffer && *buffer ? *buffer : NULL;
ssize_t cnt = 0; // Number of characters currently in the buffer. ssize_t cnt = 0; // Number of characters currently in the buffer.
int c; int c;
while (true) while (true) {
{
// Make sure there is space in the buffer for two more characters (one // Make sure there is space in the buffer for two more characters (one
// for the next character, and one for the end of string NUL byte). // for the next character, and one for the end of string NUL byte).
if (buf == NULL || cnt + 2 >= len) if (buf == NULL || cnt + 2 >= len) {
{
char *temp = (char *)realloc(buf, len + 64); char *temp = (char *)realloc(buf, len + 64);
if (temp == NULL) { if (temp == NULL) {
// Out of memory, however existing buffer remains allocated. // Out of memory, however existing buffer remains allocated.
@@ -898,7 +892,6 @@ _EXPORT ssize_t readfoldedline(FILE *file, char **buffer, size_t *buflen)
} }
} }
if (buf != NULL && cnt >= 0) if (buf != NULL && cnt >= 0)
buf[cnt] = '\0'; buf[cnt] = '\0';
@@ -914,9 +907,8 @@ _EXPORT ssize_t readfoldedline(FILE *file, char **buffer, size_t *buflen)
} }
//==================================================================== ssize_t
readfoldedline(BPositionIO &in, char **buffer, size_t *buflen)
_EXPORT ssize_t readfoldedline(BPositionIO &in, char **buffer, size_t *buflen)
{ {
ssize_t len = buflen && *buflen ? *buflen : 0; ssize_t len = buflen && *buflen ? *buflen : 0;
char * buf = buffer && *buffer ? *buffer : NULL; char * buf = buffer && *buffer ? *buffer : NULL;
@@ -924,12 +916,10 @@ _EXPORT ssize_t readfoldedline(BPositionIO &in, char **buffer, size_t *buflen)
char c; char c;
status_t errorCode; status_t errorCode;
while (true) while (true) {
{
// Make sure there is space in the buffer for two more characters (one // Make sure there is space in the buffer for two more characters (one
// for the next character, and one for the end of string NUL byte). // for the next character, and one for the end of string NUL byte).
if (buf == NULL || cnt + 2 >= len) if (buf == NULL || cnt + 2 >= len) {
{
char *temp = (char *)realloc(buf, len + 64); char *temp = (char *)realloc(buf, len + 64);
if (temp == NULL) { if (temp == NULL) {
// Out of memory, however existing buffer remains allocated. // Out of memory, however existing buffer remains allocated.
@@ -1005,7 +995,7 @@ _EXPORT ssize_t readfoldedline(BPositionIO &in, char **buffer, size_t *buflen)
} }
_EXPORT ssize_t ssize_t
nextfoldedline(const char** header, char **buffer, size_t *buflen) nextfoldedline(const char** header, char **buffer, size_t *buflen)
{ {
ssize_t len = buflen && *buflen ? *buflen : 0; ssize_t len = buflen && *buflen ? *buflen : 0;
@@ -1085,7 +1075,7 @@ nextfoldedline(const char** header, char **buffer, size_t *buflen)
} }
_EXPORT void void
trim_white_space(BString &string) trim_white_space(BString &string)
{ {
int32 i; int32 i;
@@ -1105,12 +1095,11 @@ trim_white_space(BString &string)
} }
/** Tries to return a human-readable name from the specified /*! Tries to return a human-readable name from the specified
* header parameter (should be from "To:" or "From:"). header parameter (should be from "To:" or "From:").
* Tries to return the name rather than the eMail address. Tries to return the name rather than the eMail address.
*/ */
void
_EXPORT void
extract_address_name(BString &header) extract_address_name(BString &header)
{ {
BString name; BString name;
@@ -1198,19 +1187,13 @@ extract_address_name(BString &header)
} }
/*! Given a subject in a BString, remove the extraneous RE: re: and other stuff
// Given a subject in a BString, remove the extraneous RE: re: and other stuff to get down to the core subject string, which should be identical for all
// to get down to the core subject string, which should be identical for all messages posted about a topic. The input string is modified in place to
// messages posted about a topic. The input string is modified in place to become the output core subject string.
// become the output core subject string. */
void
static int32 gLocker = 0; SubjectToThread (BString &string)
static size_t gNsub = 1;
static re_pattern_buffer gRe;
static re_pattern_buffer *gRebuf = NULL;
static unsigned char gTranslation[256];
_EXPORT void SubjectToThread (BString &string)
{ {
// a regex that matches a non-ASCII UTF8 character: // a regex that matches a non-ASCII UTF8 character:
#define U8C \ #define U8C \
@@ -1230,8 +1213,7 @@ _EXPORT void SubjectToThread (BString &string)
"|^( +| *(\\<(\\w|" U8C "){2,3} *(\\[[^\\]]*\\])? *:)+ *)" \ "|^( +| *(\\<(\\w|" U8C "){2,3} *(\\[[^\\]]*\\])? *:)+ *)" \
"| *\\(fwd\\) *$" "| *\\(fwd\\) *$"
if (gRebuf == NULL && atomic_add(&gLocker,1) == 0) if (gRebuf == NULL && atomic_add(&gLocker, 1) == 0) {
{
// the idea is to compile the regexp once to speed up testing // the idea is to compile the regexp once to speed up testing
for (int i=0; i<256; ++i) gTranslation[i]=i; for (int i=0; i<256; ++i) gTranslation[i]=i;
@@ -1256,16 +1238,13 @@ _EXPORT void SubjectToThread (BString &string)
gRebuf = &gRe; gRebuf = &gRe;
else else
fprintf(stderr, "Failed to compile the regex: %s\n", err); fprintf(stderr, "Failed to compile the regex: %s\n", err);
} } else {
else
{
int32 tries = 200; int32 tries = 200;
while (gRebuf == NULL && tries-- > 0) while (gRebuf == NULL && tries-- > 0)
snooze(10000); snooze(10000);
} }
if (gRebuf) if (gRebuf) {
{
struct re_registers regs; struct re_registers regs;
// can't be static if this function is to be thread-safe // can't be static if this function is to be thread-safe
@@ -1273,11 +1252,8 @@ _EXPORT void SubjectToThread (BString &string)
regs.start = (regoff_t*)malloc(gNsub*sizeof(regoff_t)); regs.start = (regoff_t*)malloc(gNsub*sizeof(regoff_t));
regs.end = (regoff_t*)malloc(gNsub*sizeof(regoff_t)); regs.end = (regoff_t*)malloc(gNsub*sizeof(regoff_t));
for (int start=0; for (int start = 0; (start = re_search(gRebuf, string.String(),
(start=re_search(gRebuf, string.String(), string.Length(), string.Length(), 0, string.Length(), &regs)) >= 0;) {
0, string.Length(), &regs)) >= 0;
)
{
// //
// we found something // we found something
// //
@@ -1287,7 +1263,8 @@ _EXPORT void SubjectToThread (BString &string)
start = regs.start[2]; start = regs.start[2];
string.Remove(start,regs.end[0]-start); string.Remove(start,regs.end[0]-start);
if (start) string.Insert(' ',1,start); if (start)
string.Insert(' ',1,start);
// TODO: for some subjects this results in an endless loop, check // TODO: for some subjects this results in an endless loop, check
// why this happen. // why this happen.
@@ -1306,19 +1283,19 @@ _EXPORT void SubjectToThread (BString &string)
} }
/*! Converts a date to a time. Handles numeric time zones too, unlike
// Converts a date to a time. Handles numeric time zones too, unlike parsedate(). Returns -1 if it fails.
// parsedate. Returns -1 if it fails. */
time_t
_EXPORT time_t ParseDateWithTimeZone (const char *DateString) ParseDateWithTimeZone(const char *DateString)
{ {
time_t currentTime; time_t currentTime;
time_t dateAsTime; time_t dateAsTime;
char tempDateString [80]; char tempDateString[80];
char tempZoneString [6]; char tempZoneString[6];
time_t zoneDeltaTime; time_t zoneDeltaTime;
int zoneIndex; int zoneIndex;
char *zonePntr; char *zonePntr;
// See if we can remove the time zone portion. parsedate understands time // See if we can remove the time zone portion. parsedate understands time
// zone 3 letter names, but doesn't understand the numeric +9999 time zone // zone 3 letter names, but doesn't understand the numeric +9999 time zone
@@ -1349,7 +1326,7 @@ _EXPORT time_t ParseDateWithTimeZone (const char *DateString)
return -1; // Empty string. return -1; // Empty string.
} }
} }
// Look for a numeric time zone like Tue, 30 Dec 2003 05:01:40 +0000 // Look for a numeric time zone like Tue, 30 Dec 2003 05:01:40 +0000
for (zoneIndex = strlen (tempDateString); zoneIndex >= 0; zoneIndex--) for (zoneIndex = strlen (tempDateString); zoneIndex >= 0; zoneIndex--)
{ {
@@ -1390,10 +1367,9 @@ _EXPORT time_t ParseDateWithTimeZone (const char *DateString)
} }
/** Parses a mail header and fills the headers BMessage /*! Parses a mail header and fills the headers BMessage
*/ */
status_t
_EXPORT status_t
parse_header(BMessage &headers, BPositionIO &input) parse_header(BMessage &headers, BPositionIO &input)
{ {
char *buffer = NULL; char *buffer = NULL;
@@ -1417,10 +1393,12 @@ parse_header(BMessage &headers, BPositionIO &input)
// unified case for later fetch // unified case for later fetch
delimiter++; // Skip the colon. delimiter++; // Skip the colon.
while (isspace (*delimiter)) // Skip over leading white space and tabs.
delimiter++; // Skip over leading white space and tabs. To do: (comments in brackets). // TODO: (comments in brackets).
while (isspace(*delimiter))
delimiter++;
// ToDo: implement joining of multiple header tags (i.e. multiple "Cc:"s) // TODO: implement joining of multiple header tags (i.e. multiple "Cc:"s)
headers.AddString(header.String(), delimiter); headers.AddString(header.String(), delimiter);
} }
free(buffer); free(buffer);
@@ -1429,7 +1407,7 @@ parse_header(BMessage &headers, BPositionIO &input)
} }
_EXPORT status_t status_t
extract_from_header(const BString& header, const BString& field, extract_from_header(const BString& header, const BString& field,
BString& target) BString& target)
{ {
@@ -1440,7 +1418,7 @@ extract_from_header(const BString& header, const BString& field,
if (pos < 0) if (pos < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
fieldEndPos = pos + field.Length(); fieldEndPos = pos + field.Length();
if (pos != 0 && header.ByteAt(pos - 1) != '\n') if (pos != 0 && header.ByteAt(pos - 1) != '\n')
continue; continue;
if (header.ByteAt(fieldEndPos) == ':') if (header.ByteAt(fieldEndPos) == ':')
@@ -1486,7 +1464,7 @@ extract_address(BString &address)
int32 first; int32 first;
// first, remove all quoted text // first, remove all quoted text
if ((first = address.FindFirst('"')) >= 0) { if ((first = address.FindFirst('"')) >= 0) {
int32 last = first + 1; int32 last = first + 1;
while (string[last] && string[last] != '"') while (string[last] && string[last] != '"')