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 #include "ios_state.h"
00034
00035 #define __DEBUG_MODE__
00036 #include "debug.h"
00037
00038 using namespace std;
00039 using namespace Barry::Protocol;
00040
00041 namespace Barry {
00042
00043
00044
00045
00046
00047
00048 #define MBFC_TO 0x01 // can occur multiple times
00049 #define MBFC_CC 0x02 // ditto
00050 #define MBFC_BCC 0x03 // ditto
00051 #define MBFC_SENDER 0x04
00052 #define MBFC_FROM 0x05
00053 #define MBFC_REPLY_TO 0x06
00054 #define MBFC_SUBJECT 0x0b
00055 #define MBFC_BODY 0x0c
00056 #define MBFC_REPLY_UNKNOWN 0x12 // This shows up as 0x00 on replies
00057
00058 #define MBFC_ATTACHMENT 0x16
00059 #define MBFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber
00060 #define MBFC_END 0xffff
00061
00062 #define PRIORITY_MASK 0x003f
00063 #define PRIORITY_HIGH 0x0008
00064 #define PRIORITY_LOW 0x0002
00065
00066 #define SENSITIVE_MASK 0xff80
00067 #define SENSITIVE_CONFIDENTIAL 0x0100
00068 #define SENSITIVE_PERSONAL 0x0080
00069 #define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
00070
00071 #define MESSAGE_READ 0x0800
00072 #define MESSAGE_REPLY 0x0001
00073 #define MESSAGE_SAVED 0x0002
00074 #define MESSAGE_FORWARD 0x0008
00075 #define MESSAGE_TRUNCATED 0x0020
00076 #define MESSAGE_SAVED_DELETED 0x0080
00077
00078 static FieldLink<MessageBase> MessageBaseFieldLinks[] = {
00079 { MBFC_TO, "To", 0, 0, 0, &MessageBase::To, 0, 0, 0, true },
00080 { MBFC_CC, "Cc", 0, 0, 0, &MessageBase::Cc, 0, 0, 0, true },
00081 { MBFC_BCC, "Bcc", 0, 0, 0, &MessageBase::Bcc, 0, 0, 0, true },
00082 { MBFC_SENDER, "Sender", 0, 0, 0, &MessageBase::Sender, 0, 0, 0, true },
00083 { MBFC_FROM, "From", 0, 0, 0, &MessageBase::From, 0, 0, 0, true },
00084 { MBFC_REPLY_TO, "ReplyTo", 0, 0, 0, &MessageBase::ReplyTo, 0, 0, 0, true },
00085 { MBFC_SUBJECT, "Subject", 0, 0, &MessageBase::Subject, 0, 0, 0, 0, true },
00086 { MBFC_BODY, "Body", 0, 0, &MessageBase::Body, 0, 0, 0, 0, true },
00087 { MBFC_ATTACHMENT, "Attachment", 0, 0, &MessageBase::Attachment, 0, 0, 0, 0, false },
00088 { MBFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
00089 };
00090
00091 MessageBase::MessageBase()
00092 {
00093 Clear();
00094 }
00095
00096 MessageBase::~MessageBase()
00097 {
00098 }
00099
00100 const unsigned char* MessageBase::ParseField(const unsigned char *begin,
00101 const unsigned char *end,
00102 const IConverter *ic)
00103 {
00104 const CommonField *field = (const CommonField *) begin;
00105
00106
00107 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00108 if( begin > end )
00109 return begin;
00110
00111 if( !btohs(field->size) )
00112 return begin;
00113
00114
00115 for( FieldLink<MessageBase> *b = MessageBaseFieldLinks;
00116 b->type != MBFC_END;
00117 b++ )
00118 {
00119 if( b->type == field->type ) {
00120 if( b->strMember ) {
00121
00122 std::string &s = this->*(b->strMember);
00123 s = ParseFieldString(field);
00124 if( b->iconvNeeded && ic )
00125 s = ic->FromBB(s);
00126 return begin;
00127 }
00128 else if( b->addrMember ) {
00129
00130
00131 const char *fa = (const char*)field->u.addr.addr;
00132 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
00133
00134
00135
00136
00137 EmailAddress a;
00138 a.Name = dual.c_str();
00139
00140
00141
00142 a.Email = dual.c_str() + a.Name.size() + 1;
00143
00144
00145 if( a.size() ) {
00146
00147 if( b->iconvNeeded && ic ) {
00148 a.Name = ic->FromBB(a.Name);
00149 a.Email = ic->FromBB(a.Email);
00150 }
00151
00152 EmailAddressList &al = this->*(b->addrMember);
00153 al.push_back(a);
00154 }
00155
00156 return begin;
00157 }
00158 }
00159 }
00160
00161
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
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 void MessageBase::ParseHeader(const Data &data, size_t &offset)
00183 {
00184 const unsigned char *begin = data.GetData();
00185 const unsigned char *end = data.GetData() + data.GetSize();
00186
00187 begin += offset + MESSAGE_RECORD_HEADER_SIZE;
00188 if( begin > end )
00189 return;
00190
00191 MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
00192
00193
00194 Priority = NormalPriority;
00195
00196 uint16_t priority = btohs(mr->priority);
00197 if( priority & PRIORITY_MASK ) {
00198 if( priority & PRIORITY_HIGH ) {
00199 Priority = HighPriority;
00200 }
00201 else if( priority & PRIORITY_LOW ) {
00202 Priority = LowPriority;
00203 }
00204 else
00205 Priority = UnknownPriority;
00206 }
00207
00208
00209 Sensitivity = NormalSensitivity;
00210
00211 if( priority & SENSITIVE_MASK ) {
00212 if(( priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
00213 Sensitivity = Confidential;
00214 }
00215 else if(( priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
00216 Sensitivity = Private;
00217 }
00218 else if(( priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
00219 Sensitivity = Personal;
00220 }
00221 else
00222 Sensitivity = UnknownSensitivity;
00223 }
00224
00225
00226
00227
00228 if( mr->inReplyTo )
00229 MessageReplyTo = btohl(mr->inReplyTo);
00230
00231
00232 uint32_t flags = btohl(mr->flags);
00233
00234
00235
00236 if( !( flags & MESSAGE_READ ))
00237 MessageRead = true;
00238
00239
00240
00241 if(( flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
00242 MessageReply = true;
00243
00244
00245
00246
00247 if( !( flags & MESSAGE_TRUNCATED ))
00248 MessageTruncated = true;
00249
00250
00251 if( !( flags & MESSAGE_SAVED ))
00252 MessageSaved = true;
00253
00254
00255 if( !( flags & MESSAGE_SAVED_DELETED ))
00256 MessageSavedDeleted = true;
00257
00258 MessageDateSent.Time = Message2Time(mr->dateSent, mr->timeSent);
00259 MessageDateReceived.Time = Message2Time(mr->dateReceived, mr->timeReceived);
00260
00261 offset += MESSAGE_RECORD_HEADER_SIZE;
00262 }
00263
00264 void MessageBase::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00265 {
00266 const unsigned char *finish = ParseCommonFields(*this,
00267 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00268 offset += finish - (data.GetData() + offset);
00269 }
00270
00271 void MessageBase::Validate() const
00272 {
00273 }
00274
00275 void MessageBase::BuildHeader(Data &data, size_t &offset) const
00276 {
00277 throw std::logic_error("MessageBase::BuildHeader not yet implemented");
00278 }
00279
00280 void MessageBase::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00281 {
00282 throw std::logic_error("MessageBase::BuildFields not yet implemented");
00283 }
00284
00285 void MessageBase::Clear()
00286 {
00287
00288 RecType = 0;
00289 RecordId = 0;
00290
00291
00292 From.clear();
00293 To.clear();
00294 Cc.clear();
00295 Bcc.clear();
00296 Sender.clear();
00297 ReplyTo.clear();
00298
00299 Subject.clear();
00300 Body.clear();
00301 Attachment.clear();
00302
00303 MessageRecordId = 0;
00304 MessageReplyTo = 0;
00305 MessageDateSent.clear();
00306 MessageDateReceived.clear();
00307
00308 MessageTruncated = false;
00309 MessageRead = false;
00310 MessageReply = false;
00311 MessageSaved = false;
00312 MessageSavedDeleted = false;
00313
00314 Priority = NormalPriority;
00315 Sensitivity = NormalSensitivity;
00316
00317 Unknowns.clear();
00318 }
00319
00320 template <class RecordT>
00321 void DoFillHandles(typename FieldHandle<RecordT>::ListT &handles)
00322 {
00323
00324 handles.clear();
00325
00326 #undef CONTAINER_OBJECT_NAME
00327 #define CONTAINER_OBJECT_NAME handles
00328
00329 #undef RECORD_CLASS_NAME
00330 #define RECORD_CLASS_NAME RecordT
00331
00332 FHP(RecType, "Record Type Code");
00333 FHP(RecordId, "Unique Record ID");
00334
00335 FHD(From, "From", MBFC_FROM, true);
00336 FHD(To, "To", MBFC_TO, true);
00337 FHD(Cc, "CC", MBFC_CC, true);
00338 FHD(Bcc, "BCC", MBFC_BCC, true);
00339 FHD(Sender, "Sender", MBFC_SENDER, true);
00340 FHD(ReplyTo, "Reply To", MBFC_REPLY_TO, true);
00341 FHD(Subject, "Subject", MBFC_SUBJECT, true);
00342 FHD(Body, "Body", MBFC_BODY, true);
00343 FHD(Attachment, "Attachment", MBFC_ATTACHMENT, false);
00344
00345 FHD(MessageRecordId, "Message Record ID", MBFC_RECORDID, false);
00346 FHP(MessageReplyTo, "Message Reply To");
00347 FHP(MessageDateSent, "Date Sent");
00348 FHP(MessageDateReceived, "Date Received");
00349
00350 FHP(MessageTruncated, "Truncated");
00351 FHP(MessageRead, "Read");
00352 FHP(MessageReply, "Reply");
00353 FHP(MessageSaved, "Saved");
00354 FHP(MessageSavedDeleted, "Saved Deleted");
00355
00356 FHET(pt, PriorityType, Priority, "Priority");
00357 FHE_CONST(pt, LowPriority, "Low");
00358 FHE_CONST(pt, NormalPriority, "Normal");
00359 FHE_CONST(pt, HighPriority, "High");
00360 FHE_CONST(pt, UnknownPriority, "Unknown");
00361
00362 FHET(st, SensitivityType, Sensitivity, "Sensitivity");
00363 FHE_CONST(st, NormalSensitivity, "Normal");
00364 FHE_CONST(st, Personal, "Personal");
00365 FHE_CONST(st, Private, "Private");
00366 FHE_CONST(st, Confidential, "Confidential");
00367 FHE_CONST(st, UnknownSensitivity, "Unknown");
00368
00369 FHP(Unknowns, "Unknown Fields");
00370 }
00371
00372 std::string MessageBase::GetDescription() const
00373 {
00374
00375 return Subject;
00376 }
00377
00378 std::string MessageBase::SimpleFromAddress() const
00379 {
00380 if( From.size() ) {
00381
00382 std::string ret;
00383 for( size_t i = 0; i < From[0].Email.size(); i++ )
00384 if( From[0].Email[i] != ' ' )
00385 ret += From[0].Email[i];
00386
00387 return ret;
00388 }
00389 else {
00390 return "unknown";
00391 }
00392 }
00393
00394
00395 void MessageBase::Dump(std::ostream &os) const
00396 {
00397 ios_format_state state(os);
00398
00399 static const char *Importance[] =
00400 { "Low", "Normal", "High", "Unknown Priority" };
00401 static const char *SensitivityString[] =
00402 { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
00403
00404 os << "From " << SimpleFromAddress() << " " << MessageDateReceived << "\n";
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
00415
00416 if( MessageReplyTo )
00417 os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
00418 if( MessageSaved )
00419 os << "X-Message-Status: Saved\n";
00420 else if( MessageRead )
00421 os << "Message Status: Opened\n";
00422 if( Priority != NormalPriority )
00423 os << "Importance: " << Importance[Priority] << "\n";
00424 if( Sensitivity != NormalSensitivity )
00425 os << "Sensitivity: " << SensitivityString[Sensitivity] << "\n";
00426 os << "Date: " << MessageDateSent << "\n";
00427 if( From.size() )
00428 os << "From: " << From[0] << "\n";
00429 if( To.size() )
00430 os << "To: " << To << "\n";
00431 if( Cc.size() )
00432 os << "Cc: " << Cc << "\n";
00433 if( Bcc.size() )
00434 os << "Bcc: " << Bcc << "\n";
00435 if( Sender.size() )
00436 os << "Sender: " << Sender << "\n";
00437 if( ReplyTo.size())
00438 os << "Reply To: " << ReplyTo << "\n";
00439 if( Subject.size() )
00440 os << "Subject: " << Subject << "\n";
00441 os << "\n";
00442 os << Cr2LfWrapper(Body);
00443 os << "\n";
00444
00445 if( Attachment.size() )
00446 os << "Attachments: " << Data(Attachment.data(), Attachment.size()) << "\n";
00447
00448 os << Unknowns;
00449 os << "\n\n";
00450 }
00451
00452 bool MessageBase::operator<(const MessageBase &other) const
00453 {
00454
00455
00456
00457 time_t date = std::max(MessageDateSent.Time, MessageDateReceived.Time);
00458 time_t odate = std::max(other.MessageDateSent.Time, other.MessageDateReceived.Time);
00459
00460 if( date != odate )
00461 return date < odate;
00462
00463 return Subject < other.Subject;
00464 }
00465
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475 #include "r_message.h"
00476 #include "r_pin_message.h"
00477 #include "r_saved_message.h"
00478
00479
00480 namespace Barry {
00481
00482
00483
00484
00485 const FieldHandle<Message>::ListT& Message::GetFieldHandles()
00486 {
00487 static FieldHandle<Message>::ListT fhv;
00488
00489 if( fhv.size() )
00490 return fhv;
00491
00492 DoFillHandles<Message>(fhv);
00493 return fhv;
00494 }
00495
00496
00497
00498
00499 const FieldHandle<PINMessage>::ListT& PINMessage::GetFieldHandles()
00500 {
00501 static FieldHandle<PINMessage>::ListT fhv;
00502
00503 if( fhv.size() )
00504 return fhv;
00505
00506 DoFillHandles<PINMessage>(fhv);
00507 return fhv;
00508 }
00509
00510
00511
00512
00513 const FieldHandle<SavedMessage>::ListT& SavedMessage::GetFieldHandles()
00514 {
00515 static FieldHandle<SavedMessage>::ListT fhv;
00516
00517 if( fhv.size() )
00518 return fhv;
00519
00520 DoFillHandles<SavedMessage>(fhv);
00521 return fhv;
00522 }
00523
00524 }
00525