59097d7a35c4530ac69fca87afca13efb1114f44
[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 "VCard.h"
24 #include "VEnvelope.h"
25 #include "VBody.h"
26
27 #include <QDateTime>
28 #include <QTextStream>
29
30 #include <QDebug>
31
32 using namespace EventParsers::VMGEntities;
33
34 VMessage::VMessage(const SMSEntity* parent) :
35         SMSEntity(parent), m_Version(1.1)
36 {
37 }
38
39 //VMessage::VMessage(QTextStream& stream)
40 //{
41 //}
42
43 VMessage::VMessage(const SMSEntity* parent, float version) :
44         SMSEntity(parent), m_Version(version)
45 {
46 }
47
48 VMessage::~VMessage()
49 {
50 }
51
52 bool VMessage::Read(const QString & initialLine, QTextStream & stream, EventTypes::SMS & event)
53 {
54         if(getParent() != NULL)
55         {
56                 qDebug() << "Messages cannot be nested.";
57                 return false;
58         }
59
60         bool hasEnded(false);
61         float version(0);
62
63         // Stream may or may not have a 'BEGIN' present. Swallow it if it's ours.
64         QString lineData(initialLine.length() > 0 ? initialLine : stream.readLine());
65         if(lineData.startsWith("BEGIN:"))
66         {
67                 if(lineData != QString("BEGIN:") + getTagName())
68                 {
69                         qDebug() << "Invalid stream";
70                         return false;
71                 }
72                 else // ...discard this line
73                         lineData = stream.readLine();
74         }
75
76         do
77         {
78                 if(lineData.startsWith("VERSION:"))
79                 {
80                         version = lineData.mid(lineData.indexOf(":")+1).toFloat();
81                 }
82                 else if(lineData.startsWith("X-IRMC-STATUS:"))
83                 {
84                         bool isRead(lineData.mid(lineData.indexOf(":") + 1) == "READ");
85                         event.setIsRead(isRead);
86                 }
87                 else if(lineData.startsWith("X-IRMC-BOX:"))
88                 {
89                         QString box = lineData.mid(lineData.indexOf(":") + 1);
90                         bool isOutgoing(box == "SENT");
91                         if (isOutgoing == false && box != "INBOX")
92                         {
93                                 qDebug() << "Unexpected box: " << box;
94                                 return false;
95                         }
96                         event.setDestination(isOutgoing ? EventTypes::SMS::SENT : EventTypes::SMS::INBOX);
97                 }
98                 else if(lineData.startsWith("X-NOK-DT:"))
99                 {
100                         QDateTime timestamp(QDateTime::fromString(
101                                 lineData.mid(lineData.indexOf(":") + 1),
102                                 "yyyyMMddThhmmssZ"));
103                         timestamp.setTimeSpec(Qt::UTC);
104                         event.setTimestamp(timestamp);
105                 }
106                 else if(lineData.startsWith("BEGIN:"))
107                 {
108                         iReader* reader = Factory::Instantiate(lineData, this);
109                         bool valid(NULL != reader && reader->Read(lineData, stream, event));
110                         delete reader;
111
112                         // Quit processing if the nested content is not valid
113                         if(!valid)
114                                 return valid;
115                 }
116                 else if(lineData.startsWith("END:"))
117                 {
118                         if(lineData != "END:VMSG")
119                         {
120                                 qDebug() << getTagName() << " parser mismatch error" << lineData;
121                                 return false;
122                         }
123                         else
124                         {
125                                 hasEnded = true;
126                                 break;
127                         }
128                 }
129
130                 lineData = stream.readLine();
131         }while(!hasEnded && !stream.atEnd());
132
133         return true;
134 }
135
136 void VMessage::Write(QTextStream &stream, const EventTypes::SMS &event)
137 {
138         stream << "BEGIN:VMSG\n";
139         stream << "VERSION:" << m_Version << "\n";
140         stream << "X-IRMC-STATUS:" << ( event.IsRead() ? "READ" : "") << "\n";
141         stream << "X-IRMC-BOX:" << ( event.Destination() == EventTypes::SMS::SENT ? "SENT" : "INBOX") << "\n";
142         stream << "X-NOK-DT:" << event.Timestamp().toUTC().toString("yyyyMMddThhmmssZ") << "\n";
143
144         VEnvelope msgEnvelope(this);
145
146         // Add in the empty vcard for outgoing messages
147         if(event.Destination() == EventTypes::SMS::SENT)
148         {
149                 VCard(this, 2.1, VCard::VCARD_LOCAL).Write(stream, event);
150
151                 msgEnvelope.getContentWriters().append(new VCard(&msgEnvelope, 2.1, VCard::VCARD_REMOTE));
152
153                 VEnvelope *bodyEnvelope = new VEnvelope(this);
154                 bodyEnvelope->getContentWriters().append(new VBody(bodyEnvelope));
155                 msgEnvelope.getContentWriters().append(bodyEnvelope);
156         }
157         else
158         {
159                 VCard(this, 2.1, VCard::VCARD_REMOTE).Write(stream, event);
160
161                 msgEnvelope.getContentWriters().append(new VBody(&msgEnvelope));
162         }
163
164         msgEnvelope.Write(stream, event);
165
166         stream << "END:VMSG\n";
167 }