00001 #include "genericwrapper.h"
00002 #include <libetpan/libetpan.h>
00003 #include "mailtypes.h"
00004 #include "mailstatics.h"
00005
00006 #include <opie2/odebug.h>
00007 #include <qdatetime.h>
00008
00009 using namespace Opie::Core;
00010 Genericwrapper::Genericwrapper()
00011 : AbstractMail(),MailStatics()
00012 {
00013 bodyCache.clear();
00014 m_storage = 0;
00015 m_folder = 0;
00016 }
00017
00018 Genericwrapper::~Genericwrapper()
00019 {
00020 if (m_folder) {
00021 mailfolder_free(m_folder);
00022 }
00023 if (m_storage) {
00024 mailstorage_free(m_storage);
00025 }
00026 cleanMimeCache();
00027 }
00028
00029 void Genericwrapper::fillSingleBody(RecPartP&target,mailmessage*,mailmime*mime)
00030 {
00031 if (!mime) {
00032 return;
00033 }
00034 mailmime_field*field = 0;
00035 mailmime_single_fields fields;
00036 memset(&fields, 0, sizeof(struct mailmime_single_fields));
00037 if (mime->mm_mime_fields != NULL) {
00038 mailmime_single_fields_init(&fields, mime->mm_mime_fields,
00039 mime->mm_content_type);
00040 }
00041
00042 mailmime_content*type = fields.fld_content;
00043 clistcell*current;
00044 if (!type) {
00045 target->setType("text");
00046 target->setSubtype("plain");
00047 } else {
00048 target->setSubtype(type->ct_subtype);
00049 switch(type->ct_type->tp_data.tp_discrete_type->dt_type) {
00050 case MAILMIME_DISCRETE_TYPE_TEXT:
00051 target->setType("text");
00052 break;
00053 case MAILMIME_DISCRETE_TYPE_IMAGE:
00054 target->setType("image");
00055 break;
00056 case MAILMIME_DISCRETE_TYPE_AUDIO:
00057 target->setType("audio");
00058 break;
00059 case MAILMIME_DISCRETE_TYPE_VIDEO:
00060 target->setType("video");
00061 break;
00062 case MAILMIME_DISCRETE_TYPE_APPLICATION:
00063 target->setType("application");
00064 break;
00065 case MAILMIME_DISCRETE_TYPE_EXTENSION:
00066 default:
00067 if (type->ct_type->tp_data.tp_discrete_type->dt_extension) {
00068 target->setType(type->ct_type->tp_data.tp_discrete_type->dt_extension);
00069 }
00070 break;
00071 }
00072 if (type->ct_parameters) {
00073 fillParameters(target,type->ct_parameters);
00074 }
00075 }
00076 if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) {
00077 for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) {
00078 field = (mailmime_field*)current->data;
00079 switch(field->fld_type) {
00080 case MAILMIME_FIELD_TRANSFER_ENCODING:
00081 target->setEncoding(getencoding(field->fld_data.fld_encoding));
00082 break;
00083 case MAILMIME_FIELD_ID:
00084 target->setIdentifier(field->fld_data.fld_id);
00085 break;
00086 case MAILMIME_FIELD_DESCRIPTION:
00087 target->setDescription(field->fld_data.fld_description);
00088 break;
00089 default:
00090 break;
00091 }
00092 }
00093 }
00094 }
00095
00096 void Genericwrapper::fillParameters(RecPartP&target,clist*parameters)
00097 {
00098 if (!parameters) {return;}
00099 clistcell*current=0;
00100 mailmime_parameter*param;
00101 for (current=clist_begin(parameters);current!=0;current=clist_next(current)) {
00102 param = (mailmime_parameter*)current->data;
00103 if (param) {
00104 target->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
00105 }
00106 }
00107 }
00108
00109 QString Genericwrapper::getencoding(mailmime_mechanism*aEnc)
00110 {
00111 QString enc="7bit";
00112 if (!aEnc) return enc;
00113 switch(aEnc->enc_type) {
00114 case MAILMIME_MECHANISM_7BIT:
00115 enc = "7bit";
00116 break;
00117 case MAILMIME_MECHANISM_8BIT:
00118 enc = "8bit";
00119 break;
00120 case MAILMIME_MECHANISM_BINARY:
00121 enc = "binary";
00122 break;
00123 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
00124 enc = "quoted-printable";
00125 break;
00126 case MAILMIME_MECHANISM_BASE64:
00127 enc = "base64";
00128 break;
00129 case MAILMIME_MECHANISM_TOKEN:
00130 default:
00131 if (aEnc->enc_token) {
00132 enc = QString(aEnc->enc_token);
00133 }
00134 break;
00135 }
00136 return enc;
00137 }
00138
00139 void Genericwrapper::traverseBody(RecBodyP&target,mailmessage*message,mailmime*mime,QValueList<int>recList,unsigned int current_rec,int current_count)
00140 {
00141 if (current_rec >= 10) {
00142 odebug << "too deep recursion!" << oendl;
00143 }
00144 if (!message || !mime) {
00145 return;
00146 }
00147 int r;
00148 char*data = 0;
00149 size_t len;
00150 clistiter * cur = 0;
00151 RecPartP part = new RecPart();
00152
00153 switch (mime->mm_type) {
00154 case MAILMIME_SINGLE:
00155 {
00156 QValueList<int>countlist = recList;
00157 countlist.append(current_count);
00158 r = mailmessage_fetch_section(message,mime,&data,&len);
00159 part->setSize(len);
00160 part->setPositionlist(countlist);
00161 fillSingleBody(part,message,mime);
00162 if (part->Identifier().isEmpty()) {
00163 part->setIdentifier(gen_attachment_id());
00164 }
00165
00166 if (part->Type()=="text" && target->Bodytext().isNull()) {
00167 encodedString*rs = new encodedString();
00168 rs->setContent(data,len);
00169 encodedString*res = decode_String(rs,part->Encoding());
00170 if (countlist.count()>2) {
00171 bodyCache[part->Identifier()]=rs;
00172 target->addPart(part);
00173 } else {
00174 delete rs;
00175 }
00176 QString b;
00177 b = QString(res->Content());
00178 delete res;
00179 target->setBodytext(b);
00180 target->setDescription(part);
00181 } else {
00182 bodyCache[part->Identifier()]=new encodedString(data,len);
00183 target->addPart(part);
00184 }
00185 }
00186 break;
00187 case MAILMIME_MULTIPLE:
00188 {
00189 unsigned int ccount = 1;
00190 mailmime*cbody=0;
00191 QValueList<int>countlist = recList;
00192 for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) {
00193 cbody = (mailmime*)clist_content(cur);
00194 if (cbody->mm_type==MAILMIME_MULTIPLE) {
00195 RecPartP targetPart = new RecPart();
00196 targetPart->setType("multipart");
00197 countlist.append(current_count);
00198 targetPart->setPositionlist(countlist);
00199 target->addPart(targetPart);
00200 }
00201 traverseBody(target,message, cbody,countlist,current_rec+1,ccount);
00202 if (cbody->mm_type==MAILMIME_MULTIPLE) {
00203 countlist = recList;
00204 }
00205 ++ccount;
00206 }
00207 }
00208 break;
00209 case MAILMIME_MESSAGE:
00210 {
00211 QValueList<int>countlist = recList;
00212 countlist.append(current_count);
00213
00214 if (current_rec > 0) {
00215 part->setPositionlist(countlist);
00216 r = mailmessage_fetch_section(message,mime,&data,&len);
00217 part->setSize(len);
00218 part->setPositionlist(countlist);
00219 part->setIdentifier(gen_attachment_id());
00220 part->setType("message");
00221 part->setSubtype("rfc822");
00222 bodyCache[part->Identifier()]=new encodedString(data,len);
00223 target->addPart(part);
00224 }
00225 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
00226 traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,countlist,current_rec+1);
00227 }
00228 }
00229 break;
00230 }
00231 }
00232
00233 RecBodyP Genericwrapper::parseMail( mailmessage * msg )
00234 {
00235 int err = MAILIMF_NO_ERROR;
00236 mailmime_single_fields fields;
00237
00238 mailmime * mime=0;
00239 RecBodyP body = new RecBody();
00240 memset(&fields, 0, sizeof(struct mailmime_single_fields));
00241 err = mailmessage_get_bodystructure(msg,&mime);
00242 QValueList<int>recList;
00243 traverseBody(body,msg,mime,recList);
00244 return body;
00245 }
00246
00247 QString Genericwrapper::parseAddressList( mailimf_address_list *list )
00248 {
00249 QString result( "" );
00250
00251 bool first = true;
00252 if (list == 0) return result;
00253 for ( clistiter *current = clist_begin( list->ad_list ); current != NULL; current = current->next ) {
00254 mailimf_address *addr = (mailimf_address *) current->data;
00255
00256 if ( !first ) {
00257 result.append( "," );
00258 } else {
00259 first = false;
00260 }
00261
00262 switch ( addr->ad_type ) {
00263 case MAILIMF_ADDRESS_MAILBOX:
00264 result.append( parseMailbox( addr->ad_data.ad_mailbox ) );
00265 break;
00266 case MAILIMF_ADDRESS_GROUP:
00267 result.append( parseGroup( addr->ad_data.ad_group ) );
00268 break;
00269 default:
00270 odebug << "Generic: unkown mailimf address type" << oendl;
00271 break;
00272 }
00273 }
00274
00275 return result;
00276 }
00277
00278 QString Genericwrapper::parseGroup( mailimf_group *group )
00279 {
00280 QString result( "" );
00281
00282 result.append( group->grp_display_name );
00283 result.append( ": " );
00284
00285 if ( group->grp_mb_list != NULL ) {
00286 result.append( parseMailboxList( group->grp_mb_list ) );
00287 }
00288
00289 result.append( ";" );
00290
00291 return result;
00292 }
00293
00294 QString Genericwrapper::parseMailbox( mailimf_mailbox *box )
00295 {
00296 QString result( "" );
00297
00298 if ( box->mb_display_name == NULL ) {
00299 result.append( box->mb_addr_spec );
00300 } else {
00301 result.append( convert_String(box->mb_display_name).latin1() );
00302 result.append( " <" );
00303 result.append( box->mb_addr_spec );
00304 result.append( ">" );
00305 }
00306
00307 return result;
00308 }
00309
00310 QString Genericwrapper::parseMailboxList( mailimf_mailbox_list *list )
00311 {
00312 QString result( "" );
00313
00314 bool first = true;
00315 for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) {
00316 mailimf_mailbox *box = (mailimf_mailbox *) current->data;
00317
00318 if ( !first ) {
00319 result.append( "," );
00320 } else {
00321 first = false;
00322 }
00323
00324 result.append( parseMailbox( box ) );
00325 }
00326
00327 return result;
00328 }
00329
00330 encodedString* Genericwrapper::fetchDecodedPart(const RecMailP&,const RecPartP&part)
00331 {
00332 QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part->Identifier());
00333 if (it==bodyCache.end()) return new encodedString();
00334 encodedString*t = decode_String(it.data(),part->Encoding());
00335 return t;
00336 }
00337
00338 encodedString* Genericwrapper::fetchRawPart(const RecMailP&,const RecPartP&part)
00339 {
00340 QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part->Identifier());
00341 if (it==bodyCache.end()) return new encodedString();
00342 encodedString*t = it.data();
00343 return t;
00344 }
00345
00346 QString Genericwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part)
00347 {
00348 encodedString*t = fetchDecodedPart(mail,part);
00349 QString text=t->Content();
00350 delete t;
00351 return text;
00352 }
00353
00354 void Genericwrapper::cleanMimeCache()
00355 {
00356 QMap<QString,encodedString*>::Iterator it = bodyCache.begin();
00357 for (;it!=bodyCache.end();++it) {
00358 encodedString*t = it.data();
00359
00360 if (t) delete t;
00361 }
00362 bodyCache.clear();
00363 odebug << "Genericwrapper: cache cleaned" << oendl;
00364 }
00365
00366 QStringList Genericwrapper::parseInreplies(mailimf_in_reply_to * in_replies)
00367 {
00368 QStringList res;
00369 if (!in_replies || !in_replies->mid_list) return res;
00370 clistiter * current = 0;
00371 for ( current = clist_begin( in_replies->mid_list ); current != NULL; current = current->next ) {
00372 QString h((char*)current->data);
00373 while (h.length()>0 && h[0]=='<') {
00374 h.remove(0,1);
00375 }
00376 while (h.length()>0 && h[h.length()-1]=='>') {
00377 h.remove(h.length()-1,1);
00378 }
00379 if (h.length()>0) {
00380 res.append(h);
00381 }
00382 }
00383 return res;
00384 }
00385
00386 void Genericwrapper::parseList(QValueList<Opie::Core::OSmartPointer<RecMail> > &target,mailsession*session,const QString&mailbox,bool mbox_as_to)
00387 {
00388 int r,toffset;
00389 mailmessage_list * env_list = 0;
00390 r = mailsession_get_messages_list(session,&env_list);
00391 if (r != MAIL_NO_ERROR) {
00392 odebug << "Error message list" << oendl;
00393 return;
00394 }
00395 r = mailsession_get_envelopes_list(session, env_list);
00396 if (r != MAIL_NO_ERROR) {
00397 odebug << "Error filling message list" << oendl;
00398 if (env_list) {
00399 mailmessage_list_free(env_list);
00400 }
00401 return;
00402 }
00403 mailimf_references * refs = 0;
00404 mailimf_in_reply_to * in_replies = 0;
00405 uint32_t i = 0;
00406 for(; i < carray_count(env_list->msg_tab) ; ++i) {
00407 mailmessage * msg;
00408 QBitArray mFlags(7);
00409 msg = (mailmessage*)carray_get(env_list->msg_tab, i);
00410 if (msg->msg_fields == NULL) {
00411
00412 continue;
00413 }
00414 RecMailP mail = new RecMail();
00415 mail->setWrapper(this);
00416 mail_flags * flag_result = 0;
00417 r = mailmessage_get_flags(msg,&flag_result);
00418 if (r == MAIL_ERROR_NOT_IMPLEMENTED) {
00419 mFlags.setBit(FLAG_SEEN);
00420 }
00421 mailimf_single_fields single_fields;
00422 mailimf_single_fields_init(&single_fields, msg->msg_fields);
00423 mail->setMsgsize(msg->msg_size);
00424 mail->setFlags(mFlags);
00425 mail->setMbox(mailbox);
00426 mail->setNumber(msg->msg_index);
00427 if (single_fields.fld_subject)
00428 mail->setSubject( convert_String(single_fields.fld_subject->sbj_value));
00429 if (single_fields.fld_from)
00430 mail->setFrom(parseMailboxList(single_fields.fld_from->frm_mb_list));
00431 if (!mbox_as_to) {
00432 if (single_fields.fld_to)
00433 mail->setTo( parseAddressList( single_fields.fld_to->to_addr_list ) );
00434 } else {
00435 mail->setTo(mailbox);
00436 }
00437 if (single_fields.fld_cc)
00438 mail->setCC( parseAddressList( single_fields.fld_cc->cc_addr_list ) );
00439 if (single_fields.fld_bcc)
00440 mail->setBcc( parseAddressList( single_fields.fld_bcc->bcc_addr_list ) );
00441 if (single_fields.fld_orig_date) {
00442 QDateTime d = parseDateTime( single_fields.fld_orig_date->dt_date_time,toffset);
00443 mail->setDate( d,toffset );
00444 }
00445 if (single_fields.fld_message_id && single_fields.fld_message_id->mid_value) {
00446 mail->setMsgid(QString(single_fields.fld_message_id->mid_value));
00447 }
00448 if (single_fields.fld_reply_to) {
00449 QStringList t = parseAddressList(single_fields.fld_reply_to->rt_addr_list);
00450 if (t.count()>0) {
00451 mail->setReplyto(t[0]);
00452 }
00453 }
00454 #if 0
00455 refs = single_fields.fld_references;
00456 if (refs && refs->mid_list && clist_count(refs->mid_list)) {
00457 char * text = (char*)refs->mid_list->first->data;
00458 mail->setReplyto(QString(text));
00459 }
00460 #endif
00461 if (single_fields.fld_in_reply_to && single_fields.fld_in_reply_to->mid_list &&
00462 clist_count(single_fields.fld_in_reply_to->mid_list)) {
00463 mail->setInreply(parseInreplies(single_fields.fld_in_reply_to));
00464 }
00465 target.append(mail);
00466 }
00467 if (env_list) {
00468 mailmessage_list_free(env_list);
00469 }
00470 }