- refactored record parser classes into separate files for each
[barry.git] / src / r_message.cc
blobbeee0204d45f29b99f8dabe451f20570dd950904
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 Message::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_FROM 0x05
55 #define MFC_SUBJECT 0x0b
56 #define MFC_BODY 0x0c
57 #define MFC_END 0xffff
59 FieldLink<Message> MessageFieldLinks[] = {
60 { MFC_TO, "To", 0, 0, 0, &Message::To, 0 },
61 { MFC_FROM, "From", 0, 0, 0, &Message::From, 0 },
62 { MFC_SUBJECT, "Subject", 0, 0, &Message::Subject, 0, 0 },
63 { MFC_BODY, "Body", 0, 0, &Message::Body, 0, 0 },
64 { MFC_END, "End of List",0, 0, 0, 0, 0 }
67 Message::Message()
71 Message::~Message()
75 const unsigned char* Message::ParseField(const unsigned char *begin,
76 const unsigned char *end)
78 const CommonField *field = (const CommonField *) begin;
80 // advance and check size
81 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
82 if( begin > end ) // if begin==end, we are ok
83 return begin;
85 if( !btohs(field->size) ) // if field has no size, something's up
86 return begin;
88 // cycle through the type table
89 for( FieldLink<Message> *b = MessageFieldLinks;
90 b->type != MFC_END;
91 b++ )
93 if( b->type == field->type ) {
94 if( b->strMember ) {
95 // parse regular string
96 std::string &s = this->*(b->strMember);
97 s.assign((const char *)field->u.raw, btohs(field->size)-1);
98 return begin; // done!
100 else if( b->addrMember ) {
101 // parse email address
102 // get dual name+addr string first
103 const char *fa = (const char*)field->u.addr.addr;
104 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
106 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
107 Address &a = this->*(b->addrMember);
108 a.Name = dual.c_str();
110 // assign second string, using first size as starting point
111 a.Email = dual.c_str() + a.Name.size() + 1;
116 return begin;
119 uint8_t Message::GetRecType() const
121 throw std::logic_error("Message::GetRecType() called, and not supported by the USB protocol. Should never get called.");
124 // empty API, not required by protocol
125 uint32_t Message::GetUniqueId() const
127 throw std::logic_error("Message::GetUniqueId() called, and not supported by the USB protocol. Should never get called.");
130 // empty API, not required by protocol
131 void Message::SetIds(uint8_t Type, uint32_t Id)
133 // accept it without complaining, just do nothing
136 void Message::ParseHeader(const Data &data, size_t &offset)
138 // we skip the "header" since we don't know what to do with it yet
139 offset += MESSAGE_RECORD_HEADER_SIZE;
142 void Message::ParseFields(const Data &data, size_t &offset)
144 const unsigned char *finish = ParseCommonFields(*this,
145 data.GetData() + offset, data.GetData() + data.GetSize());
146 offset += finish - (data.GetData() + offset);
149 void Message::BuildHeader(Data &data, size_t &offset) const
151 throw std::logic_error("Message::BuildHeader not yet implemented");
154 void Message::BuildFields(Data &data, size_t &offset) const
156 throw std::logic_error("Message::BuildFields not yet implemented");
159 void Message::Clear()
161 From.Name.clear();
162 From.Email.clear();
163 To.Name.clear();
164 To.Email.clear();
165 Cc.Name.clear();
166 Cc.Email.clear();
167 Subject.clear();
168 Body.clear();
171 // dump message in mbox format
172 void Message::Dump(std::ostream &os) const
174 // FIXME - use current time until we figure out the date headers
175 time_t fixme = time(NULL);
177 os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
178 << " " << ctime(&fixme);
179 os << "Date: " << ctime(&fixme);
180 os << "From: " << From << "\n";
181 if( To.Email.size() )
182 os << "To: " << To << "\n";
183 if( Cc.Email.size() )
184 os << "Cc: " << Cc << "\n";
185 if( Subject.size() )
186 os << "Subject: " << Subject << "\n";
187 os << "\n";
188 for( std::string::const_iterator i = Body.begin();
189 i != Body.end() && *i;
190 i++)
192 if( *i == '\r' )
193 os << '\n';
194 else
195 os << *i;
197 os << "\n\n";
201 } // namespace Barry