Added passing through name to number lookup for resolving numbers in exported events.
[qwerkisync] / EventParsers / VMGEntities / VMessage.cpp
1 /*
2  * Copyright (C) 2011, Jamie Thompson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License as published by the Free Software Foundation; either
7  * version 3 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; If not, see
16  * <http://www.gnu.org/licenses/>.
17  */
18
19 #include "VMessage.h"
20
21 #include "EventTypes/SMS.h"
22 #include "Factory.h"
23 #include "Settings.h"
24 #include "VBody.h"
25 #include "VCard.h"
26 #include "VEnvelope.h"
27
28 #include <QDateTime>
29 #include <QTextStream>
30
31 #include <QDebug>
32
33 using namespace EventParsers::VMGEntities;
34
35 VMessage::VMessage(const Settings &settings, const SMSEntity *parent) :
36         SMSEntity(settings, parent), m_Version(1.1)
37 {
38 }
39
40 //VMessage::VMessage(QTextStream& stream)
41 //{
42 //}
43
44 VMessage::VMessage(const Settings &settings, const SMSEntity *parent, float version) :
45         SMSEntity(settings, parent), m_Version(version)
46 {
47 }
48
49 VMessage::~VMessage()
50 {
51 }
52
53 bool VMessage::Read(const QString &initialLine, QTextStream &stream, EventTypes::SMS &event)
54 {
55         if(getParent() != NULL)
56         {
57                 qDebug() << "Messages cannot be nested.";
58                 return false;
59         }
60
61         bool hasEnded(false);
62         float version(0);
63
64         // Stream may or may not have a 'BEGIN' present. Swallow it if it's ours.
65         QString lineData(initialLine.length() > 0 ? initialLine : stream.readLine());
66         if(lineData.startsWith("BEGIN:"))
67         {
68                 if(lineData != QString("BEGIN:") + getTagName())
69                 {
70                         qDebug() << "Invalid stream";
71                         return false;
72                 }
73                 else // ...discard this line
74                         lineData = stream.readLine();
75         }
76
77         do
78         {
79                 if(lineData.startsWith("VERSION:"))
80                 {
81                         version = lineData.mid(lineData.indexOf(":")+1).toFloat();
82                 }
83                 else if(lineData.startsWith("X-IRMC-STATUS:"))
84                 {
85                         bool isRead(lineData.mid(lineData.indexOf(":") + 1) == "READ");
86                         event.IsRead(isRead);
87                 }
88                 else if(lineData.startsWith("X-IRMC-BOX:"))
89                 {
90                         QString box = lineData.mid(lineData.indexOf(":") + 1);
91                         bool isOutgoing(box == "SENT");
92
93                         // Early out once we know we're not processing this type of message
94                         if((!isOutgoing && !CurrentSettings().ShouldProcess(Settings::INCOMING, EventTypes::EVENT_TYPE_SMS))
95                                 || isOutgoing && !CurrentSettings().ShouldProcess(Settings::OUTGOING, EventTypes::EVENT_TYPE_SMS))
96                         {
97                                 return false;
98                         }
99
100                         if (isOutgoing == false && box != "INBOX")
101                         {
102                                 qDebug() << "Unexpected box: " << box;
103                                 return false;
104                         }
105                         event.Destination(isOutgoing ? EventTypes::SMS::SENT : EventTypes::SMS::INBOX);
106                 }
107                 else if(lineData.startsWith("X-NOK-DT:"))
108                 {
109                         QDateTime timestamp(QDateTime::fromString(
110                                 lineData.mid(lineData.indexOf(":") + 1),
111                                 "yyyyMMddThhmmssZ"));
112                         timestamp.setTimeSpec(Qt::UTC);
113                         event.Timestamp(timestamp);
114                 }
115                 else if(lineData.startsWith("BEGIN:"))
116                 {
117                         iReader* reader = Factory::Instantiate(CurrentSettings(), lineData, this);
118                         bool valid(NULL != reader && reader->Read(lineData, stream, event));
119                         delete reader;
120
121                         // Quit processing if the nested content is not valid
122                         if(!valid)
123                                 return valid;
124                 }
125                 else if(lineData.startsWith("END:"))
126                 {
127                         if(lineData != "END:VMSG")
128                         {
129                                 qDebug() << getTagName() << " parser mismatch error" << lineData;
130                                 return false;
131                         }
132                         else
133                         {
134                                 hasEnded = true;
135                                 break;
136                         }
137                 }
138
139                 lineData = stream.readLine();
140         }while(!hasEnded && !stream.atEnd());
141
142         return true;
143 }
144
145 void VMessage::Write(QTextStream &stream, const EventTypes::SMS &event, const NumberToNameLookup &numberToNameLookup)
146 {
147         stream << "BEGIN:VMSG\n";
148         stream << "VERSION:" << m_Version << "\n";
149         stream << "X-IRMC-STATUS:" << ( event.IsRead() ? "READ" : "") << "\n";
150         stream << "X-IRMC-BOX:" << ( event.Destination() == EventTypes::SMS::SENT ? "SENT" : "INBOX") << "\n";
151         stream << "X-NOK-DT:" << event.Timestamp().toUTC().toString("yyyyMMddThhmmssZ") << "\n";
152
153         VEnvelope msgEnvelope(CurrentSettings(), this);
154
155         // Add in the empty vcard for outgoing messages
156         if(event.Destination() == EventTypes::SMS::SENT)
157         {
158                 VCard(CurrentSettings(), this, 2.1, VCard::VCARD_LOCAL).Write(stream, event, numberToNameLookup);
159
160                 msgEnvelope.getContentWriters().append(new VCard(CurrentSettings(), &msgEnvelope, 2.1, VCard::VCARD_REMOTE));
161
162                 VEnvelope *bodyEnvelope = new VEnvelope(CurrentSettings(), this);
163                 bodyEnvelope->getContentWriters().append(new VBody(CurrentSettings(), bodyEnvelope));
164                 msgEnvelope.getContentWriters().append(bodyEnvelope);
165         }
166         else
167         {
168                 VCard(CurrentSettings(), this, 2.1, VCard::VCARD_REMOTE).Write(stream, event, numberToNameLookup);
169
170                 msgEnvelope.getContentWriters().append(new VBody(CurrentSettings(), &msgEnvelope));
171         }
172
173         msgEnvelope.Write(stream, event, numberToNameLookup);
174
175         stream << "END:VMSG\n";
176 }