- changed PKG_CONFIG_PATH setting in rpm script, so that systems
[barry.git] / src / r_pin_message.cc
blobb1e8e9a09842648b608f4ad2c112be14817f6941
1 ///
2 /// \file r_pin_message.cc
3 /// Blackberry database record parser class for pin message records.
4 ///
6 /*
7 Copyright (C) 2005-2007, Net Direct Inc. (http://www.netdirect.ca/)
8 Copyright (C) 2007, Brian Edginton (edge@edginton.net)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "r_pin_message.h"
24 #include "record-internal.h"
25 #include "protocol.h"
26 #include "protostructs.h"
27 #include "data.h"
28 #include "time.h"
29 #include "error.h"
30 #include "endian.h"
31 #include <ostream>
32 #include <iomanip>
33 #include <time.h>
34 #include <stdexcept>
36 #define __DEBUG_MODE__
37 #include "debug.h"
39 using namespace std;
40 using namespace Barry::Protocol;
42 namespace Barry {
44 //std::ostream& operator<<(std::ostream &os, const Address &msgp) {
45 // os << msgp.Name.c_str() << " <" << msgp.Email.c_str() << ">";
46 // return os;
47 //}
49 ///////////////////////////////////////////////////////////////////////////////
50 // PINMessage class
53 // PIN message field codes
54 #define PNMFC_TO 0x01 // can occur multiple times
55 #define PNMFC_CC 0x02 // ditto
56 #define PNMFC_BCC 0x03 // ditto
57 #define PNMFC_FROM 0x05
58 #define PNMFC_SUBJECT 0x0b
59 #define PNMFC_BODY 0x0c
60 #define PNMFC_RECORDID 0x4b // Internal Message ID, mimics header RecNumber
61 #define PNMFC_END 0xffff
63 FieldLink<PINMessage> PINMessageFieldLinks[] = {
64 { PNMFC_TO, "To", 0, 0, 0, &PINMessage::To, 0 },
65 { PNMFC_CC, "Cc", 0, 0, 0, &PINMessage::Cc, 0 },
66 { PNMFC_BCC, "Bcc", 0, 0, 0, &PINMessage::Bcc, 0 },
67 { PNMFC_FROM, "From", 0, 0, 0, &PINMessage::From, 0 },
68 { PNMFC_SUBJECT, "Subject", 0, 0, &PINMessage::Subject, 0, 0 },
69 { PNMFC_BODY, "Body", 0, 0, &PINMessage::Body, 0, 0 },
70 { PNMFC_END, "End of List", 0, 0, 0, 0, 0 }
73 PINMessage::PINMessage()
77 PINMessage::~PINMessage()
81 const unsigned char* PINMessage::ParseField(const unsigned char *begin,
82 const unsigned char *end)
84 const CommonField *field = (const CommonField *) begin;
86 // advance and check size
87 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
88 if( begin > end ) // if begin==end, we are ok
89 return begin;
91 if( !btohs(field->size) ) // if field has no size, something's up
92 return begin;
94 // cycle through the type table
95 for( FieldLink<PINMessage> *b = PINMessageFieldLinks;
96 b->type != PNMFC_END;
97 b++ )
99 if( b->type == field->type ) {
100 if( b->strMember ) {
101 // parse regular string
102 std::string &s = this->*(b->strMember);
103 s.assign((const char *)field->u.raw, btohs(field->size)-1);
104 return begin; // done!
106 else if( b->addrMember ) {
107 // parse email address
108 // get dual name+addr string first
109 const char *fa = (const char*)field->u.addr.addr;
110 std::string dual(fa, btohs(field->size) - sizeof(field->u.addr.unknown));
112 // assign first string, using null terminator...letting std::string add it for us if it doesn't exist
113 Address &a = this->*(b->addrMember);
114 a.Name = dual.c_str();
116 // assign second string, using first size as starting point
117 a.Email = dual.c_str() + a.Name.size() + 1;
118 return begin;
123 // handle special cases
124 switch( field->type )
126 case PNMFC_RECORDID:
127 MessageRecordId = field->u.uint32;
128 return begin;
131 // if still not handled, add to the Unknowns list
132 UnknownField uf;
133 uf.type = field->type;
134 uf.data.assign((const char*)field->u.raw, btohs(field->size));
135 Unknowns.push_back(uf);
137 return begin;
140 void PINMessage::ParseHeader(const Data &data, size_t &offset)
142 // we skip the "header" since we don't know what to do with it yet
143 // FIXME - we are using a Message (email) record header size
144 // for a PIN Message record... this is not necessarily guaranteed
145 // to be the same... someday we could use some more info on
146 // the message record header and pin message record header
147 offset += MESSAGE_RECORD_HEADER_SIZE;
150 void PINMessage::ParseFields(const Data &data, size_t &offset)
152 const unsigned char *finish = ParseCommonFields(*this,
153 data.GetData() + offset, data.GetData() + data.GetSize());
154 offset += finish - (data.GetData() + offset);
157 void PINMessage::BuildHeader(Data &data, size_t &offset) const
159 throw std::logic_error("PINMessage::BuildHeader not yet implemented");
162 void PINMessage::BuildFields(Data &data, size_t &offset) const
164 throw std::logic_error("PINMessage::BuildFields not yet implemented");
167 void PINMessage::Clear()
169 From.clear();
170 To.clear();
171 Cc.clear();
172 Bcc.clear();
174 Subject.clear();
175 Body.clear();
176 MessageRecordId = 0;
178 Unknowns.clear();
181 // dump message in mbox format
182 void PINMessage::Dump(std::ostream &os) const
184 // FIXME - use current time until we figure out the date headers
185 time_t fixme = time(NULL);
187 os << "From " << (From.Email.size() ? From.Email.c_str() : "unknown")
188 << " " << ctime(&fixme);
189 os << "X-Record-ID: (" << std::hex << MessageRecordId << ")\n";
190 if( From.Name.size()) {
191 os << " From: " << From.Name << " <" << From.Email << ">\n";
193 if( To.Name.size()) {
194 os << " To: " << To.Name << " <" << To.Email << ">\n";
196 if( Cc.Name.size()) {
197 os << " Cc: " << Cc.Name << " <" << Cc.Email << ">\n";
199 if( Bcc.Name.size()) {
200 os << " Bcc: " << Bcc.Name << " <" << Bcc.Email << ">\n";
203 if( Subject.size() )
204 os << " Subject: " << Subject << "\n";
205 else
206 os << " Subject: <>\n";
207 os << "\n";
209 for( std::string::const_iterator i = Body.begin();
210 i != Body.end() && *i;
211 i++)
213 if( *i == '\r' )
214 os << '\n';
215 else
216 os << *i;
218 os << "\n";
220 os << Unknowns;
221 os << "\n\n";
225 } // namespace Barry