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_pin_message.h"
00024 #include "record-internal.h"
00025 #include "protocol.h"
00026 #include "protostructs.h"
00027 #include "data.h"
00028 #include "time.h"
00029 #include "error.h"
00030 #include "endian.h"
00031 #include <ostream>
00032 #include <iomanip>
00033 #include <time.h>
00034 #include <stdexcept>
00035
00036 #define __DEBUG_MODE__
00037 #include "debug.h"
00038
00039 using namespace std;
00040 using namespace Barry::Protocol;
00041
00042 namespace Barry {
00043
00044
00045
00046
00047
00048
00049
00050 #define PNMFC_TO 0x01 // can occur multiple times
00051 #define PNMFC_CC 0x02 // ditto
00052 #define PNMFC_BCC 0x03 // ditto
00053 #define PNMFC_FROM 0x05
00054 #define PNMFC_SUBJECT 0x0b
00055 #define PNMFC_BODY 0x0c
00056 #define PNMFC_REPLY_UNKNOWN 0x12 // this appears on replies, always 0x00
00057 #define PNMFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber
00058 #define PNMFC_END 0xffff
00059
00060 #define PRIORITY_MASK 0x003f
00061 #define PRIORITY_HIGH 0x0008
00062 #define PRIORITY_LOW 0x0002
00063
00064 #define SENSITIVE_MASK 0xff80
00065 #define SENSITIVE_CONFIDENTIAL 0x0100
00066 #define SENSITIVE_PERSONAL 0x0080
00067 #define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
00068
00069 #define MESSAGE_READ 0x0800
00070 #define MESSAGE_REPLY 0x0001
00071 #define MESSAGE_SAVED 0x0002
00072 #define MESSAGE_FORWARD 0x0008
00073 #define MESSAGE_TRUNCATED 0x0020
00074 #define MESSAGE_SAVED_DELETED 0x0080
00075
00076 FieldLink<PINMessage> PINMessageFieldLinks[] = {
00077 { PNMFC_TO, "To", 0, 0, 0, &PINMessage::To, 0 },
00078 { PNMFC_CC, "Cc", 0, 0, 0, &PINMessage::Cc, 0 },
00079 { PNMFC_BCC, "Bcc", 0, 0, 0, &PINMessage::Bcc, 0 },
00080 { PNMFC_FROM, "From", 0, 0, 0, &PINMessage::From, 0 },
00081 { PNMFC_SUBJECT, "Subject", 0, 0, &PINMessage::Subject, 0, 0 },
00082 { PNMFC_BODY, "Body", 0, 0, &PINMessage::Body, 0, 0 },
00083 { PNMFC_END, "End of List", 0, 0, 0, 0, 0 }
00084 };
00085
00086 PINMessage::PINMessage()
00087 {
00088 }
00089
00090 PINMessage::~PINMessage()
00091 {
00092 }
00093
00094 const unsigned char* PINMessage::ParseField(const unsigned char *begin,
00095 const unsigned char *end)
00096 {
00097 const CommonField *field = (const CommonField *) begin;
00098
00099
00100 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00101 if( begin > end )
00102 return begin;
00103
00104 if( !btohs(field->size) )
00105 return begin;
00106
00107
00108 for( FieldLink<PINMessage> *b = PINMessageFieldLinks;
00109 b->type != PNMFC_END;
00110 b++ )
00111 {
00112 if( b->type == field->type ) {
00113 if( b->strMember ) {
00114
00115 std::string &s = this->*(b->strMember);
00116 s = ParseFieldString(field);
00117 return begin;
00118 }
00119 else if( b->addrMember ) {
00120
00121
00122 const char *fa = (const char*)field->u.addr.addr;
00123 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
00124
00125
00126 EmailAddress &a = this->*(b->addrMember);
00127 a.Name = dual.c_str();
00128
00129
00130 a.Email = dual.c_str() + a.Name.size() + 1;
00131 return begin;
00132 }
00133 }
00134 }
00135
00136
00137 switch( field->type )
00138 {
00139 case PNMFC_RECORDID:
00140 MessageRecordId = btohl(field->u.uint32);
00141 return begin;
00142 }
00143
00144
00145 UnknownField uf;
00146 uf.type = field->type;
00147 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00148 Unknowns.push_back(uf);
00149
00150 return begin;
00151 }
00152
00153 void PINMessage::ParseHeader(const Data &data, size_t &offset)
00154 {
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 Protocol::CheckSize(data, offset + MESSAGE_RECORD_HEADER_SIZE);
00167
00168 MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
00169
00170
00171 MessagePriority = NormalPriority;
00172
00173 uint16_t priority = btohs(mr->priority);
00174 if( priority & PRIORITY_MASK ) {
00175 if( priority & PRIORITY_HIGH ) {
00176 MessagePriority = HighPriority;
00177 }
00178 else if( priority & PRIORITY_LOW ) {
00179 MessagePriority = LowPriority;
00180 }
00181 else
00182 MessagePriority = UnknownPriority;
00183 }
00184
00185 MessageSensitivity = NormalSensitivity;
00186 if( priority & SENSITIVE_MASK ) {
00187 if(( priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
00188 MessageSensitivity = Confidential;
00189 }
00190 else if(( priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
00191 MessageSensitivity = Private;
00192 }
00193 else if(( priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
00194 MessageSensitivity = Personal;
00195 }
00196 else
00197 MessageSensitivity = UnknownSensitivity;
00198 }
00199
00200 if( mr->inReplyTo )
00201 MessageReplyTo = btohl(mr->inReplyTo);
00202
00203
00204 uint32_t flags = btohl(mr->flags);
00205 if( !( flags & MESSAGE_READ ))
00206 MessageRead = true;
00207
00208 if(( flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
00209 MessageReply = true;
00210
00211 if( !( flags & MESSAGE_TRUNCATED ))
00212 MessageTruncated = true;
00213
00214
00215 if( !( flags & MESSAGE_SAVED ))
00216 MessageSaved = true;
00217 if( !( flags & MESSAGE_SAVED_DELETED ))
00218 MessageSavedDeleted = true;
00219
00220 MessageDateSent = Message2Time(mr->dateSent, mr->timeSent);
00221 MessageDateReceived = Message2Time(mr->dateReceived, mr->timeReceived);
00222
00223 offset += MESSAGE_RECORD_HEADER_SIZE;
00224 }
00225
00226 void PINMessage::ParseFields(const Data &data, size_t &offset)
00227 {
00228 const unsigned char *finish = ParseCommonFields(*this,
00229 data.GetData() + offset, data.GetData() + data.GetSize());
00230 offset += finish - (data.GetData() + offset);
00231 }
00232
00233 void PINMessage::BuildHeader(Data &data, size_t &offset) const
00234 {
00235 throw std::logic_error("PINMessage::BuildHeader not yet implemented");
00236 }
00237
00238 void PINMessage::BuildFields(Data &data, size_t &offset) const
00239 {
00240 throw std::logic_error("PINMessage::BuildFields not yet implemented");
00241 }
00242
00243 void PINMessage::Clear()
00244 {
00245 From.clear();
00246 To.clear();
00247 Cc.clear();
00248 Bcc.clear();
00249
00250 Subject.clear();
00251 Body.clear();
00252
00253 MessageRecordId = 0;
00254 MessageReplyTo = 0;
00255 MessageDateSent = 0;
00256 MessageDateReceived = 0;
00257 MessageTruncated = false;
00258 MessageRead = false;
00259 MessageReply = false;
00260 MessageSaved = false;
00261 MessageSavedDeleted = false;
00262
00263 Unknowns.clear();
00264 }
00265
00266
00267 void PINMessage::Dump(std::ostream &os) const
00268 {
00269 static const char *MessageImportance[] =
00270 { "Low", "Normal", "High", "Unknown Priority" };
00271 static const char *MessageSensitivityString[] =
00272 { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
00273
00274 os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
00275 << " " << ctime( &MessageDateSent );
00276 os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
00277 if( MessageReplyTo )
00278 os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
00279 if( MessageSaved )
00280 os << "Message Status: Saved\n";
00281 else if( MessageRead )
00282 os << "Message Status: Opened\n";
00283 if( MessagePriority != NormalPriority )
00284 os << "Importance: " << MessageImportance[MessagePriority] << "\n";
00285 if( MessageSensitivity != NormalSensitivity )
00286 os << "Sensitivity: " << MessageSensitivityString[MessageSensitivity] << "\n";
00287 os << "Date: " << ctime(&MessageDateSent);
00288
00289 if( From.Name.size()) {
00290 os << " From: " << From.Name << " <" << From.Email << ">\n";
00291 }
00292 if( To.Name.size()) {
00293 os << " To: " << To.Name << " <" << To.Email << ">\n";
00294 }
00295 if( Cc.Name.size()) {
00296 os << " Cc: " << Cc.Name << " <" << Cc.Email << ">\n";
00297 }
00298 if( Bcc.Name.size()) {
00299 os << " Bcc: " << Bcc.Name << " <" << Bcc.Email << ">\n";
00300 }
00301
00302 if( Subject.size() )
00303 os << " Subject: " << Subject << "\n";
00304 else
00305 os << " Subject: <>\n";
00306 os << "\n";
00307
00308 for( std::string::const_iterator i = Body.begin();
00309 i != Body.end() && *i;
00310 i++)
00311 {
00312 if( *i == '\r' )
00313 os << '\n';
00314 else
00315 os << *i;
00316 }
00317 os << "\n";
00318
00319 os << Unknowns;
00320 os << "\n\n";
00321 }
00322
00323
00324 }
00325