File indexing completed on 2024-11-24 04:44:10

0001 /*
0002  * SPDX-FileCopyrightText: 2012 Christian Mollekopf <mollekopf@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-3.0-or-later
0005  */
0006 
0007 #include "commonconversion.h"
0008 #include "pimkolab_debug.h"
0009 #include "timezoneconverter.h"
0010 
0011 #include <QTimeZone>
0012 #include <iostream>
0013 
0014 namespace Kolab
0015 {
0016 namespace Conversion
0017 {
0018 QTimeZone getTimeZone(const std::string &timezone)
0019 {
0020     // Convert non-olson timezones if necessary
0021     const QString normalizedTz = TimezoneConverter::normalizeTimezone(QString::fromStdString(timezone));
0022     if (!QTimeZone::isTimeZoneIdAvailable(normalizedTz.toLatin1())) {
0023         return QTimeZone::systemTimeZone();
0024     }
0025     // FIXME convert this to a proper KTimeZone
0026     return QTimeZone(normalizedTz.toLatin1());
0027 }
0028 
0029 QTimeZone getTimeSpec(bool isUtc, const std::string &timezone)
0030 {
0031     if (isUtc) { // UTC
0032         return QTimeZone::utc();
0033     }
0034     if (timezone.empty()) { // Floating
0035         return QTimeZone::systemTimeZone();
0036     }
0037 
0038     // Convert non-olson timezones if necessary
0039     QTimeZone tz = getTimeZone(timezone);
0040     if (!tz.isValid()) {
0041         return QTimeZone::systemTimeZone();
0042     }
0043     return tz;
0044 }
0045 
0046 QDateTime toDate(const Kolab::cDateTime &dt)
0047 {
0048     QDateTime date;
0049     if (!dt.isValid()) {
0050         return {};
0051     }
0052     if (dt.isDateOnly()) {
0053         date.setDate(QDate(dt.year(), dt.month(), dt.day()));
0054         date.setTime({});
0055         date.setTimeSpec(Qt::LocalTime);
0056     } else {
0057         date.setDate(QDate(dt.year(), dt.month(), dt.day()));
0058         date.setTime(QTime(dt.hour(), dt.minute(), dt.second()));
0059         if (dt.isUTC()) {
0060             date.setTimeZone(QTimeZone::utc());
0061         } else {
0062             date.setTimeZone(getTimeZone(dt.timezone()));
0063         }
0064     }
0065     Q_ASSERT(date.isValid());
0066     return date;
0067 }
0068 
0069 cDateTime fromDate(const QDateTime &dt, bool isAllDay)
0070 {
0071     if (!dt.isValid()) {
0072         return {};
0073     }
0074     cDateTime date;
0075     if (isAllDay) {
0076         const QDate &d = dt.date();
0077         date.setDate(d.year(), d.month(), d.day());
0078     } else {
0079         const QDate &d = dt.date();
0080         date.setDate(d.year(), d.month(), d.day());
0081         const QTime &t = dt.time();
0082         date.setTime(t.hour(), t.minute(), t.second());
0083         if (dt.timeSpec() == Qt::UTC) {
0084             date.setUTC(true);
0085         } else if (dt.timeSpec() == Qt::OffsetFromUTC) {
0086             const QDateTime utcDate = dt.toUTC();
0087             const QDate &d = utcDate.date();
0088             date.setDate(d.year(), d.month(), d.day());
0089             const QTime &t = utcDate.time();
0090             date.setTime(t.hour(), t.minute(), t.second());
0091             date.setUTC(true);
0092         } else if (dt.timeSpec() == Qt::TimeZone || dt.timeSpec() == Qt::LocalTime) {
0093             const QString timezone = TimezoneConverter::normalizeTimezone(QString::fromUtf8(dt.timeZone().id()));
0094             if (!timezone.isEmpty()) {
0095                 date.setTimezone(toStdString(timezone));
0096             } else {
0097                 qCWarning(PIMKOLAB_LOG) << "invalid timezone: " << dt.timeZone().id() << ", assuming floating time";
0098                 return date;
0099             }
0100         }
0101     }
0102     Q_ASSERT(date.isValid());
0103     return date;
0104 }
0105 
0106 QStringList toStringList(const std::vector<std::string> &l)
0107 {
0108     QStringList list;
0109     list.reserve(l.size());
0110     for (const std::string &s : l) {
0111         list.append(Conversion::fromStdString(s));
0112     }
0113     return list;
0114 }
0115 
0116 std::vector<std::string> fromStringList(const QStringList &l)
0117 {
0118     std::vector<std::string> list;
0119     list.reserve(l.size());
0120     for (const QString &s : l) {
0121         list.push_back(toStdString(s));
0122     }
0123     return list;
0124 }
0125 
0126 QUrl toMailto(const std::string &email, const std::string &name)
0127 {
0128     std::string mailto;
0129     if (!name.empty()) {
0130         mailto.append(name);
0131     }
0132     mailto.append("<");
0133     mailto.append(email);
0134     mailto.append(">");
0135     return QUrl(QString::fromStdString(std::string("mailto:") + mailto));
0136 }
0137 
0138 std::string fromMailto(const QUrl &mailtoUri, std::string &name)
0139 {
0140     const QPair<std::string, std::string> pair = fromMailto(toStdString(mailtoUri.toString()));
0141     name = pair.second;
0142     return pair.first;
0143 }
0144 
0145 QPair<std::string, std::string> fromMailto(const std::string &mailto)
0146 {
0147     const std::string &decoded = toStdString(QUrl::fromPercentEncoding(QByteArray(mailto.c_str())));
0148     if (decoded.substr(0, 7).compare("mailto:")) {
0149         // WARNING("no mailto address");
0150         // std::cout << decoded << std::endl;
0151         return qMakePair(decoded, std::string());
0152     }
0153     std::size_t begin = decoded.find('<', 7);
0154     if (begin == std::string::npos) {
0155         qCDebug(PIMKOLAB_LOG) << "no mailto address";
0156         std::cout << decoded << std::endl;
0157         return qMakePair(decoded, std::string());
0158     }
0159     std::size_t end = decoded.find('>', begin);
0160     if (end == std::string::npos) {
0161         qCWarning(PIMKOLAB_LOG) << "no mailto address";
0162         std::cout << decoded << std::endl;
0163         return qMakePair(decoded, std::string());
0164     }
0165     const std::string name = decoded.substr(7, begin - 7);
0166     const std::string email = decoded.substr(begin + 1, end - begin - 1);
0167     return qMakePair(email, name);
0168 }
0169 }
0170 }