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