1 /*
2     SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "carddavprotocol_p.h"
8 
9 #include <QDomDocument>
10 #include <QStringList>
11 #include <QUrl>
12 
13 using namespace KDAV;
14 
15 class CarddavCollectionQueryBuilder : public XMLQueryBuilder
16 {
17 public:
buildQuery() const18     QDomDocument buildQuery() const override
19     {
20         QDomDocument document;
21 
22         QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
23         document.appendChild(propfindElement);
24 
25         QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
26         propfindElement.appendChild(propElement);
27 
28         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
29         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
30         propElement.appendChild(document.createElementNS(QStringLiteral("http://calendarserver.org/ns/"), QStringLiteral("getctag")));
31 
32         return document;
33     }
34 
mimeType() const35     QString mimeType() const override
36     {
37         return QString();
38     }
39 };
40 
41 class CarddavListItemsQueryBuilder : public XMLQueryBuilder
42 {
43 public:
buildQuery() const44     QDomDocument buildQuery() const override
45     {
46         QDomDocument document;
47 
48         QDomElement propfindElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind"));
49         document.appendChild(propfindElement);
50 
51         QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
52         propfindElement.appendChild(propElement);
53 
54         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")));
55         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("resourcetype")));
56         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
57 
58         return document;
59     }
60 
mimeType() const61     QString mimeType() const override
62     {
63         return QStringLiteral("text/directory");
64     }
65 };
66 
67 class CarddavMultigetQueryBuilder : public XMLQueryBuilder
68 {
69 public:
buildQuery() const70     QDomDocument buildQuery() const override
71     {
72         QDomDocument document;
73         const QStringList urls = parameter(QStringLiteral("urls")).toStringList();
74         if (urls.isEmpty()) {
75             return document;
76         }
77 
78         QDomElement multigetElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("addressbook-multiget"));
79         document.appendChild(multigetElement);
80 
81         QDomElement propElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
82         multigetElement.appendChild(propElement);
83 
84         propElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("getetag")));
85         QDomElement addressDataElement = document.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:carddav"), QStringLiteral("address-data"));
86         addressDataElement.appendChild(document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("allprop")));
87         propElement.appendChild(addressDataElement);
88 
89         for (const QString &url : urls) {
90             QDomElement hrefElement = document.createElementNS(QStringLiteral("DAV:"), QStringLiteral("href"));
91             const QUrl pathUrl = QUrl::fromUserInput(url);
92             const QDomText textNode = document.createTextNode(pathUrl.toString());
93             hrefElement.appendChild(textNode);
94 
95             multigetElement.appendChild(hrefElement);
96         }
97 
98         return document;
99     }
100 
mimeType() const101     QString mimeType() const override
102     {
103         return QString();
104     }
105 };
106 
CarddavProtocol()107 CarddavProtocol::CarddavProtocol()
108 {
109 }
110 
supportsPrincipals() const111 bool CarddavProtocol::supportsPrincipals() const
112 {
113     return true;
114 }
115 
useReport() const116 bool CarddavProtocol::useReport() const
117 {
118     return false;
119 }
120 
useMultiget() const121 bool CarddavProtocol::useMultiget() const
122 {
123     return true;
124 }
125 
principalHomeSet() const126 QString CarddavProtocol::principalHomeSet() const
127 {
128     return QStringLiteral("addressbook-home-set");
129 }
130 
principalHomeSetNS() const131 QString CarddavProtocol::principalHomeSetNS() const
132 {
133     return QStringLiteral("urn:ietf:params:xml:ns:carddav");
134 }
135 
collectionsQuery() const136 XMLQueryBuilder::Ptr CarddavProtocol::collectionsQuery() const
137 {
138     return XMLQueryBuilder::Ptr(new CarddavCollectionQueryBuilder());
139 }
140 
collectionsXQuery() const141 QString CarddavProtocol::collectionsXQuery() const
142 {
143     // clang-format off
144     const QString query(QStringLiteral("//*[local-name()='addressbook' and namespace-uri()='urn:ietf:params:xml:ns:carddav']/ancestor::*[local-name()='response' and namespace-uri()='DAV:']"));
145 
146     return query;
147     // clang-format on
148 }
149 
itemsQueries() const150 QVector<XMLQueryBuilder::Ptr> CarddavProtocol::itemsQueries() const
151 {
152     QVector<XMLQueryBuilder::Ptr> ret;
153     ret << XMLQueryBuilder::Ptr(new CarddavListItemsQueryBuilder());
154     return ret;
155 }
156 
itemsReportQuery(const QStringList & urls) const157 XMLQueryBuilder::Ptr CarddavProtocol::itemsReportQuery(const QStringList &urls) const
158 {
159     XMLQueryBuilder::Ptr ret(new CarddavMultigetQueryBuilder());
160     ret->setParameter(QStringLiteral("urls"), urls);
161     return ret;
162 }
163 
responseNamespace() const164 QString CarddavProtocol::responseNamespace() const
165 {
166     return QStringLiteral("urn:ietf:params:xml:ns:carddav");
167 }
168 
dataTagName() const169 QString CarddavProtocol::dataTagName() const
170 {
171     return QStringLiteral("address-data");
172 }
173 
collectionContentTypes(const QDomElement &) const174 DavCollection::ContentTypes CarddavProtocol::collectionContentTypes(const QDomElement &) const
175 {
176     return DavCollection::Contacts;
177 }
178