Libkdav2

davcollectioncreatejob.cpp
1/*
2 Copyright (c) 2010 Grégory Oestreicher <greg@kamago.net>
3 Copyright (c) 2018 Rémi Nicole <minijackson@riseup.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "davcollectioncreatejob.h"
21
22#include "davcollectionfetchjob.h"
23#include "davcollectionmodifyjob.h"
24#include "daverror.h"
25#include "davjob.h"
26#include "davmanager.h"
27
28#include <QColor>
29#include <QMetaEnum>
30
31using namespace KDAV2;
32
34 : DavJobBase(parent), mCollection(collection), mRedirectCount(0)
35{
36}
37
39{
40 auto protocol = mCollection.url().protocol();
41 switch (protocol) {
42 case CalDav:
43 // This is a calendar, use the MKCALENDAR request
44 createCalendar();
45 break;
46 case CardDav:
47 // This is an addressbook, use the extended MKCOL request
48 createAddressbook();
49 break;
50 default: {
51 // This is a normal collection
52 auto job = DavManager::self()->createMkColJob(collectionUrl());
53 connect(job, &DavJob::result, this, &DavCollectionCreateJob::collectionCreated);
54 }
55 }
56}
57
59{
60 return mCollection;
61}
62
63QUrl DavCollectionCreateJob::collectionUrl() const
64{
65 return mCollection.url().url();
66}
67
68void DavCollectionCreateJob::collectionCreated(KJob *job)
69{
70 auto storedJob = static_cast<DavJob*>(job);
71
72 if (storedJob->error()) {
73 setErrorFromJob(storedJob, ERR_COLLECTIONCREATE);
74 emitResult();
75 return;
76 }
77
78 DavCollectionModifyJob *modifyJob =
79 new DavCollectionModifyJob(DavUrl(storedJob->url(), mCollection.url().protocol()), this);
80
81 modifyJob->setProperty(QStringLiteral("displayname"), mCollection.displayName());
82
83 connect(modifyJob, &DavCollectionFetchJob::result, this, &DavCollectionCreateJob::collectionModified);
84 modifyJob->start();
85}
86
87void DavCollectionCreateJob::collectionModified(KJob *job)
88{
89 if (job->error()) {
90 setError(ERR_PROBLEM_WITH_REQUEST);
91 setErrorTextFromDavError();
92 emitResult();
93 return;
94 }
95
96 DavCollectionFetchJob *fetchJob = new DavCollectionFetchJob(mCollection, this);
97 connect(fetchJob, &DavCollectionFetchJob::result, this, &DavCollectionCreateJob::collectionRefreshed);
98 fetchJob->start();
99}
100
101void DavCollectionCreateJob::collectionRefreshed(KJob *job)
102{
103 if (job->error()) {
104 setError(ERR_PROBLEM_WITH_REQUEST);
105 setErrorTextFromDavError();
106 emitResult();
107 return;
108 }
109
111 mCollection = fetchJob->collection();
112
113 emitResult();
114}
115
116void DavCollectionCreateJob::createCalendar()
117{
118 // clang-format off
119 /* Create a query like this:
120 *
121 * <C:mkcalendar xmlns:D='DAV:'xmlns:C='urn:ietf:params:xml:ns:caldav' xmlns:ICAL="http://apple.com/ns/ical/">
122 * <D:set>
123 * <D:prop>
124 * <D:displayname>Test Calendar</D:displayname>
125 * <ICAL:calendar-color>#24b0a3ff</ICAL:calendar-color>
126 * <C:supported-calendar-component-set>
127 * <C:comp name="VEVENT"/>
128 * <C:comp name="VJOURNAL"/>
129 * <C:comp name="VTODO"/>
130 * </C:supported-calendar-component-set>
131 * </D:prop>
132 * </D:set>
133 * </C:mkcalendar>
134 */
135 // clang-format on
136
137 QDomDocument document;
138
139 auto mkcalElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("mkcalendar"));
140 document.appendChild(mkcalElement);
141 auto setElement = mkcalElement.appendChild(
142 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("set")));
143 auto propElement =
144 setElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")));
145
146 if (!mCollection.displayName().isEmpty()) {
147 auto displayNameElement = propElement.appendChild(
148 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
149 displayNameElement.appendChild(document.createTextNode(mCollection.displayName()));
150 }
151
152 if (mCollection.color().isValid()) {
153 auto colorElement = propElement.appendChild(document.createElementNS(
154 QStringLiteral("http://apple.com/ns/ical/"), QStringLiteral("calendar-color")));
155 colorElement.appendChild(document.createTextNode(mCollection.color().name() + "FF"));
156 }
157
158 auto compSetElement = propElement.appendChild(document.createElementNS(
159 QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("supported-calendar-component-set")));
160
161 auto supportedComp = mCollection.contentTypes();
162
163 if (supportedComp.testFlag(DavCollection::Events)) {
164 auto compElement = document.createElementNS(
165 QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
166 compElement.setAttribute(QStringLiteral("name"), QStringLiteral("VEVENT"));
167 compSetElement.appendChild(compElement);
168 }
169
170 if (supportedComp.testFlag(DavCollection::Todos)) {
171 auto compElement = document.createElementNS(
172 QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
173 compElement.setAttribute(QStringLiteral("name"), QStringLiteral("VTODO"));
174 compSetElement.appendChild(compElement);
175 }
176
178 auto compElement = document.createElementNS(
179 QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
180 compElement.setAttribute(QStringLiteral("name"), QStringLiteral("VFREEBUSY"));
181 compSetElement.appendChild(compElement);
182 }
183
185 auto compElement = document.createElementNS(
186 QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("comp"));
187 compElement.setAttribute(QStringLiteral("name"), QStringLiteral("VJOURNAL"));
188 compSetElement.appendChild(compElement);
189 }
190
191 auto job = DavManager::self()->createMkCalendarJob(collectionUrl(), document);
192 // Skip the modification
193 connect(job, &DavJob::result, this, &DavCollectionCreateJob::collectionModified);
194}
195
196void DavCollectionCreateJob::createAddressbook()
197{
198 // clang-format off
199 /* Create a query like this:
200 *
201 * <D:mkcol xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
202 * <D:set>
203 * <D:prop>
204 * <D:resourcetype>
205 * <D:collection/>
206 * <C:addressbook/>
207 * </D:resourcetype>
208 * <D:displayname>Lisa's Contacts</D:displayname>
209 * </D:prop>
210 * </D:set>
211 * </D:mkcol>
212 */
213 // clang-format on
214
215 QDomDocument document;
216
217 auto mkcolElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("mkcol"));
218 document.appendChild(mkcolElement);
219 auto setElement = mkcolElement.appendChild(
220 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("set")));
221 auto propElement =
222 setElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")));
223
224 auto resourceTypeElement = propElement.appendChild(
225 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
226
227 resourceTypeElement.appendChild(
228 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("collection")));
229
230 resourceTypeElement.appendChild(document.createElementNS(
231 QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("addressbook")));
232
233 if (!mCollection.displayName().isEmpty()) {
234 auto displayNameElement = propElement.appendChild(
235 document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
236 displayNameElement.appendChild(document.createTextNode(mCollection.displayName()));
237 }
238
239 auto job = DavManager::self()->createMkColJob(collectionUrl(), document);
240 // Skip the modification
241 connect(job, &DavJob::result, this, &DavCollectionCreateJob::collectionModified);
242}
DavCollectionCreateJob(const DavCollection &collection, QObject *parent=nullptr)
Creates a new dav collection create job.
void start() override
Starts the job.
DavCollection collection() const
Returns the created DAV item including the correct identifier url and current etag information.
A job that fetches a DAV collection from the DAV server.
void start() override
Starts the job.
A job that modifies a DAV collection.
void start() override
Starts the job.
void setProperty(const QString &property, const QString &value, const QString &ns=QString())
Sets the property that shall be modified by the job.
A helper class to store information about DAV collection.
@ Journal
The collection can contain journal DAV resources.
@ Todos
The collection can contain todo DAV resources.
@ FreeBusy
The collection can contain free/busy information.
@ Events
The collection can contain event DAV resources.
QString displayName() const
Returns the display name of the collection.
ContentTypes contentTypes() const
Returns the possible content types of the collection.
DavUrl url() const
Returns the url that identifies the collection.
QColor color() const
Return the color of the collection, or an empty string if none was provided by the backend.
base class for the jobs used by the resource.
Definition davjobbase.h:38
void setErrorFromJob(DavJob *, ErrorNumber jobErrorCode=ERR_PROBLEM_WITH_REQUEST)
Set the error of this job from a failed DavJob (executed by this job).
DavJob * createMkColJob(const QUrl &url)
Returns a preconfigured DAV MKCOL job.
static DavManager * self()
Returns the global instance of the DAV manager.
DavJob * createMkCalendarJob(const QUrl &url, const QDomDocument &document)
Returns a preconfigured DAV MKCALENDAR job.
A helper class to combine url and protocol of a DAV url.
Definition davurl.h:36
QUrl url() const
Returns the url that identifies the DAV object.
Definition davurl.cpp:41
Protocol protocol() const
Returns the DAV protocol dialect that is used to retrieve the DAV object.
Definition davurl.cpp:51
void emitResult()
int error() const
void result(KJob *job)
void setError(int errorCode)
bool isValid() const const
QString name(NameFormat format) const const
QDomElement createElementNS(const QString &nsURI, const QString &qName)
QDomText createTextNode(const QString &value)
QDomNode appendChild(const QDomNode &newChild)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:28 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.