File indexing completed on 2024-05-12 05:17:13
0001 /* 0002 SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "getmetadatajob.h" 0008 0009 #include "kimap_debug.h" 0010 #include <KLocalizedString> 0011 0012 #include "metadatajobbase_p.h" 0013 #include "response_p.h" 0014 #include "rfccodecs.h" 0015 #include "session_p.h" 0016 0017 namespace KIMAP 0018 { 0019 class GetMetaDataJobPrivate : public MetaDataJobBasePrivate 0020 { 0021 public: 0022 GetMetaDataJobPrivate(Session *session, const QString &name) 0023 : MetaDataJobBasePrivate(session, name) 0024 , depth("0") 0025 { 0026 } 0027 ~GetMetaDataJobPrivate() 0028 { 0029 } 0030 0031 qint64 maxSize = -1; 0032 QByteArray depth; 0033 QSet<QByteArray> entries; 0034 QSet<QByteArray> attributes; 0035 QMap<QString, QMap<QByteArray, QMap<QByteArray, QByteArray>>> metadata; 0036 // ^ mailbox ^ entry ^attribute ^ value 0037 }; 0038 } 0039 0040 using namespace KIMAP; 0041 0042 GetMetaDataJob::GetMetaDataJob(Session *session) 0043 : MetaDataJobBase(*new GetMetaDataJobPrivate(session, i18n("GetMetaData"))) 0044 { 0045 } 0046 0047 GetMetaDataJob::~GetMetaDataJob() 0048 { 0049 } 0050 0051 static QList<QByteArray> sort(const QSet<QByteArray> &set) 0052 { 0053 QList<QByteArray> sortedEntries = set.values(); 0054 std::sort(sortedEntries.begin(), sortedEntries.end()); 0055 return sortedEntries; 0056 } 0057 0058 void GetMetaDataJob::doStart() 0059 { 0060 Q_D(GetMetaDataJob); 0061 QByteArray parameters; 0062 parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" "; 0063 0064 QByteArray command = "GETMETADATA"; 0065 if (d->serverCapability == Annotatemore) { 0066 d->m_name = i18n("GetAnnotation"); 0067 command = "GETANNOTATION"; 0068 if (d->entries.size() > 1) { 0069 parameters += '('; 0070 } 0071 const auto sortedEntries = sort(d->entries); 0072 for (const QByteArray &entry : sortedEntries) { 0073 parameters += '\"' + entry + "\" "; 0074 } 0075 if (d->entries.size() > 1) { 0076 parameters[parameters.length() - 1] = ')'; 0077 parameters += ' '; 0078 } 0079 0080 if (d->attributes.size() > 1) { 0081 parameters += '('; 0082 } 0083 const auto sortedAttributes = sort(d->attributes); 0084 for (const QByteArray &attribute : sortedAttributes) { 0085 parameters += '\"' + attribute + "\" "; 0086 } 0087 if (d->attributes.size() > 1) { 0088 parameters[parameters.length() - 1] = ')'; 0089 } else { 0090 parameters.chop(1); 0091 } 0092 0093 } else { 0094 QByteArray options; 0095 if (d->depth != "0") { 0096 options = "DEPTH " + d->depth; 0097 } 0098 if (d->maxSize != -1) { 0099 if (!options.isEmpty()) { 0100 options += ' '; 0101 } 0102 options += "MAXSIZE " + QByteArray::number(d->maxSize); 0103 } 0104 0105 if (!options.isEmpty()) { 0106 parameters = "(" + options + ") " + parameters; 0107 } 0108 0109 if (d->entries.size() >= 1) { 0110 parameters += '('; 0111 const auto sortedEntries = sort(d->entries); 0112 for (const QByteArray &entry : sortedEntries) { 0113 parameters += entry + " "; 0114 } 0115 parameters[parameters.length() - 1] = ')'; 0116 } else { 0117 parameters.chop(1); 0118 } 0119 } 0120 0121 d->tags << d->sessionInternal()->sendCommand(command, parameters); 0122 // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters; 0123 } 0124 0125 void GetMetaDataJob::handleResponse(const Response &response) 0126 { 0127 Q_D(GetMetaDataJob); 0128 // qCDebug(KIMAP_LOG) << "GOT: " << response.toString(); 0129 0130 // TODO: handle NO error messages having [METADATA MAXSIZE NNN], [METADATA TOOMANY], [METADATA NOPRIVATE] (see rfc5464) 0131 // or [ANNOTATEMORE TOOBIG], [ANNOTATEMORE TOOMANY] respectively 0132 if (handleErrorReplies(response) == NotHandled) { 0133 if (response.content.size() >= 4) { 0134 if (d->serverCapability == Annotatemore && response.content[1].toString() == "ANNOTATION") { 0135 QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString())); 0136 0137 int i = 3; 0138 while (i < response.content.size() - 1) { 0139 QByteArray entry = response.content[i].toString(); 0140 QList<QByteArray> attributes = response.content[i + 1].toList(); 0141 int j = 0; 0142 while (j < attributes.size() - 1) { 0143 d->metadata[mailBox][entry][attributes[j]] = attributes[j + 1]; 0144 j += 2; 0145 } 0146 i += 2; 0147 } 0148 } else if (d->serverCapability == Metadata && response.content[1].toString() == "METADATA") { 0149 QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString())); 0150 0151 const QList<QByteArray> &entries = response.content[3].toList(); 0152 int i = 0; 0153 while (i < entries.size() - 1) { 0154 const QByteArray &value = entries[i + 1]; 0155 QByteArray &targetValue = d->metadata[mailBox][entries[i]][""]; 0156 if (value != "NIL") { // This just indicates no value 0157 targetValue = value; 0158 } 0159 i += 2; 0160 } 0161 } 0162 } 0163 } 0164 } 0165 0166 void GetMetaDataJob::addEntry(const QByteArray &entry, const QByteArray &attribute) 0167 { 0168 Q_D(GetMetaDataJob); 0169 if (d->serverCapability == Annotatemore && attribute.isNull()) { 0170 qCWarning(KIMAP_LOG) << "In ANNOTATEMORE mode an attribute must be specified with addEntry!"; 0171 } 0172 d->entries.insert(entry); 0173 d->attributes.insert(attribute); 0174 } 0175 0176 void GetMetaDataJob::addRequestedEntry(const QByteArray &entry) 0177 { 0178 Q_D(GetMetaDataJob); 0179 d->entries.insert(d->removePrefix(entry)); 0180 d->attributes.insert(d->getAttribute(entry)); 0181 } 0182 0183 void GetMetaDataJob::setMaximumSize(qint64 size) 0184 { 0185 Q_D(GetMetaDataJob); 0186 d->maxSize = size; 0187 } 0188 0189 void GetMetaDataJob::setDepth(Depth depth) 0190 { 0191 Q_D(GetMetaDataJob); 0192 0193 switch (depth) { 0194 case OneLevel: 0195 d->depth = "1"; // krazy:exclude=doublequote_chars 0196 break; 0197 case AllLevels: 0198 d->depth = "infinity"; 0199 break; 0200 default: 0201 d->depth = "0"; // krazy:exclude=doublequote_chars 0202 } 0203 } 0204 0205 QByteArray GetMetaDataJob::metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute) const 0206 { 0207 Q_D(const GetMetaDataJob); 0208 QByteArray attr = attribute; 0209 0210 if (d->serverCapability == Metadata) { 0211 attr = ""; 0212 } 0213 0214 QByteArray result; 0215 if (d->metadata.contains(mailBox)) { 0216 if (d->metadata[mailBox].contains(entry)) { 0217 result = d->metadata[mailBox][entry].value(attr); 0218 } 0219 } 0220 return result; 0221 } 0222 0223 QByteArray GetMetaDataJob::metaData(const QByteArray &entry) const 0224 { 0225 qCDebug(KIMAP_LOG) << entry; 0226 Q_D(const GetMetaDataJob); 0227 return d->metadata.value(d->mailBox).value(d->removePrefix(entry)).value(d->getAttribute(entry)); 0228 } 0229 0230 QMap<QByteArray, QMap<QByteArray, QByteArray>> GetMetaDataJob::allMetaData(const QString &mailBox) const 0231 { 0232 Q_D(const GetMetaDataJob); 0233 return d->metadata[mailBox]; 0234 } 0235 0236 QMap<QByteArray, QByteArray> GetMetaDataJob::allMetaData() const 0237 { 0238 Q_D(const GetMetaDataJob); 0239 return allMetaDataForMailbox(d->mailBox); 0240 } 0241 0242 QMap<QByteArray, QByteArray> GetMetaDataJob::allMetaDataForMailbox(const QString &mailbox) const 0243 { 0244 Q_D(const GetMetaDataJob); 0245 const QMap<QByteArray, QMap<QByteArray, QByteArray>> &entries = d->metadata[mailbox]; 0246 QMap<QByteArray, QByteArray> map; 0247 const auto entriesKeys = entries.keys(); 0248 for (const QByteArray &entry : entriesKeys) { 0249 const QMap<QByteArray, QByteArray> &values = entries[entry]; 0250 const auto valuesKeys = values.keys(); 0251 for (const QByteArray &attribute : valuesKeys) { 0252 map.insert(d->addPrefix(entry, attribute), values[attribute]); 0253 } 0254 } 0255 return map; 0256 } 0257 0258 QHash<QString, QMap<QByteArray, QByteArray>> GetMetaDataJob::allMetaDataForMailboxes() const 0259 { 0260 Q_D(const GetMetaDataJob); 0261 QHash<QString, QMap<QByteArray, QByteArray>> mailboxHash; 0262 0263 QMapIterator<QString, QMap<QByteArray, QMap<QByteArray, QByteArray>>> i(d->metadata); 0264 while (i.hasNext()) { 0265 i.next(); 0266 mailboxHash.insert(i.key(), allMetaDataForMailbox(i.key())); 0267 } 0268 return mailboxHash; 0269 } 0270 0271 #include "moc_getmetadatajob.cpp"