File indexing completed on 2024-12-01 04:48:10
0001 /* 0002 SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "imapquotaattribute.h" 0008 0009 #include <QByteArray> 0010 #include <QString> 0011 #include <QStringList> 0012 0013 #include <QDebug> 0014 0015 using namespace Akonadi; 0016 0017 ImapQuotaAttribute::ImapQuotaAttribute() = default; 0018 0019 Akonadi::ImapQuotaAttribute::ImapQuotaAttribute(const QList<QByteArray> &roots, 0020 const QList<QMap<QByteArray, qint64>> &limits, 0021 const QList<QMap<QByteArray, qint64>> &usages) 0022 : mRoots(roots) 0023 , mLimits(limits) 0024 , mUsages(usages) 0025 { 0026 Q_ASSERT(roots.size() == limits.size()); 0027 Q_ASSERT(roots.size() == usages.size()); 0028 } 0029 0030 void Akonadi::ImapQuotaAttribute::setQuotas(const QList<QByteArray> &roots, 0031 const QList<QMap<QByteArray, qint64>> &limits, 0032 const QList<QMap<QByteArray, qint64>> &usages) 0033 { 0034 Q_ASSERT(roots.size() == limits.size()); 0035 Q_ASSERT(roots.size() == usages.size()); 0036 0037 mRoots = roots; 0038 mLimits = limits; 0039 mUsages = usages; 0040 } 0041 0042 QList<QByteArray> Akonadi::ImapQuotaAttribute::roots() const 0043 { 0044 return mRoots; 0045 } 0046 0047 QList<QMap<QByteArray, qint64>> Akonadi::ImapQuotaAttribute::limits() const 0048 { 0049 return mLimits; 0050 } 0051 0052 QList<QMap<QByteArray, qint64>> Akonadi::ImapQuotaAttribute::usages() const 0053 { 0054 return mUsages; 0055 } 0056 0057 QByteArray ImapQuotaAttribute::type() const 0058 { 0059 static const QByteArray sType("imapquota"); 0060 return sType; 0061 } 0062 0063 Akonadi::Attribute *ImapQuotaAttribute::clone() const 0064 { 0065 return new ImapQuotaAttribute(mRoots, mLimits, mUsages); 0066 } 0067 0068 QByteArray ImapQuotaAttribute::serialized() const 0069 { 0070 QByteArray result = ""; 0071 0072 // First the roots list 0073 for (const QByteArray &root : std::as_const(mRoots)) { 0074 result += root + " % "; 0075 } 0076 result.chop(3); 0077 0078 result += " %%%% "; // Members separator 0079 0080 // Then the limit maps list 0081 for (int i = 0; i < mLimits.size(); ++i) { 0082 const QMap<QByteArray, qint64> limits = mLimits[i]; 0083 for (auto it = limits.cbegin(), end = limits.cend(); it != end; ++it) { 0084 result += it.key(); 0085 result += " % "; // We use this separator as '%' is not allowed in keys or values 0086 result += QByteArray::number(it.value()); 0087 result += " %% "; // Pairs separator 0088 } 0089 result.chop(4); 0090 result += " %%% "; // Maps separator 0091 } 0092 result.chop(5); 0093 0094 result += " %%%% "; // Members separator 0095 0096 // Then the usage maps list 0097 for (int i = 0; i < mUsages.size(); ++i) { 0098 const QMap<QByteArray, qint64> usages = mUsages[i]; 0099 for (auto it = usages.cbegin(), end = usages.cend(); it != end; ++it) { 0100 result += it.key(); 0101 result += " % "; // We use this separator as '%' is not allowed in keys or values 0102 result += QByteArray::number(it.value()); 0103 result += " %% "; // Pairs separator 0104 } 0105 result.chop(4); 0106 result += " %%% "; // Maps separator 0107 } 0108 result.chop(5); 0109 0110 return result; 0111 } 0112 0113 void ImapQuotaAttribute::deserialize(const QByteArray &data) 0114 { 0115 mRoots.clear(); 0116 mLimits.clear(); 0117 mUsages.clear(); 0118 0119 // Nothing was saved. 0120 if (data.trimmed().isEmpty()) { 0121 return; 0122 } 0123 0124 QString string = QString::fromUtf8(data); // QByteArray has no proper split, so we're forced to convert to QString... 0125 0126 QStringList members = string.split(QStringLiteral("%%%%")); 0127 0128 // We expect exactly three members (roots, limits and usages), otherwise something is funky 0129 if (members.size() != 3) { 0130 qWarning() << "We didn't find exactly three members in this quota serialization"; 0131 return; 0132 } 0133 0134 QStringList roots = members[0].trimmed().split(QStringLiteral(" % ")); 0135 for (const QString &root : std::as_const(roots)) { 0136 mRoots << root.trimmed().toUtf8(); 0137 } 0138 0139 const QStringList allLimits = members[1].trimmed().split(QStringLiteral("%%%")); 0140 0141 for (const QString &limits : std::as_const(allLimits)) { 0142 QMap<QByteArray, qint64> limitsMap; 0143 const QStringList strLines = limits.split(QStringLiteral("%%")); 0144 QList<QByteArray> lines; 0145 lines.reserve(strLines.count()); 0146 for (const QString &strLine : strLines) { 0147 lines << strLine.trimmed().toUtf8(); 0148 } 0149 0150 for (const QByteArray &line : std::as_const(lines)) { 0151 QByteArray trimmed = line.trimmed(); 0152 int wsIndex = trimmed.indexOf('%'); 0153 const QByteArray key = trimmed.mid(0, wsIndex).trimmed(); 0154 const QByteArray value = trimmed.mid(wsIndex + 1, line.length() - wsIndex).trimmed(); 0155 limitsMap[key] = value.toLongLong(); 0156 } 0157 0158 mLimits << limitsMap; 0159 } 0160 0161 const QStringList allUsages = members[2].trimmed().split(QStringLiteral("%%%")); 0162 mUsages.reserve(allUsages.count()); 0163 0164 for (const QString &usages : std::as_const(allUsages)) { 0165 QMap<QByteArray, qint64> usagesMap; 0166 const QStringList strLines = usages.split(QStringLiteral("%%")); 0167 QList<QByteArray> lines; 0168 lines.reserve(strLines.count()); 0169 for (const QString &strLine : std::as_const(strLines)) { 0170 lines << strLine.trimmed().toUtf8(); 0171 } 0172 0173 for (const QByteArray &line : std::as_const(lines)) { 0174 QByteArray trimmed = line.trimmed(); 0175 int wsIndex = trimmed.indexOf('%'); 0176 const QByteArray key = trimmed.mid(0, wsIndex).trimmed(); 0177 const QByteArray value = trimmed.mid(wsIndex + 1, line.length() - wsIndex).trimmed(); 0178 usagesMap[key] = value.toLongLong(); 0179 } 0180 0181 mUsages << usagesMap; 0182 } 0183 }