Libkdav2

utils.cpp
1/*
2 Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17*/
18
19#include "utils.h"
20
21#include "enums.h"
22
23#include "davitem.h"
24#include "davmanager.h"
25#include "davprotocolbase.h"
26#include "davurl.h"
27
28#include <QColor>
29#include <QtCore/QByteArray>
30#include <QtCore/QDateTime>
31#include <QtCore/QString>
32
33#include "libkdav2_debug.h"
34
35using namespace KDAV2;
36
37QDomElement Utils::firstChildElementNS(const QDomElement &parent, const QString &namespaceUri, const QString &tagName)
38{
39 for (QDomNode child = parent.firstChild(); !child.isNull(); child = child.nextSibling()) {
40 if (child.isElement()) {
41 const QDomElement elt = child.toElement();
42 if (tagName.isEmpty() || (elt.tagName() == tagName && elt.namespaceURI() == namespaceUri)) {
43 return elt;
44 }
45 }
46 }
47
48 return QDomElement();
49}
50
51QDomElement Utils::nextSiblingElementNS(const QDomElement &element, const QString &namespaceUri, const QString &tagName)
52{
53 for (QDomNode sib = element.nextSibling(); !sib.isNull(); sib = sib.nextSibling()) {
54 if (sib.isElement()) {
55 const QDomElement elt = sib.toElement();
56 if (tagName.isEmpty() || (elt.tagName() == tagName && elt.namespaceURI() == namespaceUri)) {
57 return elt;
58 }
59 }
60 }
61
62 return QDomElement();
63}
64
66{
67 Privileges final = None;
68 QDomElement privElement = firstChildElementNS(element, QStringLiteral("DAV:"), QStringLiteral("privilege"));
69
70 while (!privElement.isNull()) {
71 QDomElement child = privElement.firstChildElement();
72
73 while (!child.isNull()) {
74 final |= parsePrivilege(child);
75 child = child.nextSiblingElement();
76 }
77
78 privElement = Utils::nextSiblingElementNS(privElement, QStringLiteral("DAV:"), QStringLiteral("privilege"));
79 }
80
81 return final;
82}
83
85{
86 Privileges final = None;
87
88 if (!element.childNodes().isEmpty()) {
89 // This is an aggregate privilege, parse each of its children
90 QDomElement child = element.firstChildElement();
91 while (!child.isNull()) {
92 final |= parsePrivilege(child);
93 child = child.nextSiblingElement();
94 }
95 } else {
96 // This is a normal privilege
97 const QString privname = element.localName();
98
99 if (privname == QLatin1String("read")) {
100 final |= KDAV2::Read;
101 } else if (privname == QLatin1String("write")) {
102 final |= KDAV2::Write;
103 } else if (privname == QLatin1String("write-properties")) {
104 final |= KDAV2::WriteProperties;
105 } else if (privname == QLatin1String("write-content")) {
106 final |= KDAV2::WriteContent;
107 } else if (privname == QLatin1String("unlock")) {
108 final |= KDAV2::Unlock;
109 } else if (privname == QLatin1String("read-acl")) {
110 final |= KDAV2::ReadAcl;
111 } else if (privname == QLatin1String("read-current-user-privilege-set")) {
112 final |= KDAV2::ReadCurrentUserPrivilegeSet;
113 } else if (privname == QLatin1String("write-acl")) {
114 final |= KDAV2::WriteAcl;
115 } else if (privname == QLatin1String("bind")) {
116 final |= KDAV2::Bind;
117 } else if (privname == QLatin1String("unbind")) {
118 final |= KDAV2::Unbind;
119 } else if (privname == QLatin1String("all")) {
120 final |= KDAV2::All;
121 }
122 }
123
124 return final;
125}
126
128{
129 QLatin1String protocolName("");
130
131 switch (protocol) {
132 case KDAV2::CalDav:
133 protocolName = QLatin1String("CalDav");
134 break;
135 case KDAV2::CardDav:
136 protocolName = QLatin1String("CardDav");
137 break;
138 case KDAV2::GroupDav:
139 protocolName = QLatin1String("GroupDav");
140 break;
141 }
142
143 return protocolName;
144}
145
146Protocol Utils::protocolByName(const QString &name)
147{
148 Protocol protocol = KDAV2::CalDav;
149
150 if (name == QLatin1String("CalDav")) {
151 protocol = KDAV2::CalDav;
152 } else if (name == QLatin1String("CardDav")) {
153 protocol = KDAV2::CardDav;
154 } else if (name == QLatin1String("GroupDav")) {
155 protocol = KDAV2::GroupDav;
156 } else {
157 qCCritical(KDAV2_LOG) << "Unexpected protocol name : " << name;
158 }
159
160 return protocol;
161}
162
164{
165 qint64 time = QDateTime::currentMSecsSinceEpoch() / 1000;
166 int r = qrand() % 1000;
168 QString uid = QString::number(time) + QLatin1String(".") + id;
169 return uid;
170}
171
173{
174 QString ret;
175
176 if (protocol == KDAV2::CardDav) {
177 ret = QStringLiteral("text/vcard");
178 } else if (protocol == KDAV2::GroupDav) {
179 ret = QStringLiteral("text/x-vcard");
180 }
181
182 return ret;
183}
184
185bool Utils::extractCollection(const QDomElement &response, DavUrl davUrl, DavCollection &collection)
186{
187 QDomElement propstatElement;
188
189 // check for the valid propstat, without giving up on first error
190 {
191 const QDomNodeList propstats =
192 response.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
193 for (int i = 0; i < propstats.length(); ++i) {
194 const QDomElement propstatCandidate = propstats.item(i).toElement();
195 const QDomElement statusElement = Utils::firstChildElementNS(
196 propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
197 if (statusElement.text().contains(QStringLiteral("200"))) {
198 propstatElement = propstatCandidate;
199 }
200 }
201 }
202
203 if (propstatElement.isNull()) {
204 return false;
205 }
206
207 // extract url
208 const QDomElement hrefElement =
209 Utils::firstChildElementNS(response, QStringLiteral("DAV:"), QStringLiteral("href"));
210
211 if (hrefElement.isNull()) {
212 return false;
213 }
214
215
216 QString href = hrefElement.text();
217 if (!href.endsWith(QLatin1Char('/'))) {
218 href.append(QLatin1Char('/'));
219 }
220
221 QUrl url = davUrl.url();
222 url.setUserInfo(QString());
223 if (href.startsWith(QLatin1Char('/'))) {
224 // href is only a path, use request url to complete
225 url.setPath(href, QUrl::TolerantMode);
226 } else {
227 // href is a complete url
228 url = QUrl::fromUserInput(href);
229 }
230
231 // extract display name
232 const QDomElement propElement =
233 Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
234 const QDomElement displaynameElement =
235 Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("displayname"));
236 const QString displayName = displaynameElement.text();
237
238 // Extract CTag
239 const QDomElement CTagElement = Utils::firstChildElementNS(
240 propElement, QStringLiteral("http://calendarserver.org/ns/"), QStringLiteral("getctag"));
241 QString CTag;
242 if (!CTagElement.isNull()) {
243 CTag = CTagElement.text();
244 }
245
246 // extract calendar color if provided
247 const QDomElement colorElement = Utils::firstChildElementNS(
248 propElement, QStringLiteral("http://apple.com/ns/ical/"), QStringLiteral("calendar-color"));
249 QColor color;
250 if (!colorElement.isNull()) {
251 QString colorValue = colorElement.text();
252 if(colorValue[0] == '#' && colorValue.size() == 9) {
253 // Put the alpha part at the beginning for Qt:
254 // Qt wants #AARRGGBB instead of #RRGGBBAA
255 colorValue = QStringLiteral("#") + colorValue.right(2) + colorValue.mid(1, 6);
256 }
257
258 if (QColor::isValidColor(colorValue)) {
259 color.setNamedColor(colorValue);
260 }
261 }
262
263 // extract allowed content types
264 const DavCollection::ContentTypes contentTypes =
265 DavManager::self()->davProtocol(davUrl.protocol())->collectionContentTypes(propstatElement);
266
267 auto _url = url;
268 _url.setUserInfo(davUrl.url().userInfo());
269 collection = DavCollection(DavUrl(_url, davUrl.protocol()), displayName, contentTypes);
270
271 collection.setCTag(CTag);
272 if (color.isValid()) {
273 collection.setColor(color);
274 }
275
276 // extract privileges
277 const QDomElement currentPrivsElement = Utils::firstChildElementNS(
278 propElement, QStringLiteral("DAV:"), QStringLiteral("current-user-privilege-set"));
279 if (currentPrivsElement.isNull()) {
280 // Assume that we have all privileges
281 collection.setPrivileges(KDAV2::All);
282 } else {
283 Privileges privileges = Utils::extractPrivileges(currentPrivsElement);
284 collection.setPrivileges(privileges);
285 }
286
287 qCDebug(KDAV2_LOG) << url.toDisplayString() << "PRIVS: " << collection.privileges();
288
289 return true;
290}
A helper class to store information about DAV collection.
Privileges privileges() const
Returns the privileges on this collection.
void setPrivileges(Privileges privs)
Sets the privileges on this collection.
void setCTag(const QString &ctag)
Sets this collection CTag.
void setColor(const QColor &color)
Sets the color for this collection.
static DavManager * self()
Returns the global instance of the DAV manager.
const DavProtocolBase * davProtocol(Protocol protocol)
Returns the DAV protocol dialect object for the given DAV protocol.
virtual DavCollection::ContentTypes collectionContentTypes(const QDomElement &propstat) const =0
Returns the possible content types for the collection that is described by the passed propstat elemen...
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
Protocol KPIMKDAV2_EXPORT protocolByName(const QString &name)
Returns the protocol matching the given name.
Definition utils.cpp:146
Privileges KPIMKDAV2_EXPORT parsePrivilege(const QDomElement &element)
Parses a single <privilege> tag and returns the final Privileges.
Definition utils.cpp:84
QString KPIMKDAV2_EXPORT contactsMimeType(Protocol protocol)
Returns the mimetype that shall be used for contact DAV resources using protocol.
Definition utils.cpp:172
bool extractCollection(const QDomElement &response, DavUrl url, DavCollection &collection)
Extract a DavCollection from the response element of a PROPFIND result.
Definition utils.cpp:185
QDomElement KPIMKDAV2_EXPORT firstChildElementNS(const QDomElement &parent, const QString &namespaceUri, const QString &tagName)
Returns the first child element of parent that has the given tagName and is part of the namespaceUri.
Definition utils.cpp:37
QDomElement KPIMKDAV2_EXPORT nextSiblingElementNS(const QDomElement &element, const QString &namespaceUri, const QString &tagName)
Returns the next sibling element of element that has the given tagName and is part of the namespaceUr...
Definition utils.cpp:51
QString KPIMKDAV2_EXPORT createUniqueId()
Creates a unique identifier that can be used as a file name to upload the dav item.
Definition utils.cpp:163
Privileges KPIMKDAV2_EXPORT extractPrivileges(const QDomElement &element)
Extracts privileges from element.
Definition utils.cpp:65
QLatin1String KPIMKDAV2_EXPORT protocolName(Protocol protocol)
Returns the untranslated name of the given DAV protocol dialect.
Definition utils.cpp:127
bool isValidColor(QLatin1StringView name)
void setNamedColor(QLatin1StringView name)
bool isValid() const const
qint64 currentMSecsSinceEpoch()
QDomNodeList elementsByTagNameNS(const QString &nsURI, const QString &localName) const const
QString tagName() const const
QString text() const const
QDomNodeList childNodes() const const
QDomNode firstChild() const const
QDomElement firstChildElement(const QString &tagName, const QString &namespaceURI) const const
bool isNull() const const
QString localName() const const
QString namespaceURI() const const
QDomNode nextSibling() const const
QDomElement nextSiblingElement(const QString &tagName, const QString &namespaceURI) const const
QDomElement toElement() const const
bool isEmpty() const const
QDomNode item(int index) const const
int length() const const
QString & append(QChar ch)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
QString right(qsizetype n) const const
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
TolerantMode
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
void setPath(const QString &path, ParsingMode mode)
void setUserInfo(const QString &userInfo, ParsingMode mode)
QString toDisplayString(FormattingOptions options) const const
QString userInfo(ComponentFormattingOptions options) 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.