So, after crashing my hard drive and recreating all this info from notes
(backup!, backup!, backup!), here is a patch to the message databases to
parse out some of the information stored in the header, i.e. flags, priority,
time and date.
In protostructs.h I've commented on most of the fields as I've been able to
parse them out. There are still some fields that appear interesting, but most
of the important data has been discovered and I hope interpreted correctly.
Left on the TODO list:
Year information from the date field - I'll set up a test configuration that
will let me adjust the year on emails, or wait 6 months for the year to
change - whichever comes first.
Time is 'close' but I'm not sure that getting any finer resolution is worth
any more effort. The way to effect this is to go to better resolution than
1.77.
The header structure appears to be identical between Messages, Saved Email
Messages and PIN Messages, as are most of the functions being called. I will
work on some refactoring.
On my 7100g I can only save messages to one folder, it appears the
functionality exists to save and move messages to other folders. So far
cingular has limited me to v4.1 so I haven't been able to experiment with
some of the newer desktop features.
I did a quick and dirty implemention for 'Folders' to help me in debugging
the messages headers. I'll clean it up and post it soon. On my 7100g I can
see which of my accounts the message was received on, and that info is in the
header. I guess it could be parsed out and put into the output.
So here's the patch, enjoy - and yes Chris, I did 'vimify' it to check the
formatting ;)
-edge
Index: src/r_pin_message.cc
===================================================================
RCS file: /cvsroot/barry/barry/src/r_pin_message.cc,v
retrieving revision 1.4
diff -u -r1.4 r_pin_message.cc
--- src/r_pin_message.cc 8 Jun 2007 19:25:15 -0000 1.4
+++ src/r_pin_message.cc 24 Jun 2007 12:02:27 -0000
@@ -57,9 +57,26 @@
#define PNMFC_FROM 0x05
#define PNMFC_SUBJECT 0x0b
#define PNMFC_BODY 0x0c
+#define PNMFC_REPLY_UNKNOWN 0x12 // this appears on replies, always 0x00
#define PNMFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber
#define PNMFC_END 0xffff
+#define PRIORITY_MASK 0x003f
+#define PRIORITY_HIGH 0x0008
+#define PRIORITY_LOW 0x0002
+
+#define SENSITIVE_MASK 0xff80
+#define SENSITIVE_CONFIDENTIAL 0x0100
+#define SENSITIVE_PERSONAL 0x0080
+#define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
+
+#define MESSAGE_READ 0x0800
+#define MESSAGE_REPLY 0x0001
+#define MESSAGE_SAVED 0x0002
+#define MESSAGE_FORWARD 0x0008
+#define MESSAGE_TRUNCATED 0x0020
+#define MESSAGE_SAVED_DELETED 0x0080
+
FieldLink<PINMessage> PINMessageFieldLinks[] = {
{ PNMFC_TO, "To", 0, 0, 0, &PINMessage::To, 0 },
{ PNMFC_CC, "Cc", 0, 0, 0, &PINMessage::Cc, 0 },
@@ -139,11 +156,72 @@
void PINMessage::ParseHeader(const Data &data, size_t &offset)
{
- // we skip the "header" since we don't know what to do with it yet
// FIXME - we are using a Message (email) record header size
// for a PIN Message record... this is not necessarily guaranteed
// to be the same... someday we could use some more info on
// the message record header and pin message record header
+
+ // FIXED - the header structure for both the PIN messages and
+ // email messages are the same, as is the header structure for
+ // 'Saved Email Messages' although some of the fields may not directly apply.
+ //
+ // and someday is now here ;) - edge
+
+ MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
+ // Priority
+ MessagePriority = NormalPriority;
+ if( mr->priority & PRIORITY_MASK ) {
+ if( mr->priority & PRIORITY_HIGH ) {
+ MessagePriority = HighPriority;
+ }
+ else if( mr->priority & PRIORITY_LOW ) {
+ MessagePriority = LowPriority;
+ }
+ else
+ MessagePriority = UnknownPriority;
+ }
+ // Sensitivity
+ MessageSensitivity = NormalSensitivity;
+ if( mr->priority & SENSITIVE_MASK ) {
+ if(( mr->priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
+ MessageSensitivity = Confidential;
+ }
+ else if(( mr->priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
+ MessageSensitivity = Private;
+ }
+ else if(( mr->priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
+ MessageSensitivity = Personal;
+ }
+ else
+ MessageSensitivity = UnknownSensitivity;
+ }
+ // X-rim-org-message-ref-id // NOTE: I'm cheating a bit here and using this as a reply-to
+ if( mr->inReplyTo ) // It's actually sent by BB with the actual UID in every message
+ MessageReplyTo = mr->inReplyTo;
+ // Status Flags
+ if( !( mr->flags & MESSAGE_READ ))
+ MessageRead = true; // NOTE: A lot of these flags are 'backwards' but this seemed
+ // like the most logical way to interpret them for now
+ if(( mr->flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
+ MessageReply = true; // NOTE: This is a reply, the original message's flags are not changed
+ // the inReplyTo field is updated with the original messages's UID
+ if( !( mr->flags & MESSAGE_TRUNCATED ))
+ MessageTruncated = true; // NOTE: This bit is unset on truncation, around 4096 on my 7100g
+ // NOTE: bit 0x400 is set on REALLY huge messages, haven't tested
+ // the exact size yet
+ if( !( mr->flags & MESSAGE_SAVED ))
+ MessageSaved = true; // NOTE: Saved to 'saved' folder
+ if( !( mr->flags & MESSAGE_SAVED_DELETED ))
+ MessageSavedDeleted = true; // NOTE: Saved to 'saved' folder and then deleted from inbox
+
+ MessageDateSent = ( mr->dateSent & 0x01ff ) - 0x29;
+ MessageDateSent = DayToDate( MessageDateSent );
+ MessageDateSent += (time_t)( mr->timeSent*1.77 );
+
+ MessageDateReceived = ( mr->dateReceived & 0x01ff ) - 0x29;
+ MessageDateReceived = DayToDate( MessageDateReceived );
+ MessageDateReceived += (time_t)( mr->timeReceived*1.77 );
+
offset += MESSAGE_RECORD_HEADER_SIZE;
}
@@ -173,20 +251,43 @@
Subject.clear();
Body.clear();
+
MessageRecordId = 0;
-
+ MessageReplyTo = 0;
+ MessageDateSent = 0;
+ MessageDateReceived = 0;
+ MessageTruncated = false;
+ MessageRead = false;
+ MessageReply = false;
+ MessageSaved = false;
+ MessageSavedDeleted = false;
+
Unknowns.clear();
}
// dump message in mbox format
void PINMessage::Dump(std::ostream &os) const
{
- // FIXME - use current time until we figure out the date headers
- time_t fixme = time(NULL);
+ static const char *MessageImportance[] =
+ { "Low", "Normal", "High", "Unknown Priority" };
+ static const char *MessageSensitivityString[] =
+ { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
- << " " << ctime(&fixme);
- os << "X-Record-ID: (" << std::hex << MessageRecordId << ")\n";
+ << " " << ctime( &MessageDateSent );
+ os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
+ if( MessageReplyTo )
+ os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
+ if( MessageSaved )
+ os << "Message Status: Saved\n";
+ else if( MessageRead )
+ os << "Message Status: Opened\n";
+ if( MessagePriority != NormalPriority )
+ os << "Importance: " << MessageImportance[MessagePriority] << "\n";
+ if( MessageSensitivity != NormalSensitivity )
+ os << "Sensitivity: " << MessageSensitivityString[MessageSensitivity] << "\n";
+ os << "Date: " << ctime(&MessageDateSent);
+
if( From.Name.size()) {
os << " From: " << From.Name << " <" << From.Email << ">\n";
}
Index: src/time.h
===================================================================
RCS file: /cvsroot/barry/barry/src/time.h,v
retrieving revision 1.7
diff -u -r1.7 time.h
--- src/time.h 26 Jan 2007 04:10:32 -0000 1.7
+++ src/time.h 24 Jun 2007 12:02:27 -0000
@@ -67,6 +67,9 @@
const TimeZone* GetTimeZone(unsigned short Code);
unsigned short GetTimeZoneCode(signed short HourOffset,
signed short MinOffset = 0);
+
+// Message time conversion stuff
+time_t DayToDate( unsigned short Day );
} // namespace Barry
Index: src/r_pin_message.h
===================================================================
RCS file: /cvsroot/barry/barry/src/r_pin_message.h,v
retrieving revision 1.4
diff -u -r1.4 r_pin_message.h
--- src/r_pin_message.h 8 Jun 2007 19:25:15 -0000 1.4
+++ src/r_pin_message.h 24 Jun 2007 12:02:27 -0000
@@ -59,6 +59,34 @@
// and not as part of the header...
// in effect, this record ID occurs
// twice in the protocol
+ uint32_t MessageReplyTo;
+ time_t MessageDateSent;
+ time_t MessageDateReceived;
+
+ // Message Flags
+ bool MessageTruncated;
+ bool MessageRead;
+ bool MessageReply;
+ bool MessageSaved;
+ bool MessageSavedDeleted;
+
+ enum MessagePriorityType {
+ LowPriority = 0,
+ NormalPriority,
+ HighPriority,
+ UnknownPriority
+ };
+ MessagePriorityType MessagePriority;
+
+ enum MessageSensitivityType {
+ NormalSensitivity = 0,
+ Personal,
+ Private,
+ Confidential,
+ UnknownSensitivity
+ };
+ MessageSensitivityType MessageSensitivity;
+
std::vector<UnknownField> Unknowns;
public:
Index: src/r_saved_message.cc
===================================================================
RCS file: /cvsroot/barry/barry/src/r_saved_message.cc,v
retrieving revision 1.2
diff -u -r1.2 r_saved_message.cc
--- src/r_saved_message.cc 8 Jun 2007 19:25:15 -0000 1.2
+++ src/r_saved_message.cc 24 Jun 2007 12:02:27 -0000
@@ -59,6 +59,22 @@
#define SEMFC_RECORDID 0x4b
#define SEMFC_END 0xffff
+#define PRIORITY_MASK 0x003f
+#define PRIORITY_HIGH 0x0008
+#define PRIORITY_LOW 0x0002
+
+#define SENSITIVE_MASK 0xff80
+#define SENSITIVE_CONFIDENTIAL 0x0100
+#define SENSITIVE_PERSONAL 0x0080
+#define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
+
+#define MESSAGE_READ 0x0800
+#define MESSAGE_REPLY 0x0001
+#define MESSAGE_SAVED 0x0002
+#define MESSAGE_FORWARD 0x0008
+#define MESSAGE_TRUNCATED 0x0020
+#define MESSAGE_SAVED_DELETED 0x0080
+
FieldLink<SavedMessage> SavedMessageFieldLinks[] = {
{ SEMFC_TO, "To", 0, 0, 0, &SavedMessage::To, 0 },
{ SEMFC_CC, "Cc", 0, 0, 0, &SavedMessage::Cc, 0 },
@@ -142,11 +158,60 @@
void SavedMessage::ParseHeader(const Data &data, size_t &offset)
{
- // we skip the "header" since we don't know what to do with it yet
- // FIXME - we are using a Message (email) record header size
- // for a PIN Message record... this is not necessarily guaranteed
- // to be the same... someday we could use some more info on
- // the message record header and pin message record header
+ MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
+ // Priority
+ MessagePriority = NormalPriority;
+ if( mr->priority & PRIORITY_MASK ) {
+ if( mr->priority & PRIORITY_HIGH ) {
+ MessagePriority = HighPriority;
+ }
+ else if( mr->priority & PRIORITY_LOW ) {
+ MessagePriority = LowPriority;
+ }
+ else
+ MessagePriority = UnknownPriority;
+ }
+ // Sensitivity
+ MessageSensitivity = NormalSensitivity;
+ if( mr->priority & SENSITIVE_MASK ) {
+ if(( mr->priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
+ MessageSensitivity = Confidential;
+ }
+ else if(( mr->priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
+ MessageSensitivity = Private;
+ }
+ else if(( mr->priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
+ MessageSensitivity = Personal;
+ }
+ else
+ MessageSensitivity = UnknownSensitivity;
+ }
+ // X-rim-org-message-ref-id // NOTE: I'm cheating a bit here and using this as a reply-to
+ if( mr->inReplyTo ) // It's actually sent by BB with the actual UID in every message
+ MessageReplyTo = mr->inReplyTo;
+ // Status Flags
+ if( !( mr->flags & MESSAGE_READ ))
+ MessageRead = true; // NOTE: A lot of these flags are 'backwards' but this seemed
+ // like the most logical way to interpret them for now
+ if(( mr->flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
+ MessageReply = true; // NOTE: This is a reply, the original message's flags are not changed
+ // the inReplyTo field is updated with the original messages's UID
+ if( !( mr->flags & MESSAGE_TRUNCATED ))
+ MessageTruncated = true; // NOTE: This bit is unset on truncation, around 4096 on my 7100g
+ // NOTE: bit 0x400 is set on REALLY huge messages, haven't tested
+ // the exact size yet
+ if( !( mr->flags & MESSAGE_SAVED ))
+ MessageSaved = true; // NOTE: Saved to 'saved' folder
+ if( !( mr->flags & MESSAGE_SAVED_DELETED ))
+ MessageSavedDeleted = true; // NOTE: Saved to 'saved' folder and then deleted from inbox
+
+ MessageDateSent = ( mr->dateSent & 0x01ff ) - 0x29;
+ MessageDateSent = DayToDate( MessageDateSent );
+ MessageDateSent += (time_t)( mr->timeSent*1.77 );
+
+ MessageDateReceived = ( mr->dateReceived & 0x01ff ) - 0x29;
+ MessageDateReceived = DayToDate( MessageDateReceived );
+ MessageDateReceived += (time_t)( mr->timeReceived*1.77 );
offset += MESSAGE_RECORD_HEADER_SIZE;
}
@@ -180,20 +245,39 @@
Attachment.clear();
MessageRecordId = 0;
-
+ MessageReplyTo = 0;
+ MessageDateSent = 0;
+ MessageDateReceived = 0;
+ MessageTruncated = false;
+ MessageRead = false;
+ MessageReply = false;
+ MessageSaved = false;
+ MessageSavedDeleted = false;
Unknowns.clear();
}
// dump message in mbox format
void SavedMessage::Dump(std::ostream &os) const
{
- // FIXME - use current time until we figure out the date headers
- time_t fixme = time(NULL);
+ static const char *MessageImportance[] =
+ { "Low", "Normal", "High", "Unknown Priority" };
+ static const char *MessageSensitivityString[] =
+ { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
- << " " << ctime(&fixme);
- os << "X-Record-ID: (0x" << std::hex << MessageRecordId << ")\n";
- os << "Date: " << ctime(&fixme);
+ << " " << ctime( &MessageDateSent );
+ os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
+ if( MessageReplyTo )
+ os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
+ if( MessageSaved )
+ os << "Message Status: Saved\n";
+ else if( MessageRead )
+ os << "Message Status: Opened\n";
+ if( MessagePriority != NormalPriority )
+ os << "Importance: " << MessageImportance[MessagePriority] << "\n";
+ if( MessageSensitivity != NormalSensitivity )
+ os << "Sensitivity: " << MessageSensitivityString[MessageSensitivity] << "\n";
+ os << "Date: " << ctime(&MessageDateSent);
os << "From: " << From << "\n";
if( To.Email.size() )
os << "To: " << To << "\n";
Index: src/protostructs.h
===================================================================
RCS file: /cvsroot/barry/barry/src/protostructs.h,v
retrieving revision 1.15
diff -u -r1.15 protostructs.h
--- src/protostructs.h 6 Jun 2007 20:52:55 -0000 1.15
+++ src/protostructs.h 24 Jun 2007 12:02:26 -0000
@@ -432,7 +432,57 @@
struct MessageRecord
{
- uint8_t timeBlock[0x74];
+ uint8_t field1; // always 'j'
+ uint32_t field2; // always 0x00000000
+ uint32_t flags; // flags
+ uint32_t field4; // normal email and pin recv this is 0x7ff
+ // changes on sent and reply to 0x01ffffff
+ // and 0x003fffff on pin send
+ uint32_t field5; // always 0x00000000
+ uint32_t field6; // always 0x00000000
+ uint32_t field7; // always 0x00000000
+ uint32_t field8; // always 0x00000000
+ uint16_t field9; // always 0x0000
+
+ uint16_t dateReceived; // the first two of these time fields are always the same
+ uint16_t timeReceived; //
+ uint16_t dateDuplicate; // On mail sent from the BB all three fields are identical
+ uint16_t timeDuplicate; // (time sent)
+ uint16_t dateSent;
+ uint16_t timeSent;
+
+ uint16_t priority; // priority field
+ uint32_t field14; // always 0x00000000
+ uint32_t field15; // always 0x00000000
+ uint16_t field16; // always 0x0000
+ uint32_t field13; // PIN reply 0x00000000 other time 0xffffffff or 0xfffffffe
+ uint16_t messageSize; // Message size, 0x0000 if Reply or Saved, 0xffff if below ????
+ uint32_t field18; // 0x0's and 0xF'x
+ uint32_t field19; // 0x0's and 0xF's
+ uint16_t field20; // always 0x0000
+ uint16_t field21; // 0x01 unless PIN reply then 0x00
+ uint32_t inReplyTo; // reply to message?
+ uint32_t field22; // always 0x00000000
+ uint16_t field23; // TODO
+
+ uint32_t folderOne; // these are the 'folders' the message is in
+ uint32_t folderTwo; //
+
+ uint16_t replyMessageFlags; // 0xfffe on recvd messages
+ // 0x001b on reply
+ // 0x0015 on send
+ // 0x3 pin send
+ // 0x2 on pin recv
+ uint16_t field27; // set to 0x00000004 on PIN reply, 0x00000005 otherwise
+ uint32_t headerUID; // yet another copy of the UID (RecId)
+
+ uint32_t field29; // always 0x00000000
+ uint16_t field30; // always 0x0002
+ uint16_t field31; // always 0x00000000
+ uint16_t field32; // always 0x0004
+ uint16_t field34; // always 0x0000
+ uint8_t field33; // always 'd'
+ uint32_t timeBlock; // TODO
CommonField field[1];
} __attribute__ ((packed));
#define MESSAGE_RECORD_HEADER_SIZE (sizeof(Barry::Protocol::MessageRecord) - sizeof(Barry::Protocol::CommonField))
Index: src/time.cc
===================================================================
RCS file: /cvsroot/barry/barry/src/time.cc,v
retrieving revision 1.6
diff -u -r1.6 time.cc
--- src/time.cc 13 Jan 2007 07:39:35 -0000 1.6
+++ src/time.cc 24 Jun 2007 12:02:27 -0000
@@ -168,6 +168,36 @@
return TIME_ZONE_CODE_ERR;
}
+/// This routine takes the day of the year and
+/// returns a time_t adjusted from the first of
+/// the year.
+///
+/// TODO This function assumes the year hasn't changed,
+/// but I don't have enough information to determine
+/// where the year is in this header info
+///
+time_t DayToDate( unsigned short Day )
+{
+ struct tm *now, then;
+ time_t t = time( NULL );
+
+ now = localtime( &t ); // need this to get year
+ // set to Jan 1 midnight, this year;
+ then.tm_sec = 0;
+ then.tm_min = 0;
+ then.tm_hour = 0;
+ then.tm_mday = 0;
+ then.tm_mon = 0;
+ then.tm_year = now->tm_year;
+ then.tm_isdst = -1;
+ t = mktime(&then);
+ t -= 60*60; // need to subract an hour
+ t += Day * 24 * 60 * 60; // Add the day converted to seconds
+
+ return t;
+}
+
+
} // namespace Barry
Index: src/r_saved_message.h
===================================================================
RCS file: /cvsroot/barry/barry/src/r_saved_message.h,v
retrieving revision 1.2
diff -u -r1.2 r_saved_message.h
--- src/r_saved_message.h 8 Jun 2007 19:25:15 -0000 1.2
+++ src/r_saved_message.h 24 Jun 2007 12:02:27 -0000
@@ -57,6 +57,34 @@
std::string Body;
std::string Attachment;
uint32_t MessageRecordId;
+ uint32_t MessageReplyTo;
+ time_t MessageDateSent;
+ time_t MessageDateReceived;
+
+ // Message Flags
+ bool MessageTruncated;
+ bool MessageRead;
+ bool MessageReply;
+ bool MessageSaved;
+ bool MessageSavedDeleted;
+
+ enum MessagePriorityType {
+ LowPriority = 0,
+ NormalPriority,
+ HighPriority,
+ UnknownPriority
+ };
+ MessagePriorityType MessagePriority;
+
+ enum MessageSensitivityType {
+ NormalSensitivity = 0,
+ Personal,
+ Private,
+ Confidential,
+ UnknownSensitivity
+ };
+ MessageSensitivityType MessageSensitivity;
+
std::vector<UnknownField> Unknowns;
public:
Index: src/r_message.h
===================================================================
RCS file: /cvsroot/barry/barry/src/r_message.h,v
retrieving revision 1.4
diff -u -r1.4 r_message.h
--- src/r_message.h 8 Jun 2007 19:25:15 -0000 1.4
+++ src/r_message.h 24 Jun 2007 12:02:27 -0000
@@ -42,6 +42,9 @@
class Message
{
public:
+ uint8_t RecType;
+ uint32_t RecordId;
+
Address From;
Address To;
Address Cc;
@@ -52,7 +55,35 @@
std::string Body;
std::string Attachment;
std::vector<UnknownField> Unknowns;
-
+ uint32_t MessageRecordId;
+ uint32_t MessageReplyTo;
+ time_t MessageDateSent;
+ time_t MessageDateReceived;
+
+ // Message Flags
+ bool MessageTruncated;
+ bool MessageRead;
+ bool MessageReply;
+ bool MessageSaved;
+ bool MessageSavedDeleted;
+
+ enum MessagePriorityType {
+ LowPriority = 0,
+ NormalPriority,
+ HighPriority,
+ UnknownPriority
+ };
+ MessagePriorityType MessagePriority;
+
+ enum MessageSensitivityType {
+ NormalSensitivity = 0,
+ Personal,
+ Private,
+ Confidential,
+ UnknownSensitivity
+ };
+ MessageSensitivityType MessageSensitivity;
+
public:
const unsigned char* ParseField(const unsigned char *begin,
const unsigned char *end);
@@ -64,7 +95,7 @@
// Parser / Builder API (see parser.h / builder.h)
uint8_t GetRecType() const;
uint32_t GetUniqueId() const; // empty API, not required by protocol
- void SetIds(uint8_t Type, uint32_t Id); // empty API, not required by protocol
+ void SetIds(uint8_t Type, uint32_t Id){ RecType = Type; RecordId = Id; }
void ParseHeader(const Data &data, size_t &offset);
void ParseFields(const Data &data, size_t &offset);
void BuildHeader(Data &data, size_t &offset) const;
Index: src/r_message.cc
===================================================================
RCS file: /cvsroot/barry/barry/src/r_message.cc,v
retrieving revision 1.3
diff -u -r1.3 r_message.cc
--- src/r_message.cc 6 Jun 2007 20:52:55 -0000 1.3
+++ src/r_message.cc 24 Jun 2007 12:02:27 -0000
@@ -58,8 +58,26 @@
#define MFC_REPLY_TO 0x06
#define MFC_SUBJECT 0x0b
#define MFC_BODY 0x0c
+#define MFC_REPLY_UNKNOWN 0x12 // This shows up as 0x00 on replies but we don't do much with it now
#define MFC_ATTACHMENT 0x16
-#define MFC_END 0xffff
+#define MFC_RECORDID 0x4b
+#define MFC_END 0xffff
+
+#define PRIORITY_MASK 0x003f
+#define PRIORITY_HIGH 0x0008
+#define PRIORITY_LOW 0x0002
+
+#define SENSITIVE_MASK 0xff80
+#define SENSITIVE_CONFIDENTIAL 0x0100
+#define SENSITIVE_PERSONAL 0x0080
+#define SENSITIVE_PRIVATE 0x0040 // actual pattern is 0x00C0
+
+#define MESSAGE_READ 0x0800
+#define MESSAGE_REPLY 0x0001
+#define MESSAGE_SAVED 0x0002
+#define MESSAGE_FORWARD 0x0008
+#define MESSAGE_TRUNCATED 0x0020
+#define MESSAGE_SAVED_DELETED 0x0080
FieldLink<Message> MessageFieldLinks[] = {
{ MFC_TO, "To", 0, 0, 0, &Message::To, 0 },
@@ -76,6 +94,7 @@
Message::Message()
{
+ Clear();
}
Message::~Message()
@@ -123,7 +142,17 @@
}
}
}
-
+ // handle special cases
+ char swallow;
+ switch( field->type )
+ {
+ case MFC_RECORDID:
+ MessageRecordId = field->u.uint32;
+ return begin;
+ case MFC_REPLY_UNKNOWN:
+ swallow = field->u.raw[0];
+ return begin;
+ }
// if still not handled, add to the Unknowns list
UnknownField uf;
uf.type = field->type;
@@ -144,15 +173,64 @@
throw std::logic_error("Message::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
}
-// empty API, not required by protocol
-void Message::SetIds(uint8_t Type, uint32_t Id)
-{
- // accept it without complaining, just do nothing
-}
-
void Message::ParseHeader(const Data &data, size_t &offset)
{
- // we skip the "header" since we don't know what to do with it yet
+ MAKE_RECORD(const Barry::Protocol::MessageRecord, mr, data, offset);
+
+ // Priority
+ MessagePriority = NormalPriority;
+ if( mr->priority & PRIORITY_MASK ) {
+ if( mr->priority & PRIORITY_HIGH ) {
+ MessagePriority = HighPriority;
+ }
+ else if( mr->priority & PRIORITY_LOW ) {
+ MessagePriority = LowPriority;
+ }
+ else
+ MessagePriority = UnknownPriority;
+ }
+ // Sensitivity
+ MessageSensitivity = NormalSensitivity;
+ if( mr->priority & SENSITIVE_MASK ) {
+ if(( mr->priority & SENSITIVE_CONFIDENTIAL ) == SENSITIVE_CONFIDENTIAL ) {
+ MessageSensitivity = Confidential;
+ }
+ else if(( mr->priority & SENSITIVE_PRIVATE ) == SENSITIVE_PRIVATE ) {
+ MessageSensitivity = Private;
+ }
+ else if(( mr->priority & SENSITIVE_PERSONAL ) == SENSITIVE_PERSONAL ) {
+ MessageSensitivity = Personal;
+ }
+ else
+ MessageSensitivity = UnknownSensitivity;
+ }
+ // X-rim-org-message-ref-id // NOTE: I'm cheating a bit here and using this as a reply-to
+ if( mr->inReplyTo ) // It's actually sent by BB with the actual UID in every message
+ MessageReplyTo = mr->inReplyTo;
+ // Status Flags
+ if( !( mr->flags & MESSAGE_READ ))
+ MessageRead = true; // NOTE: A lot of these flags are 'backwards' but this seemed
+ // like the most logical way to interpret them for now
+ if(( mr->flags & MESSAGE_REPLY ) == MESSAGE_REPLY )
+ MessageReply = true; // NOTE: This is a reply, the original message's flags are not changed
+ // the inReplyTo field is updated with the original messages's UID
+ if( !( mr->flags & MESSAGE_TRUNCATED ))
+ MessageTruncated = true; // NOTE: This bit is unset on truncation, around 4096 on my 7100g
+ // NOTE: bit 0x400 is set on REALLY huge messages, haven't tested
+ // the exact size yet
+ if( !( mr->flags & MESSAGE_SAVED ))
+ MessageSaved = true; // NOTE: Saved to 'saved' folder
+ if( !( mr->flags & MESSAGE_SAVED_DELETED ))
+ MessageSavedDeleted = true; // NOTE: Saved to 'saved' folder and then deleted from inbox
+
+ MessageDateSent = ( mr->dateSent & 0x01ff ) - 0x29;
+ MessageDateSent = DayToDate( MessageDateSent );
+ MessageDateSent += (time_t)( mr->timeSent*1.77 );
+
+ MessageDateReceived = ( mr->dateReceived & 0x01ff ) - 0x29;
+ MessageDateReceived = DayToDate( MessageDateReceived );
+ MessageDateReceived += (time_t)( mr->timeReceived*1.77 );
+
offset += MESSAGE_RECORD_HEADER_SIZE;
}
@@ -185,18 +263,41 @@
Body.clear();
Attachment.clear();
+ MessageRecordId = 0;
+ MessageReplyTo = 0;
+ MessageDateSent = 0;
+ MessageDateReceived = 0;
+ MessageTruncated = false;
+ MessageRead = false;
+ MessageReply = false;
+ MessageSaved = false;
+ MessageSavedDeleted = false;
+
Unknowns.clear();
}
// dump message in mbox format
void Message::Dump(std::ostream &os) const
{
- // FIXME - use current time until we figure out the date headers
- time_t fixme = time(NULL);
-
+ static const char *MessageImportance[] =
+ { "Low", "Normal", "High", "Unknown Priority" };
+ static const char *MessageSensitivityString[] =
+ { "Normal", "Personal", "Private", "Confidential", "Unknown Sensivity" };
+
os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
- << " " << ctime(&fixme);
- os << "Date: " << ctime(&fixme);
+ << " " << ctime( &MessageDateSent );
+ os << "X-Record-ID: (" << setw(8) << std::hex << MessageRecordId << ")\n";
+ if( MessageReplyTo )
+ os << "X-rim-org-msg-ref-id: " << std::dec << MessageReplyTo << "\n";
+ if( MessageSaved )
+ os << "Message Status: Saved\n";
+ else if( MessageRead )
+ os << "Message Status: Opened\n";
+ if( MessagePriority != NormalPriority )
+ os << "Importance: " << MessageImportance[MessagePriority] << "\n";
+ if( MessageSensitivity != NormalSensitivity )
+ os << "Sensitivity: " << MessageSensitivityString[MessageSensitivity] << "\n";
+ os << "Date: " << ctime(&MessageDateSent);
os << "From: " << From << "\n";
if( To.Email.size() )
os << "To: " << To << "\n";
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Barry-devel mailing list
Barry-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/barry-devel