Pass the current settings down to the parsers so they can behave accordingly (i.e...
[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 "VCard.h"
25 #include "VEnvelope.h"
26 #include "VBody.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.setIsRead(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                         if (isOutgoing == false && box != "INBOX")
93                         {
94                                 qDebug() << "Unexpected box: " << box;
95                                 return false;
96                         }
97                         event.setDestination(isOutgoing ? EventTypes::SMS::SENT : EventTypes::SMS::INBOX);
98                 }
99                 else if(lineData.startsWith("X-NOK-DT:"))
100                 {
101                         QDateTime timestamp(QDateTime::fromString(
102                                 lineData.mid(lineData.indexOf(":") + 1),
103                                 "yyyyMMddThhmmssZ"));
104                         timestamp.setTimeSpec(Qt::UTC);
105                         event.setTimestamp(timestamp);
106                 }
107                 else if(lineData.startsWith("BEGIN:"))
108                 {
109                         iReader* reader = Factory::Instantiate(CurrentSettings(), lineData, this);
110                         bool valid(NULL != reader && reader->Read(lineData, stream, event));
111                         delete reader;
112
113                         // Quit processing if the nested content is not valid
114                         if(!valid)
115                                 return valid;
116                 }
117                 else if(lineData.startsWith("END:"))
118                 {
119                         if(lineData != "END:VMSG")
120                         {
121                                 qDebug() << getTagName() << " parser mismatch error" << lineData;
122                                 return false;
123                         }
124                         else
125                         {
126                                 hasEnded = true;
127                                 break;
128                         }
129                 }
130
131                 lineData = stream.readLine();
132         }while(!hasEnded && !stream.atEnd());
133
134         return true;
135 }
136
137 void VMessage::Write(QTextStream &stream, const EventTypes::SMS &event)
138 {
139         stream << "BEGIN:VMSG\n";
140         stream << "VERSION:" << m_Version << "\n";
141         stream << "X-IRMC-STATUS:" << ( event.IsRead() ? "READ" : "") << "\n";
142         stream << "X-IRMC-BOX:" << ( event.Destination() == EventTypes::SMS::SENT ? "SENT" : "INBOX") << "\n";
143         stream << "X-NOK-DT:" << event.Timestamp().toUTC().toString("yyyyMMddThhmmssZ") << "\n";
144
145         VEnvelope msgEnvelope(CurrentSettings(), this);
146
147         // Add in the empty vcard for outgoing messages
148         if(event.Destination() == EventTypes::SMS::SENT)
149         {
150                 VCard(CurrentSettings(), this, 2.1, VCard::VCARD_LOCAL).Write(stream, event);
151
152                 msgEnvelope.getContentWriters().append(new VCard(CurrentSettings(), &msgEnvelope, 2.1, VCard::VCARD_REMOTE));
153
154                 VEnvelope *bodyEnvelope = new VEnvelope(CurrentSettings(), this);
155                 bodyEnvelope->getContentWriters().append(new VBody(CurrentSettings(), bodyEnvelope));
156                 msgEnvelope.getContentWriters().append(bodyEnvelope);
157         }
158         else
159         {
160                 VCard(CurrentSettings(), this, 2.1, VCard::VCARD_REMOTE).Write(stream, event);
161
162                 msgEnvelope.getContentWriters().append(new VBody(CurrentSettings(), &msgEnvelope));
163         }
164
165         msgEnvelope.Write(stream, event);
166
167         stream << "END:VMSG\n";
168 }