1/*
2 Copyright (c) 2009 Andras Mantia <amantia@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "getmetadatajob.h"
21
22#include <KDE/KLocalizedString>
23#include <KDE/KDebug>
24
25#include "metadatajobbase_p.h"
26#include "message_p.h"
27#include "session_p.h"
28#include "rfccodecs.h"
29
30namespace KIMAP
31{
32 class GetMetaDataJobPrivate : public MetaDataJobBasePrivate
33 {
34 public:
35 GetMetaDataJobPrivate( Session *session, const QString& name ) : MetaDataJobBasePrivate( session, name ), maxSize( -1 ), depth( "0" ) { }
36 ~GetMetaDataJobPrivate() { }
37
38 qint64 maxSize;
39 QByteArray depth;
40 QList<QByteArray> entries;
41 QList<QByteArray> attributes;
42 QMap<QString, QMap<QByteArray, QMap<QByteArray, QByteArray> > > metadata;
43 // ^ mailbox ^ entry ^attribute ^ value
44 };
45}
46
47using namespace KIMAP;
48
49GetMetaDataJob::GetMetaDataJob( Session *session )
50 : MetaDataJobBase( *new GetMetaDataJobPrivate( session, i18n( "GetMetaData" ) ) )
51{
52}
53
54GetMetaDataJob::~GetMetaDataJob()
55{
56}
57
58void GetMetaDataJob::doStart()
59{
60 Q_D( GetMetaDataJob );
61 QByteArray parameters;
62 parameters = '\"' + KIMAP::encodeImapFolderName( d->mailBox.toUtf8() ) + "\" ";
63
64 QByteArray command = "GETMETADATA";
65 if ( d->serverCapability == Annotatemore ) {
66 d->m_name = i18n( "GetAnnotation" );
67 command = "GETANNOTATION";
68 if ( d->entries.size() > 1 ) {
69 parameters += '(';
70 }
71 Q_FOREACH ( const QByteArray &entry, d->entries ) {
72 parameters += '\"' + entry + "\" ";
73 }
74 if ( d->entries.size() > 1 ) {
75 parameters[parameters.length() - 1 ] = ')';
76 parameters += ' ';
77 }
78
79 if ( d->attributes.size() > 1 ) {
80 parameters += '(';
81 }
82 Q_FOREACH ( const QByteArray &attribute, d->attributes ) {
83 parameters += '\"' + attribute + "\" ";
84 }
85 if ( d->attributes.size() > 1 ) {
86 parameters[parameters.length() - 1 ] = ')';
87 } else {
88 parameters.truncate( parameters.length() - 1 );
89 }
90
91 } else {
92
93 QByteArray options;
94 if ( d->depth != "0" ) {
95 options = "DEPTH " + d->depth;
96 }
97 if ( d->maxSize != -1 ) {
98 if ( !options.isEmpty() ) {
99 options += ' ';
100 }
101 options += "MAXSIZE " + QByteArray::number( d->maxSize );
102 }
103
104 if ( !options.isEmpty() ) {
105 parameters = "(" + options + ") " + parameters;
106 }
107
108 if ( d->entries.size() >= 1 ) {
109 parameters += '(';
110 Q_FOREACH ( const QByteArray &entry, d->entries ) {
111 parameters += entry + " ";
112 }
113 parameters[parameters.length() - 1 ] = ')';
114 } else {
115 parameters.truncate( parameters.length() - 1 );
116 }
117 }
118
119 d->tags << d->sessionInternal()->sendCommand( command, parameters );
120// kDebug() << "SENT: " << command << " " << parameters;
121}
122
123void GetMetaDataJob::handleResponse( const Message &response )
124{
125 Q_D( GetMetaDataJob );
126// kDebug() << "GOT: " << response.toString();
127
128 //TODO: handle NO error messages having [METADATA MAXSIZE NNN], [METADATA TOOMANY], [METADATA NOPRIVATE] (see rfc5464)
129 // or [ANNOTATEMORE TOOBIG], [ANNOTATEMORE TOOMANY] respectively
130 if ( handleErrorReplies( response ) == NotHandled ) {
131 if ( response.content.size() >= 4 ) {
132 if ( d->serverCapability == Annotatemore && response.content[1].toString() == "ANNOTATION" ) {
133 QString mailBox = QString::fromUtf8( KIMAP::decodeImapFolderName( response.content[2].toString() ) );
134
135 int i = 3;
136 while ( i < response.content.size() - 1 ) {
137 QByteArray entry = response.content[i].toString();
138 QList<QByteArray> attributes = response.content[i + 1].toList();
139 int j = 0;
140 while ( j < attributes.size() - 1 ) {
141 d->metadata[mailBox][entry][attributes[j]] = attributes[j + 1];
142 j += 2;
143 }
144 i += 2;
145 }
146 } else if ( d->serverCapability == Metadata && response.content[1].toString() == "METADATA" ) {
147 QString mailBox = QString::fromUtf8( KIMAP::decodeImapFolderName( response.content[2].toString() ) );
148
149 const QList<QByteArray> &entries = response.content[3].toList();
150 int i = 0;
151 while ( i < entries.size() - 1 ) {
152 const QByteArray &value = entries[i + 1];
153 QByteArray &targetValue = d->metadata[mailBox][entries[i]][""];
154 if ( value != "NIL" ) { //This just indicates no value
155 targetValue = value;
156 }
157 i += 2;
158 }
159 }
160 }
161 }
162}
163
164void GetMetaDataJob::addEntry(const QByteArray &entry, const QByteArray &attribute)
165{
166 Q_D( GetMetaDataJob );
167 if ( d->serverCapability == Annotatemore && attribute.isNull() ) {
168 qWarning() << "In ANNOTATEMORE mode an attribute must be specified with addEntry!";
169 }
170 d->entries.append( entry );
171 d->attributes.append( attribute );
172}
173
174void GetMetaDataJob::addRequestedEntry(const QByteArray &entry)
175{
176 Q_D( GetMetaDataJob );
177 d->entries.append( d->removePrefix(entry) );
178 d->attributes.append( d->getAttribute( entry ) );
179}
180
181void GetMetaDataJob::setMaximumSize(qint64 size)
182{
183 Q_D( GetMetaDataJob );
184 d->maxSize = size;
185}
186
187void GetMetaDataJob::setDepth(Depth depth)
188{
189 Q_D( GetMetaDataJob );
190
191 switch ( depth ) {
192 case OneLevel:
193 d->depth = "1"; //krazy:exclude=doublequote_chars
194 break;
195 case AllLevels:
196 d->depth = "infinity";
197 break;
198 default:
199 d->depth = "0"; //krazy:exclude=doublequote_chars
200 }
201}
202
203QByteArray GetMetaDataJob::metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute) const
204{
205 Q_D( const GetMetaDataJob );
206 QByteArray attr = attribute;
207
208 if ( d->serverCapability == Metadata ) {
209 attr = "";
210 }
211
212 QByteArray result;
213 if ( d->metadata.contains( mailBox ) ) {
214 if ( d->metadata[mailBox].contains( entry ) ) {
215 result = d->metadata[mailBox][entry].value( attr );
216 }
217 }
218 return result;
219}
220
221QByteArray GetMetaDataJob::metaData(const QByteArray& entry) const
222{
223 kDebug() << entry;
224 Q_D( const GetMetaDataJob );
225 return d->metadata.value( d->mailBox ).value( d->removePrefix(entry) ).value( d->getAttribute( entry ) );
226}
227
228QMap<QByteArray, QMap<QByteArray, QByteArray> > GetMetaDataJob::allMetaData(const QString &mailBox) const
229{
230 Q_D( const GetMetaDataJob );
231 return d->metadata[mailBox];
232}
233
234QMap<QByteArray, QByteArray> GetMetaDataJob::allMetaData() const
235{
236 Q_D( const GetMetaDataJob );
237 const QMap<QByteArray, QMap<QByteArray, QByteArray> > &entries = d->metadata[d->mailBox];
238 QMap<QByteArray, QByteArray> map;
239 foreach(const QByteArray &entry, entries.keys()) {
240 const QMap<QByteArray, QByteArray> &values = entries[entry];
241 foreach(const QByteArray &attribute, values.keys()) {
242 map.insert(d->addPrefix(entry, attribute), values[attribute]);
243 }
244 }
245 return map;
246}
247
248