summaryrefslogtreecommitdiffabout
path: root/kmicromail/libmailwrapper/genericwrapper.cpp
Unidiff
Diffstat (limited to 'kmicromail/libmailwrapper/genericwrapper.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libmailwrapper/genericwrapper.cpp480
1 files changed, 480 insertions, 0 deletions
diff --git a/kmicromail/libmailwrapper/genericwrapper.cpp b/kmicromail/libmailwrapper/genericwrapper.cpp
new file mode 100644
index 0000000..f804e44
--- a/dev/null
+++ b/kmicromail/libmailwrapper/genericwrapper.cpp
@@ -0,0 +1,480 @@
1#include "genericwrapper.h"
2#include <libetpan/libetpan.h>
3#include "mailtypes.h"
4
5
6
7using namespace Opie::Core;
8Genericwrapper::Genericwrapper()
9 : AbstractMail()
10{
11 bodyCache.clear();
12 m_storage = 0;
13 m_folder = 0;
14}
15
16Genericwrapper::~Genericwrapper()
17{
18 if (m_folder) {
19 mailfolder_free(m_folder);
20 }
21 if (m_storage) {
22 mailstorage_free(m_storage);
23 }
24 cleanMimeCache();
25}
26
27void Genericwrapper::fillSingleBody(RecPartP&target,mailmessage*,mailmime*mime)
28{
29 if (!mime) {
30 return;
31 }
32 mailmime_field*field = 0;
33 mailmime_single_fields fields;
34 memset(&fields, 0, sizeof(struct mailmime_single_fields));
35 if (mime->mm_mime_fields != NULL) {
36 mailmime_single_fields_init(&fields, mime->mm_mime_fields,
37 mime->mm_content_type);
38 }
39
40 mailmime_content*type = fields.fld_content;
41 clistcell*current;
42 if (!type) {
43 target->setType("text");
44 target->setSubtype("plain");
45 } else {
46 target->setSubtype(type->ct_subtype);
47 switch(type->ct_type->tp_data.tp_discrete_type->dt_type) {
48 case MAILMIME_DISCRETE_TYPE_TEXT:
49 target->setType("text");
50 break;
51 case MAILMIME_DISCRETE_TYPE_IMAGE:
52 target->setType("image");
53 break;
54 case MAILMIME_DISCRETE_TYPE_AUDIO:
55 target->setType("audio");
56 break;
57 case MAILMIME_DISCRETE_TYPE_VIDEO:
58 target->setType("video");
59 break;
60 case MAILMIME_DISCRETE_TYPE_APPLICATION:
61 target->setType("application");
62 break;
63 case MAILMIME_DISCRETE_TYPE_EXTENSION:
64 default:
65 if (type->ct_type->tp_data.tp_discrete_type->dt_extension) {
66 target->setType(type->ct_type->tp_data.tp_discrete_type->dt_extension);
67 }
68 break;
69 }
70 if (type->ct_parameters) {
71 fillParameters(target,type->ct_parameters);
72 }
73 }
74 if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) {
75 for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) {
76 field = (mailmime_field*)current->data;
77 switch(field->fld_type) {
78 case MAILMIME_FIELD_TRANSFER_ENCODING:
79 target->setEncoding(getencoding(field->fld_data.fld_encoding));
80 break;
81 case MAILMIME_FIELD_ID:
82 target->setIdentifier(field->fld_data.fld_id);
83 break;
84 case MAILMIME_FIELD_DESCRIPTION:
85 target->setDescription(field->fld_data.fld_description);
86 break;
87 default:
88 break;
89 }
90 }
91 }
92}
93
94void Genericwrapper::fillParameters(RecPartP&target,clist*parameters)
95{
96 if (!parameters) {return;}
97 clistcell*current=0;
98 mailmime_parameter*param;
99 for (current=clist_begin(parameters);current!=0;current=clist_next(current)) {
100 param = (mailmime_parameter*)current->data;
101 if (param) {
102 target->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
103 }
104 }
105}
106
107QString Genericwrapper::getencoding(mailmime_mechanism*aEnc)
108{
109 QString enc="7bit";
110 if (!aEnc) return enc;
111 switch(aEnc->enc_type) {
112 case MAILMIME_MECHANISM_7BIT:
113 enc = "7bit";
114 break;
115 case MAILMIME_MECHANISM_8BIT:
116 enc = "8bit";
117 break;
118 case MAILMIME_MECHANISM_BINARY:
119 enc = "binary";
120 break;
121 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
122 enc = "quoted-printable";
123 break;
124 case MAILMIME_MECHANISM_BASE64:
125 enc = "base64";
126 break;
127 case MAILMIME_MECHANISM_TOKEN:
128 default:
129 if (aEnc->enc_token) {
130 enc = QString(aEnc->enc_token);
131 }
132 break;
133 }
134 return enc;
135}
136
137void Genericwrapper::traverseBody(RecBodyP&target,mailmessage*message,mailmime*mime,QValueList<int>recList,unsigned int current_rec,int current_count)
138{
139 if (current_rec >= 10) {
140 ; // odebug << "too deep recursion!" << oendl;
141 }
142 if (!message || !mime) {
143 return;
144 }
145 int r;
146 char*data = 0;
147 size_t len;
148 clistiter * cur = 0;
149 QString b;
150 RecPartP part = new RecPart();
151
152 switch (mime->mm_type) {
153 case MAILMIME_SINGLE:
154 {
155 QValueList<int>countlist = recList;
156 countlist.append(current_count);
157 r = mailmessage_fetch_section(message,mime,&data,&len);
158 part->setSize(len);
159 part->setPositionlist(countlist);
160 b = gen_attachment_id();
161 part->setIdentifier(b);
162 fillSingleBody(part,message,mime);
163 if (part->Type()=="text" && target->Bodytext().isNull()) {
164 encodedString*rs = new encodedString();
165 rs->setContent(data,len);
166 encodedString*res = decode_String(rs,part->Encoding());
167 if (countlist.count()>2) {
168 bodyCache[b]=rs;
169 target->addPart(part);
170 } else {
171 delete rs;
172 }
173 b = QString(res->Content());
174 delete res;
175 target->setBodytext(b);
176 target->setDescription(part);
177 } else {
178 bodyCache[b]=new encodedString(data,len);
179 target->addPart(part);
180 }
181 }
182 break;
183 case MAILMIME_MULTIPLE:
184 {
185 unsigned int ccount = 1;
186 mailmime*cbody=0;
187 QValueList<int>countlist = recList;
188 for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) {
189 cbody = (mailmime*)clist_content(cur);
190 if (cbody->mm_type==MAILMIME_MULTIPLE) {
191 RecPartP targetPart = new RecPart();
192 targetPart->setType("multipart");
193 countlist.append(current_count);
194 targetPart->setPositionlist(countlist);
195 target->addPart(targetPart);
196 }
197 traverseBody(target,message, cbody,countlist,current_rec+1,ccount);
198 if (cbody->mm_type==MAILMIME_MULTIPLE) {
199 countlist = recList;
200 }
201 ++ccount;
202 }
203 }
204 break;
205 case MAILMIME_MESSAGE:
206 {
207 QValueList<int>countlist = recList;
208 countlist.append(current_count);
209 /* the own header is always at recursion 0 - we don't need that */
210 if (current_rec > 0) {
211 part->setPositionlist(countlist);
212 r = mailmessage_fetch_section(message,mime,&data,&len);
213 part->setSize(len);
214 part->setPositionlist(countlist);
215 b = gen_attachment_id();
216 part->setIdentifier(b);
217 part->setType("message");
218 part->setSubtype("rfc822");
219 bodyCache[b]=new encodedString(data,len);
220 target->addPart(part);
221 }
222 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
223 traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,countlist,current_rec+1);
224 }
225 }
226 break;
227 }
228}
229
230RecBodyP Genericwrapper::parseMail( mailmessage * msg )
231{
232 int err = MAILIMF_NO_ERROR;
233 mailmime_single_fields fields;
234 /* is bound to msg and will be freed there */
235 mailmime * mime=0;
236 RecBodyP body = new RecBody();
237 memset(&fields, 0, sizeof(struct mailmime_single_fields));
238 err = mailmessage_get_bodystructure(msg,&mime);
239 QValueList<int>recList;
240 traverseBody(body,msg,mime,recList);
241 return body;
242}
243
244QString Genericwrapper::parseDateTime( mailimf_date_time *date )
245{
246 char tmp[23];
247
248 // snprintf( tmp, 23, "%02i.%02i.%04i %02i:%02i:%02i %+05i",
249 // date->dt_day, date->dt_month, date->dt_year, date->dt_hour, date->dt_min, date->dt_sec, date->dt_zone );
250 snprintf( tmp, 23, "%04i-%02i-%02i %02i:%02i:%02i %+05i",
251 date->dt_year,date->dt_month, date->dt_day, date->dt_hour, date->dt_min, date->dt_sec, date->dt_zone );
252
253 return QString( tmp );
254}
255
256QString Genericwrapper::parseAddressList( mailimf_address_list *list )
257{
258 QString result( "" );
259
260 bool first = true;
261 if (list == 0) return result;
262 for ( clistiter *current = clist_begin( list->ad_list ); current != NULL; current = current->next ) {
263 mailimf_address *addr = (mailimf_address *) current->data;
264
265 if ( !first ) {
266 result.append( "," );
267 } else {
268 first = false;
269 }
270
271 switch ( addr->ad_type ) {
272 case MAILIMF_ADDRESS_MAILBOX:
273 result.append( parseMailbox( addr->ad_data.ad_mailbox ) );
274 break;
275 case MAILIMF_ADDRESS_GROUP:
276 result.append( parseGroup( addr->ad_data.ad_group ) );
277 break;
278 default:
279 ; // odebug << "Generic: unkown mailimf address type" << oendl;
280 break;
281 }
282 }
283
284 return result;
285}
286
287QString Genericwrapper::parseGroup( mailimf_group *group )
288{
289 QString result( "" );
290
291 result.append( group->grp_display_name );
292 result.append( ": " );
293
294 if ( group->grp_mb_list != NULL ) {
295 result.append( parseMailboxList( group->grp_mb_list ) );
296 }
297
298 result.append( ";" );
299
300 return result;
301}
302
303QString Genericwrapper::parseMailbox( mailimf_mailbox *box )
304{
305 QString result( "" );
306
307 if ( box->mb_display_name == NULL ) {
308 result.append( box->mb_addr_spec );
309 } else {
310 result.append( convert_String(box->mb_display_name).latin1() );
311 result.append( " <" );
312 result.append( box->mb_addr_spec );
313 result.append( ">" );
314 }
315
316 return result;
317}
318
319QString Genericwrapper::parseMailboxList( mailimf_mailbox_list *list )
320{
321 QString result( "" );
322
323 bool first = true;
324 for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) {
325 mailimf_mailbox *box = (mailimf_mailbox *) current->data;
326
327 if ( !first ) {
328 result.append( "," );
329 } else {
330 first = false;
331 }
332
333 result.append( parseMailbox( box ) );
334 }
335
336 return result;
337}
338
339encodedString* Genericwrapper::fetchDecodedPart(const RecMailP&,const RecPartP&part)
340{
341 QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part->Identifier());
342 if (it==bodyCache.end()) return new encodedString();
343 encodedString*t = decode_String(it.data(),part->Encoding());
344 return t;
345}
346
347encodedString* Genericwrapper::fetchRawPart(const RecMailP&,const RecPartP&part)
348{
349 QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part->Identifier());
350 if (it==bodyCache.end()) return new encodedString();
351 encodedString*t = it.data();
352 return t;
353}
354
355QString Genericwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part)
356{
357 encodedString*t = fetchDecodedPart(mail,part);
358 QString text=t->Content();
359 delete t;
360 return text;
361}
362
363void Genericwrapper::cleanMimeCache()
364{
365 QMap<QString,encodedString*>::Iterator it = bodyCache.begin();
366 for (;it!=bodyCache.end();++it) {
367 encodedString*t = it.data();
368 //it.setValue(0);
369 if (t) delete t;
370 }
371 bodyCache.clear();
372 ; // odebug << "Genericwrapper: cache cleaned" << oendl;
373}
374
375QStringList Genericwrapper::parseInreplies(mailimf_in_reply_to * in_replies)
376{
377 QStringList res;
378 if (!in_replies || !in_replies->mid_list) return res;
379 clistiter * current = 0;
380 for ( current = clist_begin( in_replies->mid_list ); current != NULL; current = current->next ) {
381 QString h((char*)current->data);
382 while (h.length()>0 && h[0]=='<') {
383 h.remove(0,1);
384 }
385 while (h.length()>0 && h[h.length()-1]=='>') {
386 h.remove(h.length()-1,1);
387 }
388 if (h.length()>0) {
389 res.append(h);
390 }
391 }
392 return res;
393}
394
395void Genericwrapper::parseList(QValueList<Opie::Core::OSmartPointer<RecMail> > &target,mailsession*session,const QString&mailbox,bool mbox_as_to)
396{
397 int r;
398 mailmessage_list * env_list = 0;
399 r = mailsession_get_messages_list(session,&env_list);
400 if (r != MAIL_NO_ERROR) {
401 ; // odebug << "Error message list" << oendl;
402 return;
403 }
404 r = mailsession_get_envelopes_list(session, env_list);
405 if (r != MAIL_NO_ERROR) {
406 ; // odebug << "Error filling message list" << oendl;
407 if (env_list) {
408 mailmessage_list_free(env_list);
409 }
410 return;
411 }
412 mailimf_references * refs = 0;
413 mailimf_in_reply_to * in_replies = 0;
414 uint32_t i = 0;
415 for(; i < carray_count(env_list->msg_tab) ; ++i) {
416 mailmessage * msg;
417 QBitArray mFlags(7);
418 msg = (mailmessage*)carray_get(env_list->msg_tab, i);
419 if (msg->msg_fields == NULL) {
420 //; // odebug << "could not fetch envelope of message " << i << "" << oendl;
421 continue;
422 }
423 RecMailP mail = new RecMail();
424 mail->setWrapper(this);
425 mail_flags * flag_result = 0;
426 r = mailmessage_get_flags(msg,&flag_result);
427 if (r == MAIL_ERROR_NOT_IMPLEMENTED) {
428 mFlags.setBit(FLAG_SEEN);
429 }
430 mailimf_single_fields single_fields;
431 mailimf_single_fields_init(&single_fields, msg->msg_fields);
432 mail->setMsgsize(msg->msg_size);
433 mail->setFlags(mFlags);
434 mail->setMbox(mailbox);
435 mail->setNumber(msg->msg_index);
436 if (single_fields.fld_subject)
437 mail->setSubject( convert_String(single_fields.fld_subject->sbj_value));
438 if (single_fields.fld_from)
439 mail->setFrom(parseMailboxList(single_fields.fld_from->frm_mb_list));
440 if (!mbox_as_to) {
441 if (single_fields.fld_to)
442 mail->setTo( parseAddressList( single_fields.fld_to->to_addr_list ) );
443 } else {
444 mail->setTo(mailbox);
445 }
446 if (single_fields.fld_cc)
447 mail->setCC( parseAddressList( single_fields.fld_cc->cc_addr_list ) );
448 if (single_fields.fld_bcc)
449 mail->setBcc( parseAddressList( single_fields.fld_bcc->bcc_addr_list ) );
450 if (single_fields.fld_orig_date)
451 mail->setDate( parseDateTime( single_fields.fld_orig_date->dt_date_time ) );
452 // crashes when accessing pop3 account?
453 if (single_fields.fld_message_id->mid_value) {
454 mail->setMsgid(QString(single_fields.fld_message_id->mid_value));
455 ; // odebug << "Msgid == " << mail->Msgid().latin1() << "" << oendl;
456 }
457
458 if (single_fields.fld_reply_to) {
459 QStringList t = parseAddressList(single_fields.fld_reply_to->rt_addr_list);
460 if (t.count()>0) {
461 mail->setReplyto(t[0]);
462 }
463 }
464#if 0
465 refs = single_fields.fld_references;
466 if (refs && refs->mid_list && clist_count(refs->mid_list)) {
467 char * text = (char*)refs->mid_list->first->data;
468 mail->setReplyto(QString(text));
469 }
470#endif
471 if (single_fields.fld_in_reply_to && single_fields.fld_in_reply_to->mid_list &&
472 clist_count(single_fields.fld_in_reply_to->mid_list)) {
473 mail->setInreply(parseInreplies(single_fields.fld_in_reply_to));
474 }
475 target.append(mail);
476 }
477 if (env_list) {
478 mailmessage_list_free(env_list);
479 }
480}