summaryrefslogtreecommitdiff
authoralwin <alwin>2003-12-20 13:36:34 (UTC)
committer alwin <alwin>2003-12-20 13:36:34 (UTC)
commitadb369c28cac7600b3912d6a3fdb645f1b1d571d (patch) (side-by-side diff)
tree554fc2f00a3ea97aad6ef0382e4cc1aec3def070
parentd9ffcee06ec97f4a9e00ff0a9071d7a58e5075a1 (diff)
downloadopie-adb369c28cac7600b3912d6a3fdb645f1b1d571d.zip
opie-adb369c28cac7600b3912d6a3fdb645f1b1d571d.tar.gz
opie-adb369c28cac7600b3912d6a3fdb645f1b1d571d.tar.bz2
fetching attachments from a pop3mail works.
this moment the whole message will be hold in memory until I have an idea for a clean(!) filebased cache which will not get to large. Thats why the biggest pop3 mail we can fetch is 5MB, this should be enough.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/mail/abstractmail.cpp15
-rw-r--r--noncore/net/mail/abstractmail.h3
-rw-r--r--noncore/net/mail/libmailwrapper/abstractmail.cpp15
-rw-r--r--noncore/net/mail/libmailwrapper/abstractmail.h3
-rw-r--r--noncore/net/mail/libmailwrapper/pop3wrapper.cpp40
-rw-r--r--noncore/net/mail/libmailwrapper/pop3wrapper.h7
-rw-r--r--noncore/net/mail/pop3wrapper.cpp40
-rw-r--r--noncore/net/mail/pop3wrapper.h7
8 files changed, 112 insertions, 18 deletions
diff --git a/noncore/net/mail/abstractmail.cpp b/noncore/net/mail/abstractmail.cpp
index 3d76c96..626b9aa 100644
--- a/noncore/net/mail/abstractmail.cpp
+++ b/noncore/net/mail/abstractmail.cpp
@@ -1,68 +1,83 @@
#include "abstractmail.h"
#include "imapwrapper.h"
#include "pop3wrapper.h"
#include "mailtypes.h"
#include <qstring.h>
+#include <qfile.h>
+#include <qtextstream.h>
#include <stdlib.h>
#include <libetpan/mailmime_content.h>
AbstractMail* AbstractMail::getWrapper(IMAPaccount *a)
{
return new IMAPwrapper(a);
}
AbstractMail* AbstractMail::getWrapper(POP3account *a)
{
return new POP3wrapper(a);
}
encodedString* AbstractMail::decode_String(const encodedString*text,const QString&enc)
{
qDebug("Decode string start");
char*result_text;
size_t index = 0;
/* reset for recursive use! */
size_t target_length = 0;
result_text = 0;
int mimetype = MAILMIME_MECHANISM_7BIT;
if (enc.lower()=="quoted-printable") {
mimetype = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
} else if (enc.lower()=="base64") {
mimetype = MAILMIME_MECHANISM_BASE64;
} else if (enc.lower()=="8bit") {
mimetype = MAILMIME_MECHANISM_8BIT;
} else if (enc.lower()=="binary") {
mimetype = MAILMIME_MECHANISM_BINARY;
}
int err = mailmime_part_parse(text->Content(),text->Length(),&index,mimetype,
&result_text,&target_length);
encodedString* result = new encodedString();
if (err == MAILIMF_NO_ERROR) {
result->setContent(result_text,target_length);
}
qDebug("Decode string finished");
return result;
}
QString AbstractMail::convert_String(const char*text)
{
size_t index = 0;
char*res = 0;
/* attention - doesn't work with arm systems! */
int err = mailmime_encoded_phrase_parse("iso-8859-1",
text, strlen(text),&index, "iso-8859-1",&res);
if (err != MAILIMF_NO_ERROR) {
if (res) free(res);
return QString(text);
}
if (res) {
QString result(res);
free(res);
return result;
}
return QString(text);
}
+
+/* cp & paste from launcher */
+QString AbstractMail::gen_attachment_id()
+{
+ QFile file( "/proc/sys/kernel/random/uuid" );
+ if (!file.open(IO_ReadOnly ) )
+ return QString::null;
+
+ QTextStream stream(&file);
+
+ return "{" + stream.read().stripWhiteSpace() + "}";
+}
+
diff --git a/noncore/net/mail/abstractmail.h b/noncore/net/mail/abstractmail.h
index c16e9c0..8dd2e12 100644
--- a/noncore/net/mail/abstractmail.h
+++ b/noncore/net/mail/abstractmail.h
@@ -1,36 +1,39 @@
#ifndef __abstract_mail_
#define __abstract_mail_
#include <qobject.h>
#include "settings.h"
class RecMail;
class RecBody;
class RecPart;
class IMAPwrapper;
class POP3wrapper;
class Folder;
class encodedString;
class AbstractMail:public QObject
{
Q_OBJECT
public:
AbstractMail(){};
virtual ~AbstractMail(){}
virtual QList<Folder>* listFolders()=0;
virtual void listMessages(const QString & mailbox,QList<RecMail>&target )=0;
virtual RecBody fetchBody(const RecMail&mail)=0;
virtual QString fetchTextPart(const RecMail&mail,const RecPart&part)=0;
virtual encodedString* fetchDecodedPart(const RecMail&mail,const RecPart&part)=0;
virtual encodedString* fetchRawPart(const RecMail&mail,const RecPart&part)=0;
virtual void deleteMail(const RecMail&mail)=0;
virtual void answeredMail(const RecMail&mail)=0;
static AbstractMail* getWrapper(IMAPaccount *a);
static AbstractMail* getWrapper(POP3account *a);
+
+protected:
static encodedString*decode_String(const encodedString*text,const QString&enc);
static QString convert_String(const char*text);
+ static QString gen_attachment_id();
};
#endif
diff --git a/noncore/net/mail/libmailwrapper/abstractmail.cpp b/noncore/net/mail/libmailwrapper/abstractmail.cpp
index 3d76c96..626b9aa 100644
--- a/noncore/net/mail/libmailwrapper/abstractmail.cpp
+++ b/noncore/net/mail/libmailwrapper/abstractmail.cpp
@@ -1,68 +1,83 @@
#include "abstractmail.h"
#include "imapwrapper.h"
#include "pop3wrapper.h"
#include "mailtypes.h"
#include <qstring.h>
+#include <qfile.h>
+#include <qtextstream.h>
#include <stdlib.h>
#include <libetpan/mailmime_content.h>
AbstractMail* AbstractMail::getWrapper(IMAPaccount *a)
{
return new IMAPwrapper(a);
}
AbstractMail* AbstractMail::getWrapper(POP3account *a)
{
return new POP3wrapper(a);
}
encodedString* AbstractMail::decode_String(const encodedString*text,const QString&enc)
{
qDebug("Decode string start");
char*result_text;
size_t index = 0;
/* reset for recursive use! */
size_t target_length = 0;
result_text = 0;
int mimetype = MAILMIME_MECHANISM_7BIT;
if (enc.lower()=="quoted-printable") {
mimetype = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
} else if (enc.lower()=="base64") {
mimetype = MAILMIME_MECHANISM_BASE64;
} else if (enc.lower()=="8bit") {
mimetype = MAILMIME_MECHANISM_8BIT;
} else if (enc.lower()=="binary") {
mimetype = MAILMIME_MECHANISM_BINARY;
}
int err = mailmime_part_parse(text->Content(),text->Length(),&index,mimetype,
&result_text,&target_length);
encodedString* result = new encodedString();
if (err == MAILIMF_NO_ERROR) {
result->setContent(result_text,target_length);
}
qDebug("Decode string finished");
return result;
}
QString AbstractMail::convert_String(const char*text)
{
size_t index = 0;
char*res = 0;
/* attention - doesn't work with arm systems! */
int err = mailmime_encoded_phrase_parse("iso-8859-1",
text, strlen(text),&index, "iso-8859-1",&res);
if (err != MAILIMF_NO_ERROR) {
if (res) free(res);
return QString(text);
}
if (res) {
QString result(res);
free(res);
return result;
}
return QString(text);
}
+
+/* cp & paste from launcher */
+QString AbstractMail::gen_attachment_id()
+{
+ QFile file( "/proc/sys/kernel/random/uuid" );
+ if (!file.open(IO_ReadOnly ) )
+ return QString::null;
+
+ QTextStream stream(&file);
+
+ return "{" + stream.read().stripWhiteSpace() + "}";
+}
+
diff --git a/noncore/net/mail/libmailwrapper/abstractmail.h b/noncore/net/mail/libmailwrapper/abstractmail.h
index c16e9c0..8dd2e12 100644
--- a/noncore/net/mail/libmailwrapper/abstractmail.h
+++ b/noncore/net/mail/libmailwrapper/abstractmail.h
@@ -1,36 +1,39 @@
#ifndef __abstract_mail_
#define __abstract_mail_
#include <qobject.h>
#include "settings.h"
class RecMail;
class RecBody;
class RecPart;
class IMAPwrapper;
class POP3wrapper;
class Folder;
class encodedString;
class AbstractMail:public QObject
{
Q_OBJECT
public:
AbstractMail(){};
virtual ~AbstractMail(){}
virtual QList<Folder>* listFolders()=0;
virtual void listMessages(const QString & mailbox,QList<RecMail>&target )=0;
virtual RecBody fetchBody(const RecMail&mail)=0;
virtual QString fetchTextPart(const RecMail&mail,const RecPart&part)=0;
virtual encodedString* fetchDecodedPart(const RecMail&mail,const RecPart&part)=0;
virtual encodedString* fetchRawPart(const RecMail&mail,const RecPart&part)=0;
virtual void deleteMail(const RecMail&mail)=0;
virtual void answeredMail(const RecMail&mail)=0;
static AbstractMail* getWrapper(IMAPaccount *a);
static AbstractMail* getWrapper(POP3account *a);
+
+protected:
static encodedString*decode_String(const encodedString*text,const QString&enc);
static QString convert_String(const char*text);
+ static QString gen_attachment_id();
};
#endif
diff --git a/noncore/net/mail/libmailwrapper/pop3wrapper.cpp b/noncore/net/mail/libmailwrapper/pop3wrapper.cpp
index 65cd4ba..d3447f4 100644
--- a/noncore/net/mail/libmailwrapper/pop3wrapper.cpp
+++ b/noncore/net/mail/libmailwrapper/pop3wrapper.cpp
@@ -1,149 +1,163 @@
#include <stdlib.h>
#include "pop3wrapper.h"
#include "mailtypes.h"
#include "logindialog.h"
#include <libetpan/mailpop3.h>
#include <libetpan/mailmime.h>
#include <libetpan/data_message_driver.h>
#include <qfile.h>
/* we don't fetch messages larger than 5 MB */
#define HARD_MSG_SIZE_LIMIT 5242880
POP3wrapper::POP3wrapper( POP3account *a )
{
account = a;
m_pop3 = NULL;
msgTempName = a->getFileName()+"_msg_cache";
last_msg_id = 0;
+ bodyCache.clear();
}
POP3wrapper::~POP3wrapper()
{
logout();
QFile msg_cache(msgTempName);
if (msg_cache.exists()) {
msg_cache.remove();
}
+ cleanUpCache();
+}
+
+void POP3wrapper::cleanUpCache()
+{
+ QMap<QString,encodedString*>::Iterator it = bodyCache.begin();
+ for (;it!=bodyCache.end();++it) {
+ encodedString*t = it.data();
+ //it.setValue(0);
+ if (t) delete t;
+ }
+ bodyCache.clear();
}
void POP3wrapper::pop3_progress( size_t current, size_t maximum )
{
//qDebug( "POP3: %i of %i", current, maximum );
}
RecBody POP3wrapper::fetchBody( const RecMail &mail )
{
int err = MAILPOP3_NO_ERROR;
char *message;
size_t length = 0;
login();
if ( !m_pop3 ) {
return RecBody();
}
RecBody body;
QFile msg_cache(msgTempName);
if (mail.Msgsize()>HARD_MSG_SIZE_LIMIT) {
qDebug("Message to large: %i",mail.Msgsize());
return body;
}
+ cleanUpCache();
if (mail.getNumber()!=last_msg_id) {
if (msg_cache.exists()) {
msg_cache.remove();
}
msg_cache.open(IO_ReadWrite|IO_Truncate);
last_msg_id = mail.getNumber();
err = mailpop3_retr( m_pop3, mail.getNumber(), &message, &length );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "POP3: error retrieving body with index %i", mail.getNumber() );
last_msg_id = 0;
return RecBody();
}
msg_cache.writeBlock(message,length);
} else {
QString msg="";
msg_cache.open(IO_ReadOnly);
message = new char[4096];
memset(message,0,4096);
while (msg_cache.readBlock(message,4095)>0) {
msg+=message;
memset(message,0,4096);
}
delete message;
message = (char*)malloc(msg.length()+1*sizeof(char));
memset(message,0,msg.length()+1);
memcpy(message,msg.latin1(),msg.length());
}
body = parseMail(message);
free(message);
return body;
}
RecBody POP3wrapper::parseMail( char *message )
{
int err = MAILIMF_NO_ERROR;
/* these vars are used recurcive! set it to 0!!!!!!!!!!!!!!!!! */
size_t curTok = 0;
mailimf_message *result = 0;
mailmessage * msg=0;
mailmime_single_fields fields;
/* is bound to msg and will be freed there */
struct mailmime * mime=0;
RecBody body;
err = mailimf_message_parse( (char *) message, strlen( message ), &curTok, &result );
if ( err != MAILIMF_NO_ERROR ) {
if (result) mailimf_message_free(result);
return body;
}
char*body_msg = message;
msg = mailmessage_new();
mailmessage_init(msg, NULL, data_message_driver, 0, strlen(body_msg));
generic_message_t * msg_data;
msg_data = (generic_message_t *)msg->msg_data;
msg_data->msg_fetched = 1;
msg_data->msg_message = body_msg;
msg_data->msg_length = strlen(body_msg);
memset(&fields, 0, sizeof(struct mailmime_single_fields));
err = mailmessage_get_bodystructure(msg,&mime);
traverseBody(body,msg,mime);
mailmessage_free(msg);
return body;
}
void POP3wrapper::listMessages(const QString &, QList<RecMail> &target )
{
int err = MAILPOP3_NO_ERROR;
char * header = 0;
/* these vars are used recurcive! set it to 0!!!!!!!!!!!!!!!!! */
size_t length = 0;
carray * messages = 0;
login();
if (!m_pop3) return;
mailpop3_list( m_pop3, &messages );
for (unsigned int i = 0; i < carray_count(messages);++i) {
mailpop3_msg_info *info;
err = mailpop3_get_msg_info(m_pop3,i+1,&info);
if (info->msg_deleted)
continue;
err = mailpop3_header( m_pop3, info->msg_index, &header, &length );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "POP3: error retrieving header msgid: %i", info->msg_index );
free(header);
return;
}
RecMail *mail = parseHeader( header );
@@ -312,254 +326,264 @@ QString POP3wrapper::parseMailboxList( mailimf_mailbox_list *list )
for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) {
mailimf_mailbox *box = (mailimf_mailbox *) current->data;
if ( !first ) {
result.append( "," );
} else {
first = false;
}
result.append( parseMailbox( box ) );
}
return result;
}
void POP3wrapper::login()
{
/* we'll hold the line */
if ( m_pop3 != NULL ) return;
const char *server, *user, *pass;
uint16_t port;
int err = MAILPOP3_NO_ERROR;
server = account->getServer().latin1();
port = account->getPort().toUInt();
if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) {
LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true );
login.show();
if ( QDialog::Accepted == login.exec() ) {
// ok
user = strdup( login.getUser().latin1() );
pass = strdup( login.getPassword().latin1() );
} else {
// cancel
qDebug( "POP3: Login canceled" );
return;
}
} else {
user = account->getUser().latin1();
pass = account->getPassword().latin1();
}
m_pop3 = mailpop3_new( 200, &pop3_progress );
// connect
if (account->getSSL()) {
err = mailpop3_ssl_connect( m_pop3, (char*)server, port );
} else {
err = mailpop3_socket_connect( m_pop3, (char*)server, port );
}
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "pop3: error connecting to %s\n reason: %s", server,
m_pop3->pop3_response );
mailpop3_free( m_pop3 );
m_pop3 = NULL;
return;
}
qDebug( "POP3: connected!" );
// login
// TODO: decide if apop or plain login should be used
err = mailpop3_login( m_pop3, (char *) user, (char *) pass );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "pop3: error logging in: %s", m_pop3->pop3_response );
logout();
return;
}
qDebug( "POP3: logged in!" );
}
void POP3wrapper::logout()
{
int err = MAILPOP3_NO_ERROR;
if ( m_pop3 == NULL ) return;
err = mailpop3_quit( m_pop3 );
mailpop3_free( m_pop3 );
m_pop3 = NULL;
}
QList<Folder>* POP3wrapper::listFolders()
{
/* TODO: integrate MH directories
but not before version 0.1 ;)
*/
QList<Folder> * folders = new QList<Folder>();
folders->setAutoDelete( false );
Folder*inb=new Folder("INBOX","/");
folders->append(inb);
return folders;
}
-QString POP3wrapper::fetchTextPart(const RecMail&,const RecPart&)
+QString POP3wrapper::fetchTextPart(const RecMail&mail,const RecPart&part)
{
- return "";
+ encodedString*t = fetchDecodedPart(mail,part);
+ QString text=t->Content();
+ delete t;
+ return text;
}
void POP3wrapper::deleteMail(const RecMail&mail)
{
login();
if (!m_pop3) return;
int err = mailpop3_dele(m_pop3,mail.getNumber());
if (err != MAILPOP3_NO_ERROR) {
qDebug("error deleting mail");
}
}
void POP3wrapper::answeredMail(const RecMail&)
{
}
-encodedString* POP3wrapper::fetchDecodedPart(const RecMail&,const RecPart&)
+encodedString* POP3wrapper::fetchDecodedPart(const RecMail&,const RecPart&part)
{
- return new encodedString();
+ QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier());
+ if (it==bodyCache.end()) return new encodedString();
+ encodedString*t = decode_String(it.data(),part.Encoding());
+ return t;
}
-encodedString* POP3wrapper::fetchRawPart(const RecMail&,const RecPart&)
+encodedString* POP3wrapper::fetchRawPart(const RecMail&mail,const RecPart&part)
{
- return new encodedString();
+ QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier());
+ if (it==bodyCache.end()) return new encodedString();
+ encodedString*t = it.data();
+ return t;
}
void POP3wrapper::traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rec)
{
if (current_rec >= 10) {
qDebug("too deep recursion!");
}
if (!message || !mime) {
return;
}
int r;
char*data = 0;
size_t len;
clistiter * cur = 0;
int res;
QString b;
RecPart part;
switch (mime->mm_type) {
case MAILMIME_SINGLE:
r = mailmessage_fetch_section(message,mime,&data,&len);
part.setSize(len);
fillSingleBody(part,message,mime);
if (part.Type()=="text" && target.Bodytext().isNull()) {
encodedString*r = new encodedString();
r->setContent(data,len);
encodedString*res = decode_String(r,part.Encoding());
b = QString(res->Content());
delete r;
delete res;
target.setBodytext(b);
target.setDescription(part);
} else {
- /* TODO: Add the content to a list and store it for later use */
- if (data) free(data);
+ b = gen_attachment_id();
+ part.setIdentifier(b);
+ bodyCache[b]=new encodedString(data,len);
target.addPart(part);
}
break;
case MAILMIME_MULTIPLE:
for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) {
traverseBody(target,message, (mailmime*)clist_content(cur),current_rec+1);
}
break;
case MAILMIME_MESSAGE:
if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,current_rec+1);
}
break;
}
}
QString POP3wrapper::getencoding(mailmime_mechanism*aEnc)
{
QString enc="7bit";
if (!aEnc) return enc;
switch(aEnc->enc_type) {
case MAILMIME_MECHANISM_7BIT:
enc = "7bit";
break;
case MAILMIME_MECHANISM_8BIT:
enc = "8bit";
break;
case MAILMIME_MECHANISM_BINARY:
enc = "binary";
break;
case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
enc = "quoted-printable";
break;
case MAILMIME_MECHANISM_BASE64:
enc = "base64";
break;
case MAILMIME_MECHANISM_TOKEN:
default:
if (aEnc->enc_token) {
enc = QString(aEnc->enc_token);
}
break;
}
return enc;
}
void POP3wrapper::fillSingleBody(RecPart&target,mailmessage*,mailmime*mime)
{
if (!mime) {
return;
}
mailmime_field*field = 0;
mailmime_single_fields fields;
memset(&fields, 0, sizeof(struct mailmime_single_fields));
if (mime->mm_mime_fields != NULL) {
mailmime_single_fields_init(&fields, mime->mm_mime_fields,
mime->mm_content_type);
}
mailmime_content*type = fields.fld_content;
clistcell*current;
if (!type) {
target.setType("text");
target.setSubtype("plain");
} else {
target.setSubtype(type->ct_subtype);
switch(type->ct_type->tp_data.tp_discrete_type->dt_type) {
case MAILMIME_DISCRETE_TYPE_TEXT:
target.setType("text");
break;
case MAILMIME_DISCRETE_TYPE_IMAGE:
target.setType("image");
break;
case MAILMIME_DISCRETE_TYPE_AUDIO:
target.setType("audio");
break;
case MAILMIME_DISCRETE_TYPE_VIDEO:
target.setType("video");
break;
case MAILMIME_DISCRETE_TYPE_APPLICATION:
target.setType("application");
break;
case MAILMIME_DISCRETE_TYPE_EXTENSION:
default:
if (type->ct_type->tp_data.tp_discrete_type->dt_extension) {
target.setType(type->ct_type->tp_data.tp_discrete_type->dt_extension);
}
break;
}
if (type->ct_parameters) {
fillParameters(target,type->ct_parameters);
}
}
if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) {
for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) {
field = (mailmime_field*)current->data;
diff --git a/noncore/net/mail/libmailwrapper/pop3wrapper.h b/noncore/net/mail/libmailwrapper/pop3wrapper.h
index b17928e..a31a145 100644
--- a/noncore/net/mail/libmailwrapper/pop3wrapper.h
+++ b/noncore/net/mail/libmailwrapper/pop3wrapper.h
@@ -1,58 +1,63 @@
#ifndef __POP3WRAPPER
#define __POP3WRAPPER
#include "mailwrapper.h"
#include "abstractmail.h"
+#include <qmap.h>
+#include <qstring.h>
class RecMail;
class RecBody;
class encodedString;
struct mailpop3;
struct mailmessage;
struct mailmime;
struct mailmime_mechanism;
class POP3wrapper : public AbstractMail
{
Q_OBJECT
public:
POP3wrapper( POP3account *a );
virtual ~POP3wrapper();
/* mailbox will be ignored */
virtual void listMessages(const QString & mailbox, QList<RecMail> &target );
virtual QList<Folder>* listFolders();
virtual QString fetchTextPart(const RecMail&mail,const RecPart&part);
virtual encodedString* fetchDecodedPart(const RecMail&mail,const RecPart&part);
virtual encodedString* fetchRawPart(const RecMail&mail,const RecPart&part);
virtual void deleteMail(const RecMail&mail);
virtual void answeredMail(const RecMail&mail);
RecBody fetchBody( const RecMail &mail );
static void pop3_progress( size_t current, size_t maximum );
protected:
void login();
void logout();
RecMail *parseHeader( const char *header );
RecBody parseMail( char *message );
QString parseMailboxList( mailimf_mailbox_list *list );
QString parseMailbox( mailimf_mailbox *box );
QString parseGroup( mailimf_group *group );
QString parseAddressList( mailimf_address_list *list );
QString parseDateTime( mailimf_date_time *date );
- static void traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rek=0);
+ void cleanUpCache();
+
+ void traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rek=0);
static void fillSingleBody(RecPart&target,mailmessage*message,mailmime*mime);
static void fillParameters(RecPart&target,clist*parameters);
static QString POP3wrapper::getencoding(mailmime_mechanism*aEnc);
POP3account *account;
mailpop3 *m_pop3;
QString msgTempName;
unsigned int last_msg_id;
+ QMap<QString,encodedString*> bodyCache;
};
#endif
diff --git a/noncore/net/mail/pop3wrapper.cpp b/noncore/net/mail/pop3wrapper.cpp
index 65cd4ba..d3447f4 100644
--- a/noncore/net/mail/pop3wrapper.cpp
+++ b/noncore/net/mail/pop3wrapper.cpp
@@ -1,149 +1,163 @@
#include <stdlib.h>
#include "pop3wrapper.h"
#include "mailtypes.h"
#include "logindialog.h"
#include <libetpan/mailpop3.h>
#include <libetpan/mailmime.h>
#include <libetpan/data_message_driver.h>
#include <qfile.h>
/* we don't fetch messages larger than 5 MB */
#define HARD_MSG_SIZE_LIMIT 5242880
POP3wrapper::POP3wrapper( POP3account *a )
{
account = a;
m_pop3 = NULL;
msgTempName = a->getFileName()+"_msg_cache";
last_msg_id = 0;
+ bodyCache.clear();
}
POP3wrapper::~POP3wrapper()
{
logout();
QFile msg_cache(msgTempName);
if (msg_cache.exists()) {
msg_cache.remove();
}
+ cleanUpCache();
+}
+
+void POP3wrapper::cleanUpCache()
+{
+ QMap<QString,encodedString*>::Iterator it = bodyCache.begin();
+ for (;it!=bodyCache.end();++it) {
+ encodedString*t = it.data();
+ //it.setValue(0);
+ if (t) delete t;
+ }
+ bodyCache.clear();
}
void POP3wrapper::pop3_progress( size_t current, size_t maximum )
{
//qDebug( "POP3: %i of %i", current, maximum );
}
RecBody POP3wrapper::fetchBody( const RecMail &mail )
{
int err = MAILPOP3_NO_ERROR;
char *message;
size_t length = 0;
login();
if ( !m_pop3 ) {
return RecBody();
}
RecBody body;
QFile msg_cache(msgTempName);
if (mail.Msgsize()>HARD_MSG_SIZE_LIMIT) {
qDebug("Message to large: %i",mail.Msgsize());
return body;
}
+ cleanUpCache();
if (mail.getNumber()!=last_msg_id) {
if (msg_cache.exists()) {
msg_cache.remove();
}
msg_cache.open(IO_ReadWrite|IO_Truncate);
last_msg_id = mail.getNumber();
err = mailpop3_retr( m_pop3, mail.getNumber(), &message, &length );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "POP3: error retrieving body with index %i", mail.getNumber() );
last_msg_id = 0;
return RecBody();
}
msg_cache.writeBlock(message,length);
} else {
QString msg="";
msg_cache.open(IO_ReadOnly);
message = new char[4096];
memset(message,0,4096);
while (msg_cache.readBlock(message,4095)>0) {
msg+=message;
memset(message,0,4096);
}
delete message;
message = (char*)malloc(msg.length()+1*sizeof(char));
memset(message,0,msg.length()+1);
memcpy(message,msg.latin1(),msg.length());
}
body = parseMail(message);
free(message);
return body;
}
RecBody POP3wrapper::parseMail( char *message )
{
int err = MAILIMF_NO_ERROR;
/* these vars are used recurcive! set it to 0!!!!!!!!!!!!!!!!! */
size_t curTok = 0;
mailimf_message *result = 0;
mailmessage * msg=0;
mailmime_single_fields fields;
/* is bound to msg and will be freed there */
struct mailmime * mime=0;
RecBody body;
err = mailimf_message_parse( (char *) message, strlen( message ), &curTok, &result );
if ( err != MAILIMF_NO_ERROR ) {
if (result) mailimf_message_free(result);
return body;
}
char*body_msg = message;
msg = mailmessage_new();
mailmessage_init(msg, NULL, data_message_driver, 0, strlen(body_msg));
generic_message_t * msg_data;
msg_data = (generic_message_t *)msg->msg_data;
msg_data->msg_fetched = 1;
msg_data->msg_message = body_msg;
msg_data->msg_length = strlen(body_msg);
memset(&fields, 0, sizeof(struct mailmime_single_fields));
err = mailmessage_get_bodystructure(msg,&mime);
traverseBody(body,msg,mime);
mailmessage_free(msg);
return body;
}
void POP3wrapper::listMessages(const QString &, QList<RecMail> &target )
{
int err = MAILPOP3_NO_ERROR;
char * header = 0;
/* these vars are used recurcive! set it to 0!!!!!!!!!!!!!!!!! */
size_t length = 0;
carray * messages = 0;
login();
if (!m_pop3) return;
mailpop3_list( m_pop3, &messages );
for (unsigned int i = 0; i < carray_count(messages);++i) {
mailpop3_msg_info *info;
err = mailpop3_get_msg_info(m_pop3,i+1,&info);
if (info->msg_deleted)
continue;
err = mailpop3_header( m_pop3, info->msg_index, &header, &length );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "POP3: error retrieving header msgid: %i", info->msg_index );
free(header);
return;
}
RecMail *mail = parseHeader( header );
@@ -312,254 +326,264 @@ QString POP3wrapper::parseMailboxList( mailimf_mailbox_list *list )
for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) {
mailimf_mailbox *box = (mailimf_mailbox *) current->data;
if ( !first ) {
result.append( "," );
} else {
first = false;
}
result.append( parseMailbox( box ) );
}
return result;
}
void POP3wrapper::login()
{
/* we'll hold the line */
if ( m_pop3 != NULL ) return;
const char *server, *user, *pass;
uint16_t port;
int err = MAILPOP3_NO_ERROR;
server = account->getServer().latin1();
port = account->getPort().toUInt();
if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) {
LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true );
login.show();
if ( QDialog::Accepted == login.exec() ) {
// ok
user = strdup( login.getUser().latin1() );
pass = strdup( login.getPassword().latin1() );
} else {
// cancel
qDebug( "POP3: Login canceled" );
return;
}
} else {
user = account->getUser().latin1();
pass = account->getPassword().latin1();
}
m_pop3 = mailpop3_new( 200, &pop3_progress );
// connect
if (account->getSSL()) {
err = mailpop3_ssl_connect( m_pop3, (char*)server, port );
} else {
err = mailpop3_socket_connect( m_pop3, (char*)server, port );
}
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "pop3: error connecting to %s\n reason: %s", server,
m_pop3->pop3_response );
mailpop3_free( m_pop3 );
m_pop3 = NULL;
return;
}
qDebug( "POP3: connected!" );
// login
// TODO: decide if apop or plain login should be used
err = mailpop3_login( m_pop3, (char *) user, (char *) pass );
if ( err != MAILPOP3_NO_ERROR ) {
qDebug( "pop3: error logging in: %s", m_pop3->pop3_response );
logout();
return;
}
qDebug( "POP3: logged in!" );
}
void POP3wrapper::logout()
{
int err = MAILPOP3_NO_ERROR;
if ( m_pop3 == NULL ) return;
err = mailpop3_quit( m_pop3 );
mailpop3_free( m_pop3 );
m_pop3 = NULL;
}
QList<Folder>* POP3wrapper::listFolders()
{
/* TODO: integrate MH directories
but not before version 0.1 ;)
*/
QList<Folder> * folders = new QList<Folder>();
folders->setAutoDelete( false );
Folder*inb=new Folder("INBOX","/");
folders->append(inb);
return folders;
}
-QString POP3wrapper::fetchTextPart(const RecMail&,const RecPart&)
+QString POP3wrapper::fetchTextPart(const RecMail&mail,const RecPart&part)
{
- return "";
+ encodedString*t = fetchDecodedPart(mail,part);
+ QString text=t->Content();
+ delete t;
+ return text;
}
void POP3wrapper::deleteMail(const RecMail&mail)
{
login();
if (!m_pop3) return;
int err = mailpop3_dele(m_pop3,mail.getNumber());
if (err != MAILPOP3_NO_ERROR) {
qDebug("error deleting mail");
}
}
void POP3wrapper::answeredMail(const RecMail&)
{
}
-encodedString* POP3wrapper::fetchDecodedPart(const RecMail&,const RecPart&)
+encodedString* POP3wrapper::fetchDecodedPart(const RecMail&,const RecPart&part)
{
- return new encodedString();
+ QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier());
+ if (it==bodyCache.end()) return new encodedString();
+ encodedString*t = decode_String(it.data(),part.Encoding());
+ return t;
}
-encodedString* POP3wrapper::fetchRawPart(const RecMail&,const RecPart&)
+encodedString* POP3wrapper::fetchRawPart(const RecMail&mail,const RecPart&part)
{
- return new encodedString();
+ QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier());
+ if (it==bodyCache.end()) return new encodedString();
+ encodedString*t = it.data();
+ return t;
}
void POP3wrapper::traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rec)
{
if (current_rec >= 10) {
qDebug("too deep recursion!");
}
if (!message || !mime) {
return;
}
int r;
char*data = 0;
size_t len;
clistiter * cur = 0;
int res;
QString b;
RecPart part;
switch (mime->mm_type) {
case MAILMIME_SINGLE:
r = mailmessage_fetch_section(message,mime,&data,&len);
part.setSize(len);
fillSingleBody(part,message,mime);
if (part.Type()=="text" && target.Bodytext().isNull()) {
encodedString*r = new encodedString();
r->setContent(data,len);
encodedString*res = decode_String(r,part.Encoding());
b = QString(res->Content());
delete r;
delete res;
target.setBodytext(b);
target.setDescription(part);
} else {
- /* TODO: Add the content to a list and store it for later use */
- if (data) free(data);
+ b = gen_attachment_id();
+ part.setIdentifier(b);
+ bodyCache[b]=new encodedString(data,len);
target.addPart(part);
}
break;
case MAILMIME_MULTIPLE:
for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) {
traverseBody(target,message, (mailmime*)clist_content(cur),current_rec+1);
}
break;
case MAILMIME_MESSAGE:
if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,current_rec+1);
}
break;
}
}
QString POP3wrapper::getencoding(mailmime_mechanism*aEnc)
{
QString enc="7bit";
if (!aEnc) return enc;
switch(aEnc->enc_type) {
case MAILMIME_MECHANISM_7BIT:
enc = "7bit";
break;
case MAILMIME_MECHANISM_8BIT:
enc = "8bit";
break;
case MAILMIME_MECHANISM_BINARY:
enc = "binary";
break;
case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
enc = "quoted-printable";
break;
case MAILMIME_MECHANISM_BASE64:
enc = "base64";
break;
case MAILMIME_MECHANISM_TOKEN:
default:
if (aEnc->enc_token) {
enc = QString(aEnc->enc_token);
}
break;
}
return enc;
}
void POP3wrapper::fillSingleBody(RecPart&target,mailmessage*,mailmime*mime)
{
if (!mime) {
return;
}
mailmime_field*field = 0;
mailmime_single_fields fields;
memset(&fields, 0, sizeof(struct mailmime_single_fields));
if (mime->mm_mime_fields != NULL) {
mailmime_single_fields_init(&fields, mime->mm_mime_fields,
mime->mm_content_type);
}
mailmime_content*type = fields.fld_content;
clistcell*current;
if (!type) {
target.setType("text");
target.setSubtype("plain");
} else {
target.setSubtype(type->ct_subtype);
switch(type->ct_type->tp_data.tp_discrete_type->dt_type) {
case MAILMIME_DISCRETE_TYPE_TEXT:
target.setType("text");
break;
case MAILMIME_DISCRETE_TYPE_IMAGE:
target.setType("image");
break;
case MAILMIME_DISCRETE_TYPE_AUDIO:
target.setType("audio");
break;
case MAILMIME_DISCRETE_TYPE_VIDEO:
target.setType("video");
break;
case MAILMIME_DISCRETE_TYPE_APPLICATION:
target.setType("application");
break;
case MAILMIME_DISCRETE_TYPE_EXTENSION:
default:
if (type->ct_type->tp_data.tp_discrete_type->dt_extension) {
target.setType(type->ct_type->tp_data.tp_discrete_type->dt_extension);
}
break;
}
if (type->ct_parameters) {
fillParameters(target,type->ct_parameters);
}
}
if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) {
for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) {
field = (mailmime_field*)current->data;
diff --git a/noncore/net/mail/pop3wrapper.h b/noncore/net/mail/pop3wrapper.h
index b17928e..a31a145 100644
--- a/noncore/net/mail/pop3wrapper.h
+++ b/noncore/net/mail/pop3wrapper.h
@@ -1,58 +1,63 @@
#ifndef __POP3WRAPPER
#define __POP3WRAPPER
#include "mailwrapper.h"
#include "abstractmail.h"
+#include <qmap.h>
+#include <qstring.h>
class RecMail;
class RecBody;
class encodedString;
struct mailpop3;
struct mailmessage;
struct mailmime;
struct mailmime_mechanism;
class POP3wrapper : public AbstractMail
{
Q_OBJECT
public:
POP3wrapper( POP3account *a );
virtual ~POP3wrapper();
/* mailbox will be ignored */
virtual void listMessages(const QString & mailbox, QList<RecMail> &target );
virtual QList<Folder>* listFolders();
virtual QString fetchTextPart(const RecMail&mail,const RecPart&part);
virtual encodedString* fetchDecodedPart(const RecMail&mail,const RecPart&part);
virtual encodedString* fetchRawPart(const RecMail&mail,const RecPart&part);
virtual void deleteMail(const RecMail&mail);
virtual void answeredMail(const RecMail&mail);
RecBody fetchBody( const RecMail &mail );
static void pop3_progress( size_t current, size_t maximum );
protected:
void login();
void logout();
RecMail *parseHeader( const char *header );
RecBody parseMail( char *message );
QString parseMailboxList( mailimf_mailbox_list *list );
QString parseMailbox( mailimf_mailbox *box );
QString parseGroup( mailimf_group *group );
QString parseAddressList( mailimf_address_list *list );
QString parseDateTime( mailimf_date_time *date );
- static void traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rek=0);
+ void cleanUpCache();
+
+ void traverseBody(RecBody&target,mailmessage*message,mailmime*mime,unsigned int current_rek=0);
static void fillSingleBody(RecPart&target,mailmessage*message,mailmime*mime);
static void fillParameters(RecPart&target,clist*parameters);
static QString POP3wrapper::getencoding(mailmime_mechanism*aEnc);
POP3account *account;
mailpop3 *m_pop3;
QString msgTempName;
unsigned int last_msg_id;
+ QMap<QString,encodedString*> bodyCache;
};
#endif