/
report.cpp
194 lines (170 loc) · 6.53 KB
1
/*
2
* This file is part of buteo-sync-plugin-caldav package
3
4
5
6
*
* Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies).
*
* Contributors: Mani Chandrasekar <maninc@gmail.com>
7
* Stephan Rave <mail@stephanrave.de>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include "report.h"
#include "reader.h"
#include "settings.h"
#include <QNetworkAccessManager>
#include <QBuffer>
#include <QDebug>
#include <QStringList>
34
#include "logging.h"
35
36
37
#define PROP_URI "uri"
38
39
40
41
42
43
static const QString DateTimeFormat = QStringLiteral("yyyyMMddTHHmmss");
static const QString DateTimeFormatUTC = DateTimeFormat + QStringLiteral("Z");
static QString dateTimeToString(const QDateTime &dt)
{
if (dt.timeSpec() == Qt::UTC) {
44
return QLocale::c().toString(dt, DateTimeFormatUTC);
45
} else {
46
return QLocale::c().toString(dt, DateTimeFormat);
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
}
}
static QByteArray timeRangeFilterXml(const QDateTime &fromDateTime, const QDateTime &toDateTime)
{
QByteArray xml;
if (fromDateTime.isValid() || toDateTime.isValid()) {
xml = "<c:comp-filter name=\"VEVENT\"> <c:time-range ";
if (fromDateTime.isValid()) {
xml += "start=\"" + dateTimeToString(fromDateTime) + "\" ";
}
if (toDateTime.isValid()) {
xml += "end=\"" + dateTimeToString(toDateTime) + "\" ";
}
xml += " /></c:comp-filter>";
}
return xml;
}
67
Report::Report(QNetworkAccessManager *manager, Settings *settings, QObject *parent)
68
: Request(manager, settings, "REPORT", parent)
69
{
70
FUNCTION_CALL_TRACE(lcCalDavTrace);
71
72
}
73
void Report::getAllEvents(const QString &remoteCalendarPath, const QDateTime &fromDateTime, const QDateTime &toDateTime)
74
{
75
FUNCTION_CALL_TRACE(lcCalDavTrace);
76
sendCalendarQuery(remoteCalendarPath, fromDateTime, toDateTime, true);
77
78
}
79
void Report::getAllETags(const QString &remoteCalendarPath, const QDateTime &fromDateTime, const QDateTime &toDateTime)
80
{
81
FUNCTION_CALL_TRACE(lcCalDavTrace);
82
sendCalendarQuery(remoteCalendarPath, fromDateTime, toDateTime, false);
83
}
84
85
void Report::sendCalendarQuery(const QString &remoteCalendarPath,
86
87
88
89
const QDateTime &fromDateTime,
const QDateTime &toDateTime,
bool getCalendarData)
{
90
FUNCTION_CALL_TRACE(lcCalDavTrace);
91
92
93
QByteArray requestData = \
"<c:calendar-query xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">" \
"<d:prop>" \
94
95
96
97
98
99
"<d:getetag />";
if (getCalendarData) {
requestData += \
"<c:calendar-data />";
}
requestData += \
100
101
102
103
104
105
106
107
108
109
"</d:prop>"
"<c:filter>" \
"<c:comp-filter name=\"VCALENDAR\">";
if (fromDateTime.isValid() || toDateTime.isValid()) {
requestData.append(timeRangeFilterXml(fromDateTime, toDateTime));
}
requestData += \
"</c:comp-filter>" \
"</c:filter>" \
"</c:calendar-query>";
110
sendRequest(remoteCalendarPath, requestData);
111
112
}
113
void Report::multiGetEvents(const QString &remoteCalendarPath, const QStringList &eventHrefList)
114
{
115
FUNCTION_CALL_TRACE(lcCalDavTrace);
116
if (eventHrefList.isEmpty()) {
117
return;
118
}
119
120
QByteArray requestData = "<c:calendar-multiget xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">" \
121
"<d:prop><d:getetag /><c:calendar-data /></d:prop>";
122
for (const QString &eventHref : eventHrefList) {
123
requestData.append("<d:href>");
124
requestData.append(eventHref.toUtf8());
125
126
127
128
requestData.append("</d:href>");
}
requestData.append("</c:calendar-multiget>");
129
sendRequest(remoteCalendarPath, requestData);
130
131
mFetchedUris = eventHrefList;
132
}
133
134
void Report::sendRequest(const QString &remoteCalendarPath, const QByteArray &requestData)
135
{
136
FUNCTION_CALL_TRACE(lcCalDavTrace);
137
mRemoteCalendarPath = remoteCalendarPath;
138
139
QNetworkRequest request;
140
prepareRequest(&request, remoteCalendarPath);
141
142
request.setRawHeader("Depth", "1");
request.setRawHeader("Prefer", "return-minimal");
143
request.setHeader(QNetworkRequest::ContentLengthHeader, requestData.length());
144
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml; charset=utf-8");
145
QBuffer *buffer = new QBuffer(this);
146
buffer->setData(requestData);
147
// TODO: when Qt5.8 is available, remove the use of buffer, and pass requestData directly.
148
QNetworkReply *reply = mNAManager->sendCustomRequest(request, REQUEST_TYPE.toLatin1(), buffer);
149
reply->setProperty(PROP_URI, remoteCalendarPath);
150
debugRequest(request, buffer->buffer());
151
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
152
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
153
154
155
this, SLOT(slotSslErrors(QList<QSslError>)));
}
156
void Report::handleReply(QNetworkReply *reply)
157
{
158
FUNCTION_CALL_TRACE(lcCalDavTrace);
159
160
const QString &uri = reply->property(PROP_URI).toString();
161
if (reply->error() != QNetworkReply::NoError) {
162
finishedWithReplyResult(uri, reply);
163
164
return;
}
165
166
const QByteArray data = reply->readAll();
167
debugReply(*reply, data);
168
169
if (!data.isNull() && !data.isEmpty()) {
170
171
Reader reader;
reader.read(data);
172
if (reader.hasError()) {
173
174
finishedWithError(uri, Buteo::SyncResults::INTERNAL_ERROR,
QString("Malformed response body for REPORT"), data);
175
176
} else {
mReceivedResources = reader.results();
177
finishedWithSuccess(uri);
178
}
179
} else {
180
181
182
finishedWithError(uri, Buteo::SyncResults::INTERNAL_ERROR,
QString("Empty response body for REPORT"),
QByteArray());
183
184
185
}
}
186
const QList<Reader::CalendarResource>& Report::receivedCalendarResources() const
187
188
189
{
return mReceivedResources;
}
190
191
192
193
194
const QStringList& Report::fetchedUris() const
{
return mFetchedUris;
}