1 2 3 4 5 6 7 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
/*
* This file is part of buteo-sync-plugin-caldav package
*
* Copyright (C) 2013 Jolla Ltd. and/or its subsidiary(-ies).
*
* Contributors: Mani Chandrasekar <maninc@gmail.com>
* Stephan Rave <mail@stephanrave.de>
*
* 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_p.h"
#include "settings_p.h"
#include "reader_p.h"
#include <QNetworkAccessManager>
#include <QBuffer>
#include <QDebug>
#include <QStringList>
#define PROP_URI "uri"
static const QString DateTimeFormat = QStringLiteral("yyyyMMddTHHmmss");
static const QString DateTimeFormatUTC = DateTimeFormat + QStringLiteral("Z");
static QString dateTimeToString(const QDateTime &dt)
{
if (dt.timeSpec() == Qt::UTC) {
return QLocale::c().toString(dt, DateTimeFormatUTC);
} else {
return QLocale::c().toString(dt, DateTimeFormat);
}
}
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;
}
Report::Report(QNetworkAccessManager *manager, Settings *settings, QObject *parent)
: Request(manager, settings, "REPORT", parent)
{
}
void Report::getAllEvents(const QString &remoteCalendarPath, const QDateTime &fromDateTime, const QDateTime &toDateTime)
{
sendCalendarQuery(remoteCalendarPath, fromDateTime, toDateTime, true);
}
void Report::getAllETags(const QString &remoteCalendarPath, const QDateTime &fromDateTime, const QDateTime &toDateTime)
{
sendCalendarQuery(remoteCalendarPath, fromDateTime, toDateTime, false);
}
void Report::sendCalendarQuery(const QString &remoteCalendarPath,
const QDateTime &fromDateTime,
const QDateTime &toDateTime,
bool getCalendarData)
{
QByteArray requestData = \
"<c:calendar-query xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">" \
"<d:prop>" \
"<d:getetag />";
if (getCalendarData) {
requestData += \
"<c:calendar-data />";
}
requestData += \
"</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>";
sendRequest(remoteCalendarPath, requestData);
}
void Report::multiGetEvents(const QString &remoteCalendarPath, const QStringList &eventHrefList)
{
if (eventHrefList.isEmpty()) {
return;
}
QByteArray requestData = "<c:calendar-multiget xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">" \
"<d:prop><d:getetag /><c:calendar-data /></d:prop>";
for (const QString &eventHref : eventHrefList) {
requestData.append("<d:href>");
requestData.append(eventHref.toUtf8());
requestData.append("</d:href>");
}
requestData.append("</c:calendar-multiget>");
sendRequest(remoteCalendarPath, requestData);
}
void Report::sendRequest(const QString &remoteCalendarPath, const QByteArray &requestData)
{
mRemoteCalendarPath = remoteCalendarPath;
QNetworkRequest request;
prepareRequest(&request, remoteCalendarPath);
request.setRawHeader("Depth", "1");
request.setRawHeader("Prefer", "return-minimal");
request.setHeader(QNetworkRequest::ContentLengthHeader, requestData.length());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/xml; charset=utf-8");
QBuffer *buffer = new QBuffer(this);
buffer->setData(requestData);
// TODO: when Qt5.8 is available, remove the use of buffer, and pass requestData directly.
QNetworkReply *reply = mNAManager->sendCustomRequest(request, REQUEST_TYPE.toLatin1(), buffer);
reply->setProperty(PROP_URI, remoteCalendarPath);
debugRequest(request, buffer->buffer());
connect(reply, &QNetworkReply::finished, this, &Report::requestFinished);
connect(reply, &QNetworkReply::sslErrors, this, &Report::slotSslErrors);
}
void Report::handleReply(QNetworkReply *reply)
{
const QString &uri = reply->property(PROP_URI).toString();
if (reply->error() != QNetworkReply::NoError) {
finishedWithReplyResult(uri, reply);
return;
}
const QByteArray data = reply->readAll();
debugReply(*reply, data);
if (!data.isNull() && !data.isEmpty()) {
Reader reader;
reader.read(data);
if (reader.hasError()) {
finishedWithError(uri, QString("Malformed response body for REPORT"),
QByteArray());
} else {
mResponse = reader.results();
finishedWithSuccess(uri);
}
} else {
finishedWithError(uri, QString("Empty response body for REPORT"),
QByteArray());
}
}
const QList<Buteo::Dav::Resource>& Report::response() const
{
return mResponse;
}
|