Libkdav2

utils.cpp
1 /*
2  Copyright (c) 2010 Tobias Koenig <[email protected]>
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 
35 using namespace KDAV2;
36 
37 QDomElement 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 
51 QDomElement 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 
146 Protocol 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;
167  QString id = QLatin1String("R") + QString::number(r);
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 
185 bool 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 }
QUrl url() const
Returns the url that identifies the DAV object.
Definition: davurl.cpp:41
Privileges KPIMKDAV2_EXPORT parsePrivilege(const QDomElement &element)
Parses a single <privilege> tag and returns the final Privileges.
Definition: utils.cpp:84
QString & append(QChar ch)
QDomNode item(int index) const const
QString toDisplayString(QUrl::FormattingOptions options) const const
QDomNodeList elementsByTagNameNS(const QString &nsURI, const QString &localName) const const
A helper class to store information about DAV collection.
Definition: davcollection.h:49
void setPrivileges(Privileges privs)
Sets the privileges on this collection.
static DavManager * self()
Returns the global instance of the DAV manager.
Definition: davmanager.cpp:52
int size() const const
QString namespaceURI() const const
QDomElement nextSiblingElement(const QString &tagName) const const
TolerantMode
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
void setNamedColor(const QString &name)
bool isValidColor(const QString &name)
QUrl fromUserInput(const QString &userInput)
QDomNodeList childNodes() const const
A helper class to combine url and protocol of a DAV url.
Definition: davurl.h:35
Privileges privileges() const
Returns the privileges on this collection.
QDomNode nextSibling() const const
QDomElement toElement() const const
void setPath(const QString &path, QUrl::ParsingMode mode)
bool isEmpty() const const
qint64 currentMSecsSinceEpoch()
QString number(int n, int base)
QString localName() const const
QString text() const const
bool extractCollection(const QDomElement &response, DavUrl url, DavCollection &collection)
Extract a DavCollection from the response element of a PROPFIND result.
Definition: utils.cpp:185
const DavProtocolBase * davProtocol(Protocol protocol)
Returns the DAV protocol dialect object for the given DAV protocol.
Definition: davmanager.cpp:140
Protocol KPIMKDAV2_EXPORT protocolByName(const QString &name)
Returns the protocol matching the given name.
Definition: utils.cpp:146
bool isEmpty() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString right(int n) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
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
bool isNull() const const
Protocol protocol() const
Returns the DAV protocol dialect that is used to retrieve the DAV object.
Definition: davurl.cpp:51
QDomNode firstChild() const const
QString mid(int position, int n) const const
Privileges KPIMKDAV2_EXPORT extractPrivileges(const QDomElement &element)
Extracts privileges from element.
Definition: utils.cpp:65
QString KPIMKDAV2_EXPORT contactsMimeType(Protocol protocol)
Returns the mimetype that shall be used for contact DAV resources using protocol. ...
Definition: utils.cpp:172
QDomElement firstChildElement(const QString &tagName) const const
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
void setCTag(const QString &ctag)
Sets this collection CTag.
QString tagName() const const
int length() const const
void setColor(const QColor &color)
Sets the color for this collection.
void setUserInfo(const QString &userInfo, QUrl::ParsingMode mode)
QLatin1String KPIMKDAV2_EXPORT protocolName(Protocol protocol)
Returns the untranslated name of the given DAV protocol dialect.
Definition: utils.cpp:127
bool isValid() const const
QString userInfo(QUrl::ComponentFormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jan 27 2022 23:10:33 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.