- applied patch from Niels de Vos fixing debian package build dependency
[barry.git] / src / r_message.cc
blob3eaca5eebfd9d9c0059688f73f02f1654d1ce6bd
1 ///
2 /// \file r_message.cc
3 /// Blackberry database record parser class for email records.
4 ///
6 /*
7 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "r_message.h"
23 #include "record-internal.h"
24 #include "protocol.h"
25 #include "protostructs.h"
26 #include "data.h"
27 #include "time.h"
28 #include "error.h"
29 #include "endian.h"
30 #include <ostream>
31 #include <iomanip>
32 #include <time.h>
33 #include <stdexcept>
35 #define __DEBUG_MODE__
36 #include "debug.h"
38 using namespace std;
39 using namespace Barry::Protocol;
41 namespace Barry {
43 std::ostream& operator<<(std::ostream &os, const Address &msga) {
44 os << msga.Name.c_str() << " <" << msga.Email.c_str() << ">";
45 return os;
48 ///////////////////////////////////////////////////////////////////////////////
49 // Message class
52 // Email / message field codes
53 #define MFC_TO 0x01 // can occur multiple times
54 #define MFC_CC 0x02 // ditto
55 #define MFC_BCC 0x03 // ditto
56 #define MFC_SENDER 0x04
57 #define MFC_FROM 0x05
58 #define MFC_REPLY_TO 0x06
59 #define MFC_SUBJECT 0x0b
60 #define MFC_BODY 0x0c
61 #define MFC_ATTACHMENT 0x16
62 #define MFC_END 0xffff
64 FieldLink<Message> MessageFieldLinks[] = {
65 { MFC_TO, "To", 0, 0, 0, &Message::To, 0 },
66 { MFC_CC, "Cc", 0, 0, 0, &Message::Cc, 0 },
67 { MFC_BCC, "Bcc", 0, 0, 0, &Message::Bcc, 0 },
68 { MFC_SENDER, "Sender", 0, 0, 0, &Message::Sender, 0 },
69 { MFC_FROM, "From", 0, 0, 0, &Message::From, 0 },
70 { MFC_REPLY_TO, "ReplyTo", 0, 0, 0, &Message::ReplyTo, 0 },
71 { MFC_SUBJECT, "Subject", 0, 0, &Message::Subject, 0, 0 },
72 { MFC_BODY, "Body", 0, 0, &Message::Body, 0, 0 },
73 { MFC_ATTACHMENT, "Attachment", 0, 0, &Message::Attachment, 0, 0 },
74 { MFC_END, "End of List", 0, 0, 0, 0, 0 }
77 Message::Message()
81 Message::~Message()
85 const unsigned char* Message::ParseField(const unsigned char *begin,
86 const unsigned char *end)
88 const CommonField *field = (const CommonField *) begin;
90 // advance and check size
91 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
92 if( begin > end ) // if begin==end, we are ok
93 return begin;
95 if( !btohs(field->size) ) // if field has no size, something's up
96 return begin;
98 // cycle through the type table
99 for( FieldLink<Message> *b = MessageFieldLinks;
100 b->type != MFC_END;
101 b++ )
103 if( b->type == field->type ) {
104 if( b->strMember ) {
105 // parse regular string
106 std::string &s = this->*(b->strMember);
107 s.assign((const char *)field->u.raw, btohs(field->size)-1);
108 return begin; // done!
110 else if( b->addrMember ) {
111 // parse email address
112 // get dual name+addr string first
113 const char *fa = (const char*)field->u.addr.addr;
114 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
116 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
117 Address &a = this->*(b->addrMember);
118 a.Name = dual.c_str();
120 // assign second string, using first size as starting point
121 a.Email = dual.c_str() + a.Name.size() + 1;
122 return begin;
127 // if still not handled, add to the Unknowns list
128 UnknownField uf;
129 uf.type = field->type;
130 uf.data.assign((const char*)field->u.raw, btohs(field->size));
131 Unknowns.push_back(uf);
133 return begin;
136 uint8_t Message::GetRecType() const
138 throw std::logic_error("Message::GetRecType() called, and not supported by the USB protocol. Should never get called.");
141 // empty API, not required by protocol
142 uint32_t Message::GetUniqueId() const
144 throw std::logic_error("Message::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
147 // empty API, not required by protocol
148 void Message::SetIds(uint8_t Type, uint32_t Id)
150 // accept it without complaining, just do nothing
153 void Message::ParseHeader(const Data &data, size_t &offset)
155 // we skip the "header" since we don't know what to do with it yet
156 offset += MESSAGE_RECORD_HEADER_SIZE;
159 void Message::ParseFields(const Data &data, size_t &offset)
161 const unsigned char *finish = ParseCommonFields(*this,
162 data.GetData() + offset, data.GetData() + data.GetSize());
163 offset += finish - (data.GetData() + offset);
166 void Message::BuildHeader(Data &data, size_t &offset) const
168 throw std::logic_error("Message::BuildHeader not yet implemented");
171 void Message::BuildFields(Data &data, size_t &offset) const
173 throw std::logic_error("Message::BuildFields not yet implemented");
176 void Message::Clear()
178 From.clear();
179 To.clear();
180 Cc.clear();
181 Bcc.clear();
182 Sender.clear();
183 ReplyTo.clear();
184 Subject.clear();
185 Body.clear();
186 Attachment.clear();
188 Unknowns.clear();
191 // dump message in mbox format
192 void Message::Dump(std::ostream &os) const
194 // FIXME - use current time until we figure out the date headers
195 time_t fixme = time(NULL);
197 os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
198 << " " << ctime(&fixme);
199 os << "Date: " << ctime(&fixme);
200 os << "From: " << From << "\n";
201 if( To.Email.size() )
202 os << "To: " << To << "\n";
203 if( Cc.Email.size() )
204 os << "Cc: " << Cc << "\n";
205 if( Bcc.Email.size() )
206 os << "Bcc: " << Bcc << "\n";
207 if( Sender.Email.size() )
208 os << "Sender: " << Sender << "\n";
209 if( ReplyTo.Email.size())
210 os << "Reply To: " << ReplyTo << "\n";
211 if( Subject.size() )
212 os << "Subject: " << Subject << "\n";
213 os << "\n";
214 for( std::string::const_iterator i = Body.begin();
215 i != Body.end() && *i;
216 i++)
218 if( *i == '\r' )
219 os << '\n';
220 else
221 os << *i;
223 os << "\n";
224 if( Attachment.size() )
225 os << "Attachments: " << Attachment << "\n";
227 os << Unknowns;
228 os << "\n\n";
232 } // namespace Barry