Here is a patch to add PIN Message and add some additional fields to Message.
Note that I had to make a change to FieldLinks<T>. It had originally included a direct reference to a Message::Address which wouldn't allow a PINMessage::Address (or others for future adds). I created an Address object in record.h and made the necessary changes in r_message and r_pin_message and record-internal.h. Saved Email Messages is coming next, along with a rough cut at the Message header itself, which will provide the recieved and sent dates, the flags having to do with opened, not read, truncated, saved, etc. Chris: I made a quick hack to src/Makefile.am to get these in but you might want to add them differently. -edge
Index: src/r_message.h =================================================================== RCS file: /cvsroot/barry/barry/src/r_message.h,v retrieving revision 1.1 diff -u -r1.1 r_message.h --- src/r_message.h 25 May 2007 06:35:34 -0000 1.1 +++ src/r_message.h 1 Jun 2007 10:37:20 -0000 @@ -42,18 +42,16 @@ class Message { public: - struct Address - { - std::string Name; - std::string Email; - }; - Address From; Address To; Address Cc; + Address Bcc; + Address Sender; + Address ReplyTo; std::string Subject; std::string Body; + std::string Attachment; std::vector<UnknownField> Unknowns; public: @@ -90,7 +88,7 @@ return os; } -std::ostream& operator<<(std::ostream &os, const Message::Address &msga); +std::ostream& operator<<(std::ostream &os, const Address &msga); /// @} Index: src/record-internal.h =================================================================== RCS file: /cvsroot/barry/barry/src/record-internal.h,v retrieving revision 1.2 diff -u -r1.2 record-internal.h --- src/record-internal.h 25 May 2007 20:34:05 -0000 1.2 +++ src/record-internal.h 1 Jun 2007 10:37:20 -0000 @@ -68,7 +68,7 @@ char *ldif; char *objectClass; std::string RecordT::* strMember; // FIXME - find a more general - Message::Address RecordT::* addrMember; // way to do this... + Address RecordT::* addrMember; // way to do this... time_t RecordT::* timeMember; }; Index: src/r_message.cc =================================================================== RCS file: /cvsroot/barry/barry/src/r_message.cc,v retrieving revision 1.1 diff -u -r1.1 r_message.cc --- src/r_message.cc 25 May 2007 06:35:34 -0000 1.1 +++ src/r_message.cc 1 Jun 2007 10:37:20 -0000 @@ -40,7 +40,7 @@ namespace Barry { -std::ostream& operator<<(std::ostream &os, const Message::Address &msga) { +std::ostream& operator<<(std::ostream &os, const Address &msga) { os << msga.Name.c_str() << " <" << msga.Email.c_str() << ">"; return os; } @@ -51,17 +51,27 @@ // Email / message field codes #define MFC_TO 0x01 // can occur multiple times +#define MFC_CC 0x02 // ditto +#define MFC_BCC 0x03 // ditto +#define MFC_SENDER 0x04 #define MFC_FROM 0x05 +#define MFC_REPLY_TO 0x06 #define MFC_SUBJECT 0x0b #define MFC_BODY 0x0c +#define MFC_ATTACHMENT 0x16 #define MFC_END 0xffff FieldLink<Message> MessageFieldLinks[] = { - { MFC_TO, "To", 0, 0, 0, &Message::To, 0 }, - { MFC_FROM, "From", 0, 0, 0, &Message::From, 0 }, - { MFC_SUBJECT, "Subject", 0, 0, &Message::Subject, 0, 0 }, - { MFC_BODY, "Body", 0, 0, &Message::Body, 0, 0 }, - { MFC_END, "End of List",0, 0, 0, 0, 0 } + { MFC_TO, "To", 0, 0, 0, &Message::To, 0 }, + { MFC_CC, "Cc", 0, 0, 0, &Message::Cc, 0 }, + { MFC_BCC, "Bcc", 0, 0, 0, &Message::Bcc, 0 }, + { MFC_SENDER, "Sender", 0, 0, 0, &Message::Sender, 0 }, + { MFC_FROM, "From", 0, 0, 0, &Message::From, 0 }, + { MFC_REPLY_TO, "ReplyTo", 0, 0, 0, &Message::ReplyTo, 0 }, + { MFC_SUBJECT, "Subject", 0, 0, &Message::Subject, 0, 0 }, + { MFC_BODY, "Body", 0, 0, &Message::Body, 0, 0 }, + { MFC_ATTACHMENT, "Attachment", 0, 0, &Message::Attachment, 0, 0 }, + { MFC_END, "End of List", 0, 0, 0, 0, 0 } }; Message::Message() @@ -109,10 +119,17 @@ // assign second string, using first size as starting point a.Email = dual.c_str() + a.Name.size() + 1; + return begin; } } } + // if still not handled, add to the Unknowns list + UnknownField uf; + uf.type = field->type; + uf.data.assign((const char*)field->u.raw, btohs(field->size)); + Unknowns.push_back(uf); + return begin; } @@ -164,8 +181,17 @@ To.Email.clear(); Cc.Name.clear(); Cc.Email.clear(); + Bcc.Email.clear(); + Bcc.Name.clear(); + Sender.Name.clear(); + Sender.Email.clear(); + ReplyTo.Name.clear(); + ReplyTo.Email.clear(); Subject.clear(); Body.clear(); + Attachment.clear(); + + Unknowns.clear(); } // dump message in mbox format @@ -182,6 +208,12 @@ os << "To: " << To << "\n"; if( Cc.Email.size() ) os << "Cc: " << Cc << "\n"; + if( Bcc.Email.size() ) + os << "Bcc: " << Bcc << "\n"; + if( Sender.Email.size() ) + os << "Sender: " << Sender << "\n"; + if( ReplyTo.Email.size()) + os << "Reply To: " << ReplyTo << "\n"; if( Subject.size() ) os << "Subject: " << Subject << "\n"; os << "\n"; @@ -194,6 +226,11 @@ else os << *i; } + os << "\n"; + if( Attachment.size() ) + os << "Attachments: " << Attachment << "\n"; + + os << Unknowns; os << "\n\n"; } Index: src/s11n-boost.h =================================================================== RCS file: /cvsroot/barry/barry/src/s11n-boost.h,v retrieving revision 1.6 diff -u -r1.6 s11n-boost.h --- src/s11n-boost.h 27 May 2007 17:19:25 -0000 1.6 +++ src/s11n-boost.h 1 Jun 2007 10:37:21 -0000 @@ -113,7 +113,7 @@ } template <class ArchiveT> -void serialize(ArchiveT &ar, Barry::Message::Address &a, const unsigned int ver) +void serialize(ArchiveT &ar, Barry::Address &a, const unsigned int ver) { ar & make_nvp("Name", a.Name); ar & make_nvp("Email", a.Email); @@ -125,8 +125,11 @@ ar & make_nvp("From", m.From); ar & make_nvp("To", m.To); ar & make_nvp("Cc", m.Cc); + ar & make_nvp("Sender", m.Sender); + ar & make_nvp("ReplyTo", m.ReplyTo); ar & make_nvp("Subject", m.Subject); ar & make_nvp("Body", m.Body); + ar & make_nvp("Attachment", m.Attachment); if( ver < BARRY_POD_MAP_VERSION ) { ar & make_nvp("Unknowns", m.Unknowns); @@ -216,6 +219,21 @@ } } +template<class ArchiveT> +void serialize(ArchiveT &ar, Barry::PINMessage &p, const unsigned int ver) +{ + ar & make_nvp("From", p.From); + ar & make_nvp("To", p.To); + ar & make_nvp("Cc", p.Cc); + ar & make_nvp("Bcc", p.Bcc); + ar & make_nvp("Subject", p.Subject); + ar & make_nvp("Body", p.Body); + + if(ver < BARRY_POD_MAP_VERSION) { + ar & make_nvp("Unknowns", p.Unknowns); + } +} + }} // namespace boost::serialization #endif Index: src/record.h =================================================================== RCS file: /cvsroot/barry/barry/src/record.h,v retrieving revision 1.23 diff -u -r1.23 record.h --- src/record.h 25 May 2007 21:29:00 -0000 1.23 +++ src/record.h 1 Jun 2007 10:37:20 -0000 @@ -174,6 +174,11 @@ }; std::ostream& operator<< (std::ostream &os, const std::vector<UnknownField> &unknowns); +typedef struct Address +{ + std::string Name; + std::string Email; +}; /// \addtogroup RecordParserClasses /// Parser and data storage classes. These classes take a @@ -193,6 +198,7 @@ #include "r_message.h" #include "r_servicebook.h" #include "r_task.h" +#include "r_pin_message.h" #endif Index: src/Makefile.am =================================================================== RCS file: /cvsroot/barry/barry/src/Makefile.am,v retrieving revision 1.15 diff -u -r1.15 Makefile.am --- src/Makefile.am 25 May 2007 21:29:00 -0000 1.15 +++ src/Makefile.am 1 Jun 2007 10:37:20 -0000 @@ -68,6 +68,7 @@ r_message.h \ r_servicebook.h \ r_task.h \ + r_pin_message.h \ socket.h \ time.h \ usbwrap.h \ @@ -93,6 +94,7 @@ r_message.cc \ r_servicebook.cc \ r_task.cc \ + r_pin_message.cc packet.cc packet.h \ controller.cc \ version.cc \ Index: tools/btool.cc =================================================================== RCS file: /cvsroot/barry/barry/tools/btool.cc,v retrieving revision 1.16 diff -u -r1.16 btool.cc --- tools/btool.cc 27 May 2007 17:19:25 -0000 1.16 +++ tools/btool.cc 1 Jun 2007 10:37:21 -0000 @@ -229,6 +229,11 @@ new RecordParser<Task, Store<Task> > ( new Store<Task>(filename, false ))); } + else if( name == "PIN Messages" ) { + return auto_ptr<Parser>( + new RecordParser<PINMessage, Store<PINMessage> > ( + new Store<PINMessage>(filename, false ))); + } else { // unknown database, use null parser return auto_ptr<Parser>( new DataDumpParser ); Index: src/r_pin_message.cc =================================================================== RCS file: src/r_pin_message.cc diff -N src/r_pin_message.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/r_pin_message.cc 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,240 @@ +/// +/// \file r_pin_message.cc +/// Blackberry database record parser class for pin message records. +/// + +/* + Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/) + Copyright (C) 2007, Brian Edginton ([EMAIL PROTECTED]) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#include "r_pin_message.h" +#include "record-internal.h" +#include "protocol.h" +#include "protostructs.h" +#include "data.h" +#include "time.h" +#include "error.h" +#include "endian.h" +#include <ostream> +#include <iomanip> +#include <time.h> +#include <stdexcept> + +#define __DEBUG_MODE__ +#include "debug.h" + +using namespace std; +using namespace Barry::Protocol; + +namespace Barry { + +//std::ostream& operator<<(std::ostream &os, const Address &msgp) { +// os << msgp.Name.c_str() << " <" << msgp.Email.c_str() << ">"; +// return os; +//} + +/////////////////////////////////////////////////////////////////////////////// +// PINMessage class + + +// PIN message field codes +#define PNMFC_TO 0x01 // can occur multiple times +#define PNMFC_CC 0x02 // ditto +#define PNMFC_BCC 0x03 // ditto +#define PNMFC_FROM 0x05 +#define PNMFC_SUBJECT 0x0b +#define PNMFC_BODY 0x0c +#define PNMFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber +#define PNMFC_END 0xffff + +FieldLink<PINMessage> PINMessageFieldLinks[] = { + { PNMFC_TO, "To", 0, 0, 0, &PINMessage::To, 0 }, + { PNMFC_CC, "Cc", 0, 0, 0, &PINMessage::Cc, 0 }, + { PNMFC_BCC, "Bcc", 0, 0, 0, &PINMessage::Bcc, 0 }, + { PNMFC_FROM, "From", 0, 0, 0, &PINMessage::From, 0 }, + { PNMFC_SUBJECT "Subject", 0, 0, &PINMessage::Subject, 0, 0 }, + { PNMFC_BODY, "Body", 0, 0, &PINMessage::Body, 0, 0 }, + { PNMFC_END, "End of List", 0, 0, 0, 0, 0 } +}; + +PINMessage::PINMessage() +{ +} + +PINMessage::~PINMessage() +{ +} + +const unsigned char* PINMessage::ParseField(const unsigned char *begin, + const unsigned char *end) +{ + const CommonField *field = (const CommonField *) begin; + + // advance and check size + begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size); + if( begin > end ) // if begin==end, we are ok + return begin; + + if( !btohs(field->size) ) // if field has no size, something's up + return begin; + + // cycle through the type table + for( FieldLink<PINMessage> *b = PINMessageFieldLinks; + b->type != PNMFC_END; + b++ ) + { + if( b->type == field->type ) { + if( b->strMember ) { + // parse regular string + std::string &s = this->*(b->strMember); + s.assign((const char *)field->u.raw, btohs(field->size)-1); + return begin; // done! + } + else if( b->addrMember ) { + // parse email address + // get dual name+addr string first + const char *fa = (const char*)field->u.addr.addr; + std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown)); + + // assign first string, using null terminator...letting std::string add it for us if it doesn't exist + Address &a = this->*(b->addrMember); + a.Name = dual.c_str(); + + // assign second string, using first size as starting point + a.Email = dual.c_str() + a.Name.size() + 1; + return begin; + } + } + } + // handle special cases + switch( field->type ) + { + case PNMFC_RECORDID: + MessageRecordId = field->u.min1900; // not really time, but we need easy access to an int + return begin; + } + // if still not handled, add to the Unknowns list + UnknownField uf; + uf.type = field->type; + uf.data.assign((const char*)field->u.raw, btohs(field->size)); + Unknowns.push_back(uf); + + return begin; +} + +uint8_t PINMessage::GetRecType() const +{ + throw std::logic_error("PINMessage::GetRecType() called, and not supported by the USB protocol. Should never get called."); +} + +// empty API, not required by protocol +uint32_t PINMessage::GetUniqueId() const +{ + throw std::logic_error("PINMessage::GetUniqueId() called, and not supported by the USB protocol. Should never get called."); +} + +// empty API, not required by protocol +void PINMessage::SetIds(uint8_t Type, uint32_t Id) +{ + // accept it without complaining, just do nothing +} + +void PINMessage::ParseHeader(const Data &data, size_t &offset) +{ + // we skip the "header" since we don't know what to do with it yet + offset += MESSAGE_RECORD_HEADER_SIZE; +} + +void PINMessage::ParseFields(const Data &data, size_t &offset) +{ + const unsigned char *finish = ParseCommonFields(*this, + data.GetData() + offset, data.GetData() + data.GetSize()); + offset += finish - (data.GetData() + offset); +} + +void PINMessage::BuildHeader(Data &data, size_t &offset) const +{ + throw std::logic_error("PINMessage::BuildHeader not yet implemented"); +} + +void PINMessage::BuildFields(Data &data, size_t &offset) const +{ + throw std::logic_error("PINMessage::BuildFields not yet implemented"); +} + +void PINMessage::Clear() +{ + + From.Name.clear(); + From.Email.clear(); + + To.Name.clear(); + To.Email.clear(); + + Cc.Name.clear(); + Cc.Email.clear(); + + Bcc.Name.clear(); + Bcc.Email.clear(); + + Subject.clear(); + Body.clear(); + MessageRecordId = 0; + + Unknowns.clear(); +} + +// dump message in mbox format +void PINMessage::Dump(std::ostream &os) const +{ + os << "Record ID (" << MessageRecordId << ")\n"; + if( From.Name.size()) { + os << " From: " << From.Name << " <" << From.Email << ">\n"; + } + if( To.Name.size()) { + os << " To: " << To.Name << " <" << To.Email << ">\n"; + } + if( Cc.Name.size()) { + os << " Cc: " << Cc.Name << " <" << Cc.Email << ">\n"; + } + if( Bcc.Name.size()) { + os << " Bcc: " << Bcc.Name << " <" << Bcc.Email << ">\n"; + } + + if( Subject.size() ) + os << " Subject: " << Subject << "\n"; + else + os << " Subject: <>\n"; + os << "\n"; + + for( std::string::const_iterator i = Body.begin(); + i != Body.end() && *i; + i++) + { + if( *i == '\r' ) + os << '\n'; + else + os << *i; + } + os << "\n"; + + os << Unknowns; + os << "\n\n"; +} + + +} // namespace Barry + Index: src/r_pin_message.h =================================================================== RCS file: src/r_pin_message.h diff -N src/r_pin_message.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/r_pin_message.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,99 @@ +/// +/// \file r_pin_message.h +/// Blackberry database record parser class for pin message records. +/// + +/* + Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/) + Copyright (C) 2007, Brian Edginton ([EMAIL PROTECTED]) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#ifndef __BARRY_RECORD_PIN_MESSAGE_H__ +#define __BARRY_RECORD_PIN_MESSAGE_H__ + +#include "record.h" +#include <iosfwd> +#include <string> +#include <vector> +#include <map> +#include <stdint.h> + +namespace Barry { + +// +// NOTE: All classes here must be container-safe! Perhaps add sorting +// operators in the future. +// + +/// \addtogroup RecordParserClasses +/// @{ + +class PINMessage +{ +public: + + Address From; + Address To; + Address Cc; + Address Bcc; + std::string Subject; + std::string Body; + uint32_t MessageRecordId; + std::vector<UnknownField> Unknowns; + +public: + const unsigned char* ParseField(const unsigned char *begin, + const unsigned char *end); + +public: + PINMessage(); + ~PINMessage(); + + // 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 ParseHeader(const Data &data, size_t &offset); + void ParseFields(const Data &data, size_t &offset); + void BuildHeader(Data &data, size_t &offset) const; + void BuildFields(Data &data, size_t &offset) const; + + void Clear(); + + void Dump(std::ostream &os) const; + + // sorting + bool operator<(const PINMessage &other) const { return Subject < other.Subject; } + + // database name + static const char * GetDBName() { return "PIN Messages"; } + static uint8_t GetDefaultRecType() { return 0; } +}; + +inline std::ostream& operator<<(std::ostream &os, const PINMessage &msg) { + msg.Dump(os); + return os; +} + +std::ostream& operator<<(std::ostream &os, const Address &msga); + + +/// @} + +} // namespace Barry + +#endif // __BARRY_RECORD_PIN_MESSAGE_H__ + +
pgpnDmntKAVHS.pgp
Description: PGP signature
------------------------------------------------------------------------- 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