3 /// Blackberry database record parser class for email records.
7 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "r_message.h"
23 #include "record-internal.h"
25 #include "protostructs.h"
35 #define __DEBUG_MODE__
39 using namespace Barry::Protocol
;
43 std::ostream
& operator<<(std::ostream
&os
, const Address
&msga
) {
44 os
<< msga
.Name
.c_str() << " <" << msga
.Email
.c_str() << ">";
48 ///////////////////////////////////////////////////////////////////////////////
52 // Email / message field codes
53 #define MFC_TO 0x01 // can occur multiple times
54 #define MFC_CC 0x02 // ditto
55 #define MFC_BCC 0x03 // ditto
56 #define MFC_SENDER 0x04
58 #define MFC_REPLY_TO 0x06
59 #define MFC_SUBJECT 0x0b
61 #define MFC_ATTACHMENT 0x16
62 #define MFC_END 0xffff
64 FieldLink
<Message
> MessageFieldLinks
[] = {
65 { MFC_TO
, "To", 0, 0, 0, &Message::To
, 0 },
66 { MFC_CC
, "Cc", 0, 0, 0, &Message::Cc
, 0 },
67 { MFC_BCC
, "Bcc", 0, 0, 0, &Message::Bcc
, 0 },
68 { MFC_SENDER
, "Sender", 0, 0, 0, &Message::Sender
, 0 },
69 { MFC_FROM
, "From", 0, 0, 0, &Message::From
, 0 },
70 { MFC_REPLY_TO
, "ReplyTo", 0, 0, 0, &Message::ReplyTo
, 0 },
71 { MFC_SUBJECT
, "Subject", 0, 0, &Message::Subject
, 0, 0 },
72 { MFC_BODY
, "Body", 0, 0, &Message::Body
, 0, 0 },
73 { MFC_ATTACHMENT
, "Attachment", 0, 0, &Message::Attachment
, 0, 0 },
74 { MFC_END
, "End of List", 0, 0, 0, 0, 0 }
85 const unsigned char* Message::ParseField(const unsigned char *begin
,
86 const unsigned char *end
)
88 const CommonField
*field
= (const CommonField
*) begin
;
90 // advance and check size
91 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
92 if( begin
> end
) // if begin==end, we are ok
95 if( !btohs(field
->size
) ) // if field has no size, something's up
98 // cycle through the type table
99 for( FieldLink
<Message
> *b
= MessageFieldLinks
;
103 if( b
->type
== field
->type
) {
105 // parse regular string
106 std::string
&s
= this->*(b
->strMember
);
107 s
.assign((const char *)field
->u
.raw
, btohs(field
->size
)-1);
108 return begin
; // done!
110 else if( b
->addrMember
) {
111 // parse email address
112 // get dual name+addr string first
113 const char *fa
= (const char*)field
->u
.addr
.addr
;
114 std::string
dual(fa
, btohs(field
->size
) - sizeof(field
->u
.addr
.unknown
));
116 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
117 Address
&a
= this->*(b
->addrMember
);
118 a
.Name
= dual
.c_str();
120 // assign second string, using first size as starting point
121 a
.Email
= dual
.c_str() + a
.Name
.size() + 1;
127 // if still not handled, add to the Unknowns list
129 uf
.type
= field
->type
;
130 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
131 Unknowns
.push_back(uf
);
136 uint8_t Message::GetRecType() const
138 throw std::logic_error("Message::GetRecType() called, and not supported by the USB protocol. Should never get called.");
141 // empty API, not required by protocol
142 uint32_t Message::GetUniqueId() const
144 throw std::logic_error("Message::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
147 // empty API, not required by protocol
148 void Message::SetIds(uint8_t Type
, uint32_t Id
)
150 // accept it without complaining, just do nothing
153 void Message::ParseHeader(const Data
&data
, size_t &offset
)
155 // we skip the "header" since we don't know what to do with it yet
156 offset
+= MESSAGE_RECORD_HEADER_SIZE
;
159 void Message::ParseFields(const Data
&data
, size_t &offset
)
161 const unsigned char *finish
= ParseCommonFields(*this,
162 data
.GetData() + offset
, data
.GetData() + data
.GetSize());
163 offset
+= finish
- (data
.GetData() + offset
);
166 void Message::BuildHeader(Data
&data
, size_t &offset
) const
168 throw std::logic_error("Message::BuildHeader not yet implemented");
171 void Message::BuildFields(Data
&data
, size_t &offset
) const
173 throw std::logic_error("Message::BuildFields not yet implemented");
176 void Message::Clear()
191 // dump message in mbox format
192 void Message::Dump(std::ostream
&os
) const
194 // FIXME - use current time until we figure out the date headers
195 time_t fixme
= time(NULL
);
197 os
<< "From " << (From
.Email
.size() ? From
.Email
.c_str() : "unknown")
198 << " " << ctime(&fixme
);
199 os
<< "Date: " << ctime(&fixme
);
200 os
<< "From: " << From
<< "\n";
201 if( To
.Email
.size() )
202 os
<< "To: " << To
<< "\n";
203 if( Cc
.Email
.size() )
204 os
<< "Cc: " << Cc
<< "\n";
205 if( Bcc
.Email
.size() )
206 os
<< "Bcc: " << Bcc
<< "\n";
207 if( Sender
.Email
.size() )
208 os
<< "Sender: " << Sender
<< "\n";
209 if( ReplyTo
.Email
.size())
210 os
<< "Reply To: " << ReplyTo
<< "\n";
212 os
<< "Subject: " << Subject
<< "\n";
214 for( std::string::const_iterator i
= Body
.begin();
215 i
!= Body
.end() && *i
;
224 if( Attachment
.size() )
225 os
<< "Attachments: " << Attachment
<< "\n";