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 Message::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
55 #define MFC_SUBJECT 0x0b
57 #define MFC_END 0xffff
59 FieldLink
<Message
> MessageFieldLinks
[] = {
60 { MFC_TO
, "To", 0, 0, 0, &Message::To
, 0 },
61 { MFC_FROM
, "From", 0, 0, 0, &Message::From
, 0 },
62 { MFC_SUBJECT
, "Subject", 0, 0, &Message::Subject
, 0, 0 },
63 { MFC_BODY
, "Body", 0, 0, &Message::Body
, 0, 0 },
64 { MFC_END
, "End of List",0, 0, 0, 0, 0 }
75 const unsigned char* Message::ParseField(const unsigned char *begin
,
76 const unsigned char *end
)
78 const CommonField
*field
= (const CommonField
*) begin
;
80 // advance and check size
81 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
82 if( begin
> end
) // if begin==end, we are ok
85 if( !btohs(field
->size
) ) // if field has no size, something's up
88 // cycle through the type table
89 for( FieldLink
<Message
> *b
= MessageFieldLinks
;
93 if( b
->type
== field
->type
) {
95 // parse regular string
96 std::string
&s
= this->*(b
->strMember
);
97 s
.assign((const char *)field
->u
.raw
, btohs(field
->size
)-1);
98 return begin
; // done!
100 else if( b
->addrMember
) {
101 // parse email address
102 // get dual name+addr string first
103 const char *fa
= (const char*)field
->u
.addr
.addr
;
104 std::string
dual(fa
, btohs(field
->size
) - sizeof(field
->u
.addr
.unknown
));
106 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
107 Address
&a
= this->*(b
->addrMember
);
108 a
.Name
= dual
.c_str();
110 // assign second string, using first size as starting point
111 a
.Email
= dual
.c_str() + a
.Name
.size() + 1;
119 uint8_t Message::GetRecType() const
121 throw std::logic_error("Message::GetRecType() called, and not supported by the USB protocol. Should never get called.");
124 // empty API, not required by protocol
125 uint32_t Message::GetUniqueId() const
127 throw std::logic_error("Message::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
130 // empty API, not required by protocol
131 void Message::SetIds(uint8_t Type
, uint32_t Id
)
133 // accept it without complaining, just do nothing
136 void Message::ParseHeader(const Data
&data
, size_t &offset
)
138 // we skip the "header" since we don't know what to do with it yet
139 offset
+= MESSAGE_RECORD_HEADER_SIZE
;
142 void Message::ParseFields(const Data
&data
, size_t &offset
)
144 const unsigned char *finish
= ParseCommonFields(*this,
145 data
.GetData() + offset
, data
.GetData() + data
.GetSize());
146 offset
+= finish
- (data
.GetData() + offset
);
149 void Message::BuildHeader(Data
&data
, size_t &offset
) const
151 throw std::logic_error("Message::BuildHeader not yet implemented");
154 void Message::BuildFields(Data
&data
, size_t &offset
) const
156 throw std::logic_error("Message::BuildFields not yet implemented");
159 void Message::Clear()
171 // dump message in mbox format
172 void Message::Dump(std::ostream
&os
) const
174 // FIXME - use current time until we figure out the date headers
175 time_t fixme
= time(NULL
);
177 os
<< "From " << (From
.Email
.size() ? From
.Email
.c_str() : "unknown")
178 << " " << ctime(&fixme
);
179 os
<< "Date: " << ctime(&fixme
);
180 os
<< "From: " << From
<< "\n";
181 if( To
.Email
.size() )
182 os
<< "To: " << To
<< "\n";
183 if( Cc
.Email
.size() )
184 os
<< "Cc: " << Cc
<< "\n";
186 os
<< "Subject: " << Subject
<< "\n";
188 for( std::string::const_iterator i
= Body
.begin();
189 i
!= Body
.end() && *i
;