00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "r_message_base.h"
00024 #include "record-internal.h"
00025 #include "protostructs.h"
00026 #include "data.h"
00027 #include "time.h"
00028 #include "endian.h"
00029 #include "iconv.h"
00030 #include <ostream>
00031 #include <iomanip>
00032 #include <stdexcept>
00033
00034 #define __DEBUG_MODE__
00035 #include "debug.h"
00036
00037 using namespace std;
00038 using namespace Barry::Protocol;
00039
00040 namespace Barry {
00041
00042
00043
00044
00045
00046
00047 #define MBFC_TO 0x01 // can occur multiple times
00048 #define MBFC_CC 0x02 // ditto
00049 #define MBFC_BCC 0x03 // ditto
00050 #define MBFC_SENDER 0x04
00051 #define MBFC_FROM 0x05
00052 #define MBFC_REPLY_TO 0x06
00053 #define MBFC_SUBJECT 0x0b
00054 #define MBFC_BODY 0x0c
00055 #define MBFC_REPLY_UNKNOWN 0x12 // This shows up as 0x00 on replies
00056
00057 #define MBFC_ATTACHMENT 0x16
00058 #define MBFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber
00059 #define MBFC_END 0xffff
00060
00061 #define PRIORITY_MASK 0x003f
00062 #define PRIORITY_HIGH 0x0008
00063 #define PRIORITY_LOW 0x0002
00064
00065 #define SENSITIVE_MASK 0xff80
00066 #define SENSITIVE_CONFIDENTIAL 0x0100
00067 #define SENSITIVE_PERSONAL 0x0080
00068 #define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
00069
00070 #define MESSAGE_READ 0x0800
00071 #define MESSAGE_REPLY 0x0001
00072 #define MESSAGE_SAVED 0x0002
00073 #define MESSAGE_FORWARD 0x0008
00074 #define MESSAGE_TRUNCATED 0x0020
00075 #define MESSAGE_SAVED_DELETED 0x0080
00076
00077 static FieldLink<MessageBase> MessageBaseFieldLinks[] = {
00078 { MBFC_TO, "To", 0, 0, 0, &MessageBase::To, 0, 0, 0, true },
00079 { MBFC_CC, "Cc", 0, 0, 0, &MessageBase::Cc, 0, 0, 0, true },
00080 { MBFC_BCC, "Bcc", 0, 0, 0, &MessageBase::Bcc, 0, 0, 0, true },
00081 { MBFC_SENDER, "Sender", 0, 0, 0, &MessageBase::Sender, 0, 0, 0, true },
00082 { MBFC_FROM, "From", 0, 0, 0, &MessageBase::From, 0, 0, 0, true },
00083 { MBFC_REPLY_TO, "ReplyTo", 0, 0, 0, &MessageBase::ReplyTo, 0, 0, 0, true },
00084 { MBFC_SUBJECT, "Subject", 0, 0, &MessageBase::Subject, 0, 0, 0, 0, true },
00085 { MBFC_BODY, "Body", 0, 0, &MessageBase::Body, 0, 0, 0, 0, true },
00086 { MBFC_ATTACHMENT, "Attachment", 0, 0, &MessageBase::Attachment, 0, 0, 0, 0, false },
00087 { MBFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
00088 };
00089
00090 MessageBase::MessageBase()
00091 {
00092 Clear();
00093 }
00094
00095 MessageBase::~MessageBase()
00096 {
00097 }
00098
00099 const unsigned char* MessageBase::ParseField(const unsigned char *begin,
00100 const unsigned char *end,
00101 const IConverter *ic)
00102 {
00103 const CommonField *field = (const CommonField *) begin;
00104
00105
00106 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00107 if( begin > end )
00108 return begin;
00109
00110 if( !btohs(field->size) )
00111 return begin;
00112
00113
00114 for( FieldLink<MessageBase> *b = MessageBaseFieldLinks;
00115 b->type != MBFC_END;
00116 b++ )
00117 {
00118 if( b->type == field->type ) {
00119 if( b->strMember ) {
00120
00121 std::string &s = this->*(b->strMember);
00122 s = ParseFieldString(field);
00123 if( b->iconvNeeded && ic )
00124 s = ic->FromBB(s);
00125 return begin;
00126 }
00127 else if( b->addrMember ) {
00128
00129
00130 const char *fa = (const char*)field->u.addr.addr;
00131 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
00132
00133
00134
00135
00136 EmailAddress a;
00137 a.Name = dual.c_str();
00138
00139
00140
00141 a.Email = dual.c_str() + a.Name.size() + 1;
00142
00143
00144 if( a.size() ) {
00145
00146 if( b->iconvNeeded && ic ) {
00147 a.Name = ic->FromBB(a.Name);
00148 a.Email = ic->FromBB(a.Email);
00149 }
00150
00151 EmailAddressList &al = this->*(b->addrMember);
00152 al.push_back(a);
00153 }
00154
00155 return begin;
00156 }
00157 }
00158 }
00159
00160
00161 char swallow;
00162 switch( field->type )
00163 {
00164 case MBFC_RECORDID:
00165 MessageRecordId = btohl(field->u.uint32);
00166 return begin;
00167
00168 case MBFC_REPLY_UNKNOWN:
00169 swallow = field->u.raw[0];
00170 return begin;
00171 }
00172
00173
00174 UnknownField uf;
00175 uf.type = field->type;
00176 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00177 Unknowns.push_back(uf);
00178
00179 return begin;
00180 }
00181
00182 uint8_t MessageBase::GetRecType() const
00183 {
00184 throw std::logic_error("MessageBase::GetRecType() called, and not supported by the USB protocol. Should never get called.");
00185 }
00186
00187 uint32_t MessageBase::GetUniqueId() const
00188 {
00189 throw std::logic_error("MessageBase::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
00190 }
00191
00192 void MessageBase::ParseHeader(const Data &data, size_t &offset)
00193 {
00194 Protocol::CheckSize(data, offset + MESSAGE_RECORD_HEADER_SIZE);
00195
00196 MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
00197
00198
00199 Priority = NormalPriority;
00200
00201 uint16_t priority = btohs(mr->priority);
00202 if( priority & PRIORITY_MASK ) {
00203 if( priority & PRIORITY_HIGH ) {
00204 Priority = HighPriority;
00205 }
00206 else if( priority & PRIORITY_LOW ) {
00207 Priority = LowPriority;
00208 }
00209 else
00210 Priority = UnknownPriority;
00211 }
00212
00213
00214 Sensitivity = NormalSensitivity;
00215
00216 if( priority & SENSITIVE_MASK ) {
00217 if(( priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
00218 Sensitivity = Confidential;
00219 }
00220 else if(( priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
00221 Sensitivity = Private;
00222 }
00223 else if(( priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
00224 Sensitivity = Personal;
00225 }
00226 else
00227 Sensitivity = UnknownSensitivity;
00228 }
00229
00230
00231
00232
00233 if( mr->inReplyTo )
00234 MessageReplyTo = btohl(mr->inReplyTo);
00235
00236
00237 uint32_t flags = btohl(mr->flags);
00238
00239
00240
00241 if( !( flags & MESSAGE_READ ))
00242 MessageRead = true;
00243
00244
00245
00246 if(( flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
00247 MessageReply = true;
00248
00249
00250
00251
00252 if( !( flags & MESSAGE_TRUNCATED ))
00253 MessageTruncated = true;
00254
00255
00256 if( !( flags & MESSAGE_SAVED ))
00257 MessageSaved = true;
00258
00259
00260 if( !( flags & MESSAGE_SAVED_DELETED ))
00261 MessageSavedDeleted = true;
00262
00263 MessageDateSent = Message2Time(mr->dateSent, mr->timeSent);
00264 MessageDateReceived = Message2Time(mr->dateReceived, mr->timeReceived);
00265
00266 offset += MESSAGE_RECORD_HEADER_SIZE;
00267 }
00268
00269 void MessageBase::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00270 {
00271 const unsigned char *finish = ParseCommonFields(*this,
00272 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00273 offset += finish - (data.GetData() + offset);
00274 }
00275
00276 void MessageBase::BuildHeader(Data &data, size_t &offset) const
00277 {
00278 throw std::logic_error("MessageBase::BuildHeader not yet implemented");
00279 }
00280
00281 void MessageBase::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00282 {
00283 throw std::logic_error("MessageBase::BuildFields not yet implemented");
00284 }
00285
00286 void MessageBase::Clear()
00287 {
00288 From.clear();
00289 To.clear();
00290 Cc.clear();
00291 Bcc.clear();
00292 Sender.clear();
00293 ReplyTo.clear();
00294
00295 Subject.clear();
00296 Body.clear();
00297 Attachment.clear();
00298
00299 MessageRecordId = 0;
00300 MessageReplyTo = 0;
00301 MessageDateSent = 0;
00302 MessageDateReceived = 0;
00303 MessageTruncated = false;
00304 MessageRead = false;
00305 MessageReply = false;
00306 MessageSaved = false;
00307 MessageSavedDeleted = false;
00308
00309 Priority = NormalPriority;
00310 Sensitivity = NormalSensitivity;
00311
00312 Unknowns.clear();
00313 }
00314
00315 std::string MessageBase::SimpleFromAddress() const
00316 {
00317 if( From.size() ) {
00318
00319 std::string ret;
00320 for( size_t i = 0; i < From[0].Email.size(); i++ )
00321 if( From[0].Email[i] != ' ' )
00322 ret += From[0].Email[i];
00323
00324 return ret;
00325 }
00326 else {
00327 return "unknown";
00328 }
00329 }
00330
00331
00332 void MessageBase::Dump(std::ostream &os) const
00333 {
00334 static const char *Importance[] =
00335 { "Low", "Normal", "High", "Unknown Priority" };
00336 static const char *SensitivityString[] =
00337 { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
00338
00339 os << "From " << SimpleFromAddress() << " " << ctime( &MessageDateReceived );
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
00350
00351 if( MessageReplyTo )
00352 os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
00353 if( MessageSaved )
00354 os << "X-Message-Status: Saved\n";
00355 else if( MessageRead )
00356 os << "Message Status: Opened\n";
00357 if( Priority != NormalPriority )
00358 os << "Importance: " << Importance[Priority] << "\n";
00359 if( Sensitivity != NormalSensitivity )
00360 os << "Sensitivity: " << SensitivityString[Sensitivity] << "\n";
00361 os << "Date: " << ctime(&MessageDateSent);
00362 if( From.size() )
00363 os << "From: " << From[0] << "\n";
00364 if( To.size() )
00365 os << "To: " << To << "\n";
00366 if( Cc.size() )
00367 os << "Cc: " << Cc << "\n";
00368 if( Bcc.size() )
00369 os << "Bcc: " << Bcc << "\n";
00370 if( Sender.size() )
00371 os << "Sender: " << Sender << "\n";
00372 if( ReplyTo.size())
00373 os << "Reply To: " << ReplyTo << "\n";
00374 if( Subject.size() )
00375 os << "Subject: " << Subject << "\n";
00376 os << "\n";
00377 for( std::string::const_iterator i = Body.begin();
00378 i != Body.end() && *i;
00379 i++)
00380 {
00381 if( *i == '\r' )
00382 os << '\n';
00383 else
00384 os << *i;
00385 }
00386 os << "\n";
00387
00388 if( Attachment.size() )
00389 os << "Attachments: " << Data(Attachment.data(), Attachment.size()) << "\n";
00390
00391 os << Unknowns;
00392 os << "\n\n";
00393 }
00394
00395 bool MessageBase::operator<(const MessageBase &other) const
00396 {
00397
00398
00399
00400 time_t date = std::max(MessageDateSent, MessageDateReceived);
00401 time_t odate = std::max(other.MessageDateSent, other.MessageDateReceived);
00402
00403 if( date != odate )
00404 return date < odate;
00405
00406 return Subject < other.Subject;
00407 }
00408
00409 }
00410