2 /// \file r_saved_message.cc
3 /// Blackberry database record parser class for saved email
8 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
9 Copyright (C) 2005-2007, Brian Edginton (edge@edginton.net)
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 See the GNU General Public License in the COPYING file at the
21 root directory of this project for more details.
24 #include "r_saved_message.h"
25 #include "record-internal.h"
27 #include "protostructs.h"
37 #define __DEBUG_MODE__
41 using namespace Barry::Protocol
;
45 ///////////////////////////////////////////////////////////////////////////////
49 // Email / message field codes
50 #define SEMFC_TO 0x01 // can occur multiple times
51 #define SEMFC_CC 0x02 // ditto
52 #define SEMFC_BCC 0x03 // ditto
53 #define SEMFC_SENDER 0x04
54 #define SEMFC_FROM 0x05
55 #define SEMFC_REPLY_TO 0x06
56 #define SEMFC_SUBJECT 0x0b
57 #define SEMFC_BODY 0x0c
58 #define SEMFC_ATTACHMENT 0x16
59 #define SEMFC_RECORDID 0x4b
60 #define SEMFC_END 0xffff
62 FieldLink
<SavedMessage
> SavedMessageFieldLinks
[] = {
63 { SEMFC_TO
, "To", 0, 0, 0, &SavedMessage::To
, 0 },
64 { SEMFC_CC
, "Cc", 0, 0, 0, &SavedMessage::Cc
, 0 },
65 { SEMFC_BCC
, "Bcc", 0, 0, 0, &SavedMessage::Bcc
, 0 },
66 { SEMFC_SENDER
, "Sender", 0, 0, 0, &SavedMessage::Sender
, 0 },
67 { SEMFC_FROM
, "From", 0, 0, 0, &SavedMessage::From
, 0 },
68 { SEMFC_REPLY_TO
, "ReplyTo", 0, 0, 0, &SavedMessage::ReplyTo
, 0 },
69 { SEMFC_SUBJECT
, "Subject", 0, 0, &SavedMessage::Subject
, 0, 0 },
70 { SEMFC_BODY
, "Body", 0, 0, &SavedMessage::Body
, 0, 0 },
71 { SEMFC_ATTACHMENT
, "Attachment", 0, 0, &SavedMessage::Attachment
, 0, 0 },
72 { SEMFC_END
, "End of List", 0, 0, 0, 0, 0 }
75 SavedMessage::SavedMessage()
80 SavedMessage::~SavedMessage()
84 const unsigned char* SavedMessage::ParseField(const unsigned char *begin
,
85 const unsigned char *end
)
87 const CommonField
*field
= (const CommonField
*) begin
;
89 // advance and check size
90 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
91 if( begin
> end
) // if begin==end, we are ok
94 if( !btohs(field
->size
) ) // if field has no size, something's up
97 // cycle through the type table
98 for( FieldLink
<SavedMessage
> *b
= SavedMessageFieldLinks
;
102 if( b
->type
== field
->type
) {
104 // parse regular string
105 std::string
&s
= this->*(b
->strMember
);
106 s
.assign((const char *)field
->u
.raw
, btohs(field
->size
)-1);
107 return begin
; // done!
109 else if( b
->addrMember
) {
110 // parse email address
111 // get dual name+addr string first
112 const char *fa
= (const char*)field
->u
.addr
.addr
;
113 std::string
dual(fa
, btohs(field
->size
) - sizeof(field
->u
.addr
.unknown
));
115 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
116 Address
&a
= this->*(b
->addrMember
);
117 a
.Name
= dual
.c_str();
119 // assign second string, using first size as starting point
120 a
.Email
= dual
.c_str() + a
.Name
.size() + 1;
126 // handle special cases
127 switch( field
->type
)
130 MessageRecordId
= field
->u
.uint32
;
134 // if still not handled, add to the Unknowns list
136 uf
.type
= field
->type
;
137 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
138 Unknowns
.push_back(uf
);
143 void SavedMessage::ParseHeader(const Data
&data
, size_t &offset
)
145 // we skip the "header" since we don't know what to do with it yet
146 // FIXME - we are using a Message (email) record header size
147 // for a PIN Message record... this is not necessarily guaranteed
148 // to be the same... someday we could use some more info on
149 // the message record header and pin message record header
150 offset
+= MESSAGE_RECORD_HEADER_SIZE
;
153 void SavedMessage::ParseFields(const Data
&data
, size_t &offset
)
155 const unsigned char *finish
= ParseCommonFields(*this,
156 data
.GetData() + offset
, data
.GetData() + data
.GetSize());
157 offset
+= finish
- (data
.GetData() + offset
);
160 void SavedMessage::BuildHeader(Data
&data
, size_t &offset
) const
162 throw std::logic_error("SavedMessage::BuildHeader not yet implemented");
165 void SavedMessage::BuildFields(Data
&data
, size_t &offset
) const
167 throw std::logic_error("SavedMessage::BuildFields not yet implemented");
170 void SavedMessage::Clear()
187 // dump message in mbox format
188 void SavedMessage::Dump(std::ostream
&os
) const
190 // FIXME - use current time until we figure out the date headers
191 time_t fixme
= time(NULL
);
193 os
<< "From " << (From
.Email
.size() ? From
.Email
.c_str() : "unknown")
194 << " " << ctime(&fixme
);
195 os
<< "X-Record-ID: (0x" << std::hex
<< MessageRecordId
<< ")\n";
196 os
<< "Date: " << ctime(&fixme
);
197 os
<< "From: " << From
<< "\n";
198 if( To
.Email
.size() )
199 os
<< "To: " << To
<< "\n";
200 if( Cc
.Email
.size() )
201 os
<< "Cc: " << Cc
<< "\n";
202 if( Bcc
.Email
.size() )
203 os
<< "Bcc: " << Bcc
<< "\n";
204 if( Sender
.Email
.size() )
205 os
<< "Sender: " << Sender
<< "\n";
206 if( ReplyTo
.Email
.size())
207 os
<< "Reply To: " << ReplyTo
<< "\n";
209 os
<< "Subject: " << Subject
<< "\n";
211 for( std::string::const_iterator i
= Body
.begin();
212 i
!= Body
.end() && *i
;
221 if( Attachment
.size() )
222 os
<< "Attachments: " << Attachment
<< "\n";