summaryrefslogtreecommitdiff
authorjgf <jgf>2003-12-18 02:43:07 (UTC)
committer jgf <jgf>2003-12-18 02:43:07 (UTC)
commitd7fed5a555f51008db8b96e8b978c3830c59be77 (patch) (side-by-side diff)
tree9f3a8aa82909ef80cf1c42431abc20d3ac585436
parent77e353da0c33bbfabf1b919e25008d62581bf164 (diff)
downloadopie-d7fed5a555f51008db8b96e8b978c3830c59be77.zip
opie-d7fed5a555f51008db8b96e8b978c3830c59be77.tar.gz
opie-d7fed5a555f51008db8b96e8b978c3830c59be77.tar.bz2
decoding of imap folder names
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/mail/defines.h11
-rw-r--r--noncore/net/mail/libmailwrapper/mailwrapper.cpp107
-rw-r--r--noncore/net/mail/libmailwrapper/mailwrapper.h2
-rw-r--r--noncore/net/mail/mailwrapper.cpp107
-rw-r--r--noncore/net/mail/mailwrapper.h2
5 files changed, 201 insertions, 28 deletions
diff --git a/noncore/net/mail/defines.h b/noncore/net/mail/defines.h
index 9036658..d9cdab0 100644
--- a/noncore/net/mail/defines.h
+++ b/noncore/net/mail/defines.h
@@ -1,40 +1,51 @@
#ifndef DEFINE_CONSTANTS_H
#define DEFINE_CONSTANTS_H
#include <qpe/resource.h>
#define USER_AGENT "OpieMail v0.1"
#define PIC_COMPOSEMAIL "mail/composemail"
#define PIC_SENDQUEUED "mail/sendqueued"
#define PIC_SHOWFOLDERS "mail/showfolders"
#define PIC_SEARCHMAILS "mail/searchmails"
#define PIC_EDITSETTINGS "mail/editsettings"
#define PIC_EDITACCOUNTS "mail/editaccounts"
#define PIC_SYNC "mail/sync"
#define PIC_IMAPFOLDER "mail/imapfolder"
#define PIC_POP3FOLDER "mail/pop3folder"
#define PIC_INBOXFOLDER "mail/inbox"
#define ICON_COMPOSEMAIL QIconSet( Resource::loadPixmap( PIC_COMPOSEMAIL ) )
#define ICON_SENDQUEUED QIconSet( Resource::loadPixmap( PIC_SENDQUEUED ) )
#define ICON_SHOWFOLDERS QIconSet( Resource::loadPixmap( PIC_SHOWFOLDERS ) )
#define ICON_SEARCHMAILS QIconSet( Resource::loadPixmap( PIC_SEARCHMAILS ) )
#define ICON_EDITSETTINGS QIconSet( Resource::loadPixmap( PIC_EDITSETTINGS ) )
#define ICON_EDITACCOUNTS QIconSet( Resource::loadPixmap( PIC_EDITACCOUNTS ) )
#define ICON_SYNC QIconSet( Resource::loadPixmap( PIC_SYNC ) )
#define PIXMAP_IMAPFOLDER QPixmap( Resource::loadPixmap( PIC_IMAPFOLDER ) )
#define PIXMAP_POP3FOLDER QPixmap( Resource::loadPixmap( PIC_POP3FOLDER ) )
#define PIXMAP_INBOXFOLDER QPixmap( Resource::loadPixmap( PIC_INBOXFOLDER) )
#define IMAP_PORT "143"
#define IMAP_SSL_PORT "993"
#define SMTP_PORT "25"
#define SMTP_SSL_PORT "465"
#define POP3_PORT "110"
#define POP3_SSL_PORT "995"
#define NNTP_PORT "119"
#define NNTP_SSL_PORT "563"
+/* used for decoding imapfoldername */
+#define UNDEFINED 64
+#define MAXLINE 76
+#define UTF16MASK 0x03FFUL
+#define UTF16SHIFT 10
+#define UTF16BASE 0x10000UL
+#define UTF16HIGHSTART 0xD800UL
+#define UTF16HIGHEND 0xDBFFUL
+#define UTF16LOSTART 0xDC00UL
+#define UTF16LOEND 0xDFFFUL
+
#endif
diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp
index 858283f..75c06f9 100644
--- a/noncore/net/mail/libmailwrapper/mailwrapper.cpp
+++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp
@@ -1,439 +1,518 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <qdir.h>
#include "mailwrapper.h"
#include "logindialog.h"
//#include "mail.h"
#include "defines.h"
Attachment::Attachment( DocLnk lnk )
{
doc = lnk;
size = QFileInfo( doc.file() ).size();
}
Folder::Folder(const QString&tmp_name, const QString&sep )
{
name = tmp_name;
nameDisplay = name;
-
- for ( int pos = nameDisplay.find( '&' ); pos != -1;
- pos = nameDisplay.find( '&' ) ) {
- int end = nameDisplay.find( '-' );
- if ( end == -1 || end <= pos ) break;
- QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 );
- // TODO: do real base64 decoding here !
- if ( str64.compare( "APw" ) == 0 ) {
- nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" );
- } else if ( str64.compare( "APY" ) == 0 ) {
- nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" );
- }
- }
- qDebug( "folder " + name + " - displayed as " + nameDisplay );
separator = sep;
}
const QString& Folder::Separator()const
{
return separator;
}
IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix )
: Folder( name,sep ),m_MaySelect(select)
{
+ // Decode IMAP foldername
+ nameDisplay = IMAPFolder::decodeFolderName( name );
+ qDebug( "folder " + name + " - displayed as " + nameDisplay );
+
if (prefix.length()>0) {
if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) {
nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length());
}
}
}
+static unsigned char base64chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+
+/**
+ * Decodes base64 encoded parts of the imapfolder name
+ * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc
+ */
+QString IMAPFolder::decodeFolderName( const QString &name )
+{
+ unsigned char c, i, bitcount;
+ unsigned long ucs4, utf16, bitbuf;
+ unsigned char base64[256], utf8[6];
+ unsigned long srcPtr = 0;
+ QCString dst;
+ QCString src = name.ascii();
+
+ /* initialize modified base64 decoding table */
+ memset(base64, UNDEFINED, sizeof(base64));
+ for (i = 0; i < sizeof(base64chars); ++i) {
+ base64[(int)base64chars[i]] = i;
+ }
+
+ /* loop until end of string */
+ while (srcPtr < src.length ()) {
+ c = src[srcPtr++];
+ /* deal with literal characters and &- */
+ if (c != '&' || src[srcPtr] == '-') {
+ /* encode literally */
+ dst += c;
+ /* skip over the '-' if this is an &- sequence */
+ if (c == '&')
+ srcPtr++;
+ } else {
+ /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
+ bitbuf = 0;
+ bitcount = 0;
+ ucs4 = 0;
+ while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) {
+ ++srcPtr;
+ bitbuf = (bitbuf << 6) | c;
+ bitcount += 6;
+ /* enough bits for a UTF-16 character? */
+ if (bitcount >= 16) {
+ bitcount -= 16;
+ utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff;
+ /* convert UTF16 to UCS4 */
+ if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
+ ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
+ continue;
+ } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
+ ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
+ } else {
+ ucs4 = utf16;
+ }
+ /* convert UTF-16 range of UCS4 to UTF-8 */
+ if (ucs4 <= 0x7fUL) {
+ utf8[0] = ucs4;
+ i = 1;
+ } else if (ucs4 <= 0x7ffUL) {
+ utf8[0] = 0xc0 | (ucs4 >> 6);
+ utf8[1] = 0x80 | (ucs4 & 0x3f);
+ i = 2;
+ } else if (ucs4 <= 0xffffUL) {
+ utf8[0] = 0xe0 | (ucs4 >> 12);
+ utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ utf8[2] = 0x80 | (ucs4 & 0x3f);
+ i = 3;
+ } else {
+ utf8[0] = 0xf0 | (ucs4 >> 18);
+ utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
+ utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ utf8[3] = 0x80 | (ucs4 & 0x3f);
+ i = 4;
+ }
+ /* copy it */
+ for (c = 0; c < i; ++c) {
+ dst += utf8[c];
+ }
+ }
+ }
+ /* skip over trailing '-' in modified UTF-7 encoding */
+ if (src[srcPtr] == '-')
+ ++srcPtr;
+ }
+ }
+
+ return QString::fromUtf8( dst.data() );
+}
+
MailWrapper::MailWrapper( Settings *s )
: QObject()
{
settings = s;
}
QString MailWrapper::mailsmtpError( int errnum )
{
switch ( errnum ) {
case MAILSMTP_NO_ERROR:
return tr( "No error" );
case MAILSMTP_ERROR_UNEXPECTED_CODE:
return tr( "Unexpected error code" );
case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
return tr( "Service not available" );
case MAILSMTP_ERROR_STREAM:
return tr( "Stream error" );
case MAILSMTP_ERROR_HOSTNAME:
return tr( "gethostname() failed" );
case MAILSMTP_ERROR_NOT_IMPLEMENTED:
return tr( "Not implemented" );
case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
return tr( "Error, action not taken" );
case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
return tr( "Data exceeds storage allocation" );
case MAILSMTP_ERROR_IN_PROCESSING:
return tr( "Error in processing" );
// case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE:
// return tr( "Insufficient system storage" );
case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
return tr( "Mailbox unavailable" );
case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
return tr( "Mailbox name not allowed" );
case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
return tr( "Bad command sequence" );
case MAILSMTP_ERROR_USER_NOT_LOCAL:
return tr( "User not local" );
case MAILSMTP_ERROR_TRANSACTION_FAILED:
return tr( "Transaction failed" );
case MAILSMTP_ERROR_MEMORY:
return tr( "Memory error" );
case MAILSMTP_ERROR_CONNECTION_REFUSED:
return tr( "Connection refused" );
default:
return tr( "Unknown error code" );
}
}
mailimf_mailbox *MailWrapper::newMailbox(const QString&name, const QString&mail )
{
return mailimf_mailbox_new( strdup( name.latin1() ),
strdup( mail.latin1() ) );
}
mailimf_address_list *MailWrapper::parseAddresses(const QString&addr )
{
mailimf_address_list *addresses;
if ( addr.isEmpty() ) return NULL;
addresses = mailimf_address_list_new_empty();
QStringList list = QStringList::split( ',', addr );
QStringList::Iterator it;
for ( it = list.begin(); it != list.end(); it++ ) {
char *str = strdup( (*it).latin1() );
int err = mailimf_address_list_add_parse( addresses, str );
if ( err != MAILIMF_NO_ERROR ) {
qDebug( "Error parsing" );
qDebug( *it );
free( str );
} else {
qDebug( "Parse success! :)" );
}
}
return addresses;
}
mailimf_fields *MailWrapper::createImfFields( Mail *mail )
{
mailimf_fields *fields;
mailimf_field *xmailer;
mailimf_mailbox *sender, *fromBox;
mailimf_mailbox_list *from;
mailimf_address_list *to, *cc, *bcc, *reply;
char *subject = strdup( mail->getSubject().latin1() );
int err;
sender = newMailbox( mail->getName(), mail->getMail() );
if ( sender == NULL ) goto err_free;
fromBox = newMailbox( mail->getName(), mail->getMail() );
if ( fromBox == NULL ) goto err_free_sender;
from = mailimf_mailbox_list_new_empty();
if ( from == NULL ) goto err_free_fromBox;
err = mailimf_mailbox_list_add( from, fromBox );
if ( err != MAILIMF_NO_ERROR ) goto err_free_from;
to = parseAddresses( mail->getTo() );
if ( to == NULL ) goto err_free_from;
cc = parseAddresses( mail->getCC() );
bcc = parseAddresses( mail->getBCC() );
reply = parseAddresses( mail->getReply() );
fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc,
NULL, NULL, subject );
if ( fields == NULL ) goto err_free_reply;
xmailer = mailimf_field_new_custom( strdup( "User-Agent" ),
strdup( USER_AGENT ) );
if ( xmailer == NULL ) goto err_free_fields;
err = mailimf_fields_add( fields, xmailer );
if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer;
return fields; // Success :)
err_free_xmailer:
mailimf_field_free( xmailer );
err_free_fields:
mailimf_fields_free( fields );
err_free_reply:
mailimf_address_list_free( reply );
mailimf_address_list_free( bcc );
mailimf_address_list_free( cc );
mailimf_address_list_free( to );
err_free_from:
mailimf_mailbox_list_free( from );
err_free_fromBox:
mailimf_mailbox_free( fromBox );
err_free_sender:
mailimf_mailbox_free( sender );
err_free:
free( subject );
qDebug( "createImfFields - error" );
return NULL; // Error :(
}
mailmime *MailWrapper::buildTxtPart( QString str )
{
mailmime *txtPart;
mailmime_fields *fields;
mailmime_content *content;
mailmime_parameter *param;
char *txt = strdup( str.latin1() );
int err;
param = mailmime_parameter_new( strdup( "charset" ),
strdup( "iso-8859-1" ) );
if ( param == NULL ) goto err_free;
content = mailmime_content_new_with_str( "text/plain" );
if ( content == NULL ) goto err_free_param;
err = clist_append( content->ct_parameters, param );
if ( err != MAILIMF_NO_ERROR ) goto err_free_content;
fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT );
if ( fields == NULL ) goto err_free_content;
txtPart = mailmime_new_empty( content, fields );
if ( txtPart == NULL ) goto err_free_fields;
err = mailmime_set_body_text( txtPart, txt, strlen( txt ) );
if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
return txtPart; // Success :)
err_free_txtPart:
mailmime_free( txtPart );
err_free_fields:
mailmime_fields_free( fields );
err_free_content:
mailmime_content_free( content );
err_free_param:
mailmime_parameter_free( param );
err_free:
free( txt );
qDebug( "buildTxtPart - error" );
return NULL; // Error :(
}
mailmime *MailWrapper::buildFilePart( QString filename, QString mimetype )
{
mailmime * filePart;
mailmime_fields * fields;
mailmime_content * content;
mailmime_parameter * param = NULL;
int err;
int pos = filename.findRev( '/' );
QString tmp = filename.right( filename.length() - ( pos + 1 ) );
char *name = strdup( tmp.latin1() ); // just filename
char *file = strdup( filename.latin1() ); // full name with path
char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain
fields = mailmime_fields_new_filename(
MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name,
MAILMIME_MECHANISM_BASE64 );
if ( fields == NULL ) goto err_free;
content = mailmime_content_new_with_str( mime );
if ( content == NULL ) goto err_free_fields;
if ( mimetype.compare( "text/plain" ) == 0 ) {
param = mailmime_parameter_new( strdup( "charset" ),
strdup( "iso-8859-1" ) );
if ( param == NULL ) goto err_free_content;
err = clist_append( content->ct_parameters, param );
if ( err != MAILIMF_NO_ERROR ) goto err_free_param;
}
filePart = mailmime_new_empty( content, fields );
if ( filePart == NULL ) goto err_free_param;
err = mailmime_set_body_file( filePart, file );
if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
return filePart; // Success :)
err_free_filePart:
mailmime_free( filePart );
err_free_param:
if ( param != NULL ) mailmime_parameter_free( param );
err_free_content:
mailmime_content_free( content );
err_free_fields:
mailmime_fields_free( fields );
err_free:
free( name );
free( mime );
free( file );
qDebug( "buildFilePart - error" );
return NULL; // Error :(
}
void MailWrapper::addFileParts( mailmime *message, QList<Attachment> files )
{
Attachment *it;
for ( it = files.first(); it; it = files.next() ) {
qDebug( "Adding file" );
mailmime *filePart;
int err;
filePart = buildFilePart( it->getFileName(), it->getMimeType() );
if ( filePart == NULL ) goto err_free;
err = mailmime_smart_add_part( message, filePart );
if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
continue; // Success :)
err_free_filePart:
mailmime_free( filePart );
err_free:
qDebug( "addFileParts: error adding file:" );
qDebug( it->getFileName() );
}
}
mailmime *MailWrapper::createMimeMail( Mail *mail )
{
mailmime *message, *txtPart;
mailimf_fields *fields;
int err;
fields = createImfFields( mail );
if ( fields == NULL ) goto err_free;
message = mailmime_new_message_data( NULL );
if ( message == NULL ) goto err_free_fields;
mailmime_set_imf_fields( message, fields );
txtPart = buildTxtPart( mail->getMessage() );
if ( txtPart == NULL ) goto err_free_message;
err = mailmime_smart_add_part( message, txtPart );
if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
addFileParts( message, mail->getAttachments() );
return message; // Success :)
err_free_txtPart:
mailmime_free( txtPart );
err_free_message:
mailmime_free( message );
err_free_fields:
mailimf_fields_free( fields );
err_free:
qDebug( "createMimeMail: error" );
return NULL; // Error :(
}
mailimf_field *MailWrapper::getField( mailimf_fields *fields, int type )
{
mailimf_field *field;
clistiter *it;
it = clist_begin( fields->fld_list );
while ( it ) {
field = (mailimf_field *) it->data;
if ( field->fld_type == type ) {
return field;
}
it = it->next;
}
return NULL;
}
static void addRcpts( clist *list, mailimf_address_list *addr_list )
{
clistiter *it, *it2;
for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) {
mailimf_address *addr;
addr = (mailimf_address *) it->data;
if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) {
esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL );
} else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) {
clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list;
for ( it2 = clist_begin( l ); it2; it2 = it2->next ) {
mailimf_mailbox *mbox;
mbox = (mailimf_mailbox *) it2->data;
esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL );
}
}
}
}
clist *MailWrapper::createRcptList( mailimf_fields *fields )
{
clist *rcptList;
mailimf_field *field;
rcptList = esmtp_address_list_new();
field = getField( fields, MAILIMF_FIELD_TO );
if ( field && (field->fld_type == MAILIMF_FIELD_TO)
&& field->fld_data.fld_to->to_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_to->to_addr_list );
}
field = getField( fields, MAILIMF_FIELD_CC );
if ( field && (field->fld_type == MAILIMF_FIELD_CC)
&& field->fld_data.fld_cc->cc_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list );
}
field = getField( fields, MAILIMF_FIELD_BCC );
if ( field && (field->fld_type == MAILIMF_FIELD_BCC)
&& field->fld_data.fld_bcc->bcc_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list );
}
return rcptList;
}
char *MailWrapper::getFrom( mailmime *mail )
{
char *from = NULL;
mailimf_field *ffrom;
ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM );
if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM)
&& ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) {
clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list;
clistiter *it;
for ( it = clist_begin( cl ); it; it = it->next ) {
mailimf_mailbox *mb = (mailimf_mailbox *) it->data;
from = strdup( mb->mb_addr_spec );
}
diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.h b/noncore/net/mail/libmailwrapper/mailwrapper.h
index d78f8e9..02fe4b7 100644
--- a/noncore/net/mail/libmailwrapper/mailwrapper.h
+++ b/noncore/net/mail/libmailwrapper/mailwrapper.h
@@ -1,124 +1,126 @@
#ifndef MAILWRAPPER_H
#define MAILWRAPPER_H
#include <qpe/applnk.h>
#include <libetpan/mailmime.h>
#include <libetpan/mailimf.h>
#include <libetpan/mailsmtp.h>
#include <libetpan/mailstorage.h>
#include <libetpan/maildriver.h>
#include <qbitarray.h>
#include <qdatetime.h>
#include "settings.h"
class Attachment
{
public:
Attachment( DocLnk lnk );
virtual ~Attachment(){}
const QString getFileName()const{ return doc.file(); }
const QString getName()const{ return doc.name(); }
const QString getMimeType()const{ return doc.type(); }
const QPixmap getPixmap()const{ return doc.pixmap(); }
const int getSize()const { return size; }
DocLnk getDocLnk() { return doc; }
protected:
DocLnk doc;
int size;
};
class Mail
{
public:
Mail();
/* Possible that this destructor must not be declared virtual
* 'cause it seems that it will never have some child classes.
* in this case this object will not get a virtual table -> memory and
* speed will be a little bit better?
*/
virtual ~Mail(){}
void addAttachment( Attachment *att ) { attList.append( att ); }
const QList<Attachment>& getAttachments()const { return attList; }
void removeAttachment( Attachment *att ) { attList.remove( att ); }
const QString&getName()const { return name; }
void setName( QString s ) { name = s; }
const QString&getMail()const{ return mail; }
void setMail( const QString&s ) { mail = s; }
const QString&getTo()const{ return to; }
void setTo( const QString&s ) { to = s; }
const QString&getCC()const{ return cc; }
void setCC( const QString&s ) { cc = s; }
const QString&getBCC()const { return bcc; }
void setBCC( const QString&s ) { bcc = s; }
const QString&getMessage()const { return message; }
void setMessage( const QString&s ) { message = s; }
const QString&getSubject()const { return subject; }
void setSubject( const QString&s ) { subject = s; }
const QString&getReply()const{ return reply; }
void setReply( const QString&a ) { reply = a; }
private:
QList<Attachment> attList;
QString name, mail, to, cc, bcc, reply, subject, message;
};
class Folder : public QObject
{
Q_OBJECT
public:
Folder( const QString&init_name,const QString&sep );
const QString&getDisplayName()const { return nameDisplay; }
const QString&getName()const { return name; }
virtual bool may_select()const{return true;};
const QString&Separator()const;
protected:
QString nameDisplay, name, separator;
};
class IMAPFolder : public Folder
{
public:
IMAPFolder(const QString&name, const QString&sep, bool select=true,const QString&prefix="" );
virtual bool may_select()const{return m_MaySelect;}
private:
+ static QString decodeFolderName( const QString &name );
bool m_MaySelect;
+
};
class MailWrapper : public QObject
{
Q_OBJECT
public:
MailWrapper( Settings *s );
void sendMail( Mail mail );
private:
mailimf_mailbox *newMailbox(const QString&name,const QString&mail );
mailimf_address_list *parseAddresses(const QString&addr );
mailimf_fields *createImfFields( Mail *mail );
mailmime *buildTxtPart( QString str );
mailmime *buildFilePart( QString filename, QString mimetype );
void addFileParts( mailmime *message, QList<Attachment> files );
mailmime *createMimeMail( Mail *mail );
void smtpSend( mailmime *mail );
mailimf_field *getField( mailimf_fields *fields, int type );
clist *createRcptList( mailimf_fields *fields );
char *getFrom( mailmime *mail );
SMTPaccount *getAccount( QString from );
void writeToFile( QString file, mailmime *mail );
void readFromFile( QString file, char **data, size_t *size );
static QString mailsmtpError( int err );
static QString getTmpFile();
Settings *settings;
};
#endif
diff --git a/noncore/net/mail/mailwrapper.cpp b/noncore/net/mail/mailwrapper.cpp
index 858283f..75c06f9 100644
--- a/noncore/net/mail/mailwrapper.cpp
+++ b/noncore/net/mail/mailwrapper.cpp
@@ -1,439 +1,518 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <qdir.h>
#include "mailwrapper.h"
#include "logindialog.h"
//#include "mail.h"
#include "defines.h"
Attachment::Attachment( DocLnk lnk )
{
doc = lnk;
size = QFileInfo( doc.file() ).size();
}
Folder::Folder(const QString&tmp_name, const QString&sep )
{
name = tmp_name;
nameDisplay = name;
-
- for ( int pos = nameDisplay.find( '&' ); pos != -1;
- pos = nameDisplay.find( '&' ) ) {
- int end = nameDisplay.find( '-' );
- if ( end == -1 || end <= pos ) break;
- QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 );
- // TODO: do real base64 decoding here !
- if ( str64.compare( "APw" ) == 0 ) {
- nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" );
- } else if ( str64.compare( "APY" ) == 0 ) {
- nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" );
- }
- }
- qDebug( "folder " + name + " - displayed as " + nameDisplay );
separator = sep;
}
const QString& Folder::Separator()const
{
return separator;
}
IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix )
: Folder( name,sep ),m_MaySelect(select)
{
+ // Decode IMAP foldername
+ nameDisplay = IMAPFolder::decodeFolderName( name );
+ qDebug( "folder " + name + " - displayed as " + nameDisplay );
+
if (prefix.length()>0) {
if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) {
nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length());
}
}
}
+static unsigned char base64chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+
+/**
+ * Decodes base64 encoded parts of the imapfolder name
+ * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc
+ */
+QString IMAPFolder::decodeFolderName( const QString &name )
+{
+ unsigned char c, i, bitcount;
+ unsigned long ucs4, utf16, bitbuf;
+ unsigned char base64[256], utf8[6];
+ unsigned long srcPtr = 0;
+ QCString dst;
+ QCString src = name.ascii();
+
+ /* initialize modified base64 decoding table */
+ memset(base64, UNDEFINED, sizeof(base64));
+ for (i = 0; i < sizeof(base64chars); ++i) {
+ base64[(int)base64chars[i]] = i;
+ }
+
+ /* loop until end of string */
+ while (srcPtr < src.length ()) {
+ c = src[srcPtr++];
+ /* deal with literal characters and &- */
+ if (c != '&' || src[srcPtr] == '-') {
+ /* encode literally */
+ dst += c;
+ /* skip over the '-' if this is an &- sequence */
+ if (c == '&')
+ srcPtr++;
+ } else {
+ /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
+ bitbuf = 0;
+ bitcount = 0;
+ ucs4 = 0;
+ while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) {
+ ++srcPtr;
+ bitbuf = (bitbuf << 6) | c;
+ bitcount += 6;
+ /* enough bits for a UTF-16 character? */
+ if (bitcount >= 16) {
+ bitcount -= 16;
+ utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff;
+ /* convert UTF16 to UCS4 */
+ if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
+ ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
+ continue;
+ } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
+ ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
+ } else {
+ ucs4 = utf16;
+ }
+ /* convert UTF-16 range of UCS4 to UTF-8 */
+ if (ucs4 <= 0x7fUL) {
+ utf8[0] = ucs4;
+ i = 1;
+ } else if (ucs4 <= 0x7ffUL) {
+ utf8[0] = 0xc0 | (ucs4 >> 6);
+ utf8[1] = 0x80 | (ucs4 & 0x3f);
+ i = 2;
+ } else if (ucs4 <= 0xffffUL) {
+ utf8[0] = 0xe0 | (ucs4 >> 12);
+ utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ utf8[2] = 0x80 | (ucs4 & 0x3f);
+ i = 3;
+ } else {
+ utf8[0] = 0xf0 | (ucs4 >> 18);
+ utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
+ utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
+ utf8[3] = 0x80 | (ucs4 & 0x3f);
+ i = 4;
+ }
+ /* copy it */
+ for (c = 0; c < i; ++c) {
+ dst += utf8[c];
+ }
+ }
+ }
+ /* skip over trailing '-' in modified UTF-7 encoding */
+ if (src[srcPtr] == '-')
+ ++srcPtr;
+ }
+ }
+
+ return QString::fromUtf8( dst.data() );
+}
+
MailWrapper::MailWrapper( Settings *s )
: QObject()
{
settings = s;
}
QString MailWrapper::mailsmtpError( int errnum )
{
switch ( errnum ) {
case MAILSMTP_NO_ERROR:
return tr( "No error" );
case MAILSMTP_ERROR_UNEXPECTED_CODE:
return tr( "Unexpected error code" );
case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
return tr( "Service not available" );
case MAILSMTP_ERROR_STREAM:
return tr( "Stream error" );
case MAILSMTP_ERROR_HOSTNAME:
return tr( "gethostname() failed" );
case MAILSMTP_ERROR_NOT_IMPLEMENTED:
return tr( "Not implemented" );
case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
return tr( "Error, action not taken" );
case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
return tr( "Data exceeds storage allocation" );
case MAILSMTP_ERROR_IN_PROCESSING:
return tr( "Error in processing" );
// case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE:
// return tr( "Insufficient system storage" );
case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
return tr( "Mailbox unavailable" );
case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
return tr( "Mailbox name not allowed" );
case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
return tr( "Bad command sequence" );
case MAILSMTP_ERROR_USER_NOT_LOCAL:
return tr( "User not local" );
case MAILSMTP_ERROR_TRANSACTION_FAILED:
return tr( "Transaction failed" );
case MAILSMTP_ERROR_MEMORY:
return tr( "Memory error" );
case MAILSMTP_ERROR_CONNECTION_REFUSED:
return tr( "Connection refused" );
default:
return tr( "Unknown error code" );
}
}
mailimf_mailbox *MailWrapper::newMailbox(const QString&name, const QString&mail )
{
return mailimf_mailbox_new( strdup( name.latin1() ),
strdup( mail.latin1() ) );
}
mailimf_address_list *MailWrapper::parseAddresses(const QString&addr )
{
mailimf_address_list *addresses;
if ( addr.isEmpty() ) return NULL;
addresses = mailimf_address_list_new_empty();
QStringList list = QStringList::split( ',', addr );
QStringList::Iterator it;
for ( it = list.begin(); it != list.end(); it++ ) {
char *str = strdup( (*it).latin1() );
int err = mailimf_address_list_add_parse( addresses, str );
if ( err != MAILIMF_NO_ERROR ) {
qDebug( "Error parsing" );
qDebug( *it );
free( str );
} else {
qDebug( "Parse success! :)" );
}
}
return addresses;
}
mailimf_fields *MailWrapper::createImfFields( Mail *mail )
{
mailimf_fields *fields;
mailimf_field *xmailer;
mailimf_mailbox *sender, *fromBox;
mailimf_mailbox_list *from;
mailimf_address_list *to, *cc, *bcc, *reply;
char *subject = strdup( mail->getSubject().latin1() );
int err;
sender = newMailbox( mail->getName(), mail->getMail() );
if ( sender == NULL ) goto err_free;
fromBox = newMailbox( mail->getName(), mail->getMail() );
if ( fromBox == NULL ) goto err_free_sender;
from = mailimf_mailbox_list_new_empty();
if ( from == NULL ) goto err_free_fromBox;
err = mailimf_mailbox_list_add( from, fromBox );
if ( err != MAILIMF_NO_ERROR ) goto err_free_from;
to = parseAddresses( mail->getTo() );
if ( to == NULL ) goto err_free_from;
cc = parseAddresses( mail->getCC() );
bcc = parseAddresses( mail->getBCC() );
reply = parseAddresses( mail->getReply() );
fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc,
NULL, NULL, subject );
if ( fields == NULL ) goto err_free_reply;
xmailer = mailimf_field_new_custom( strdup( "User-Agent" ),
strdup( USER_AGENT ) );
if ( xmailer == NULL ) goto err_free_fields;
err = mailimf_fields_add( fields, xmailer );
if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer;
return fields; // Success :)
err_free_xmailer:
mailimf_field_free( xmailer );
err_free_fields:
mailimf_fields_free( fields );
err_free_reply:
mailimf_address_list_free( reply );
mailimf_address_list_free( bcc );
mailimf_address_list_free( cc );
mailimf_address_list_free( to );
err_free_from:
mailimf_mailbox_list_free( from );
err_free_fromBox:
mailimf_mailbox_free( fromBox );
err_free_sender:
mailimf_mailbox_free( sender );
err_free:
free( subject );
qDebug( "createImfFields - error" );
return NULL; // Error :(
}
mailmime *MailWrapper::buildTxtPart( QString str )
{
mailmime *txtPart;
mailmime_fields *fields;
mailmime_content *content;
mailmime_parameter *param;
char *txt = strdup( str.latin1() );
int err;
param = mailmime_parameter_new( strdup( "charset" ),
strdup( "iso-8859-1" ) );
if ( param == NULL ) goto err_free;
content = mailmime_content_new_with_str( "text/plain" );
if ( content == NULL ) goto err_free_param;
err = clist_append( content->ct_parameters, param );
if ( err != MAILIMF_NO_ERROR ) goto err_free_content;
fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT );
if ( fields == NULL ) goto err_free_content;
txtPart = mailmime_new_empty( content, fields );
if ( txtPart == NULL ) goto err_free_fields;
err = mailmime_set_body_text( txtPart, txt, strlen( txt ) );
if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
return txtPart; // Success :)
err_free_txtPart:
mailmime_free( txtPart );
err_free_fields:
mailmime_fields_free( fields );
err_free_content:
mailmime_content_free( content );
err_free_param:
mailmime_parameter_free( param );
err_free:
free( txt );
qDebug( "buildTxtPart - error" );
return NULL; // Error :(
}
mailmime *MailWrapper::buildFilePart( QString filename, QString mimetype )
{
mailmime * filePart;
mailmime_fields * fields;
mailmime_content * content;
mailmime_parameter * param = NULL;
int err;
int pos = filename.findRev( '/' );
QString tmp = filename.right( filename.length() - ( pos + 1 ) );
char *name = strdup( tmp.latin1() ); // just filename
char *file = strdup( filename.latin1() ); // full name with path
char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain
fields = mailmime_fields_new_filename(
MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name,
MAILMIME_MECHANISM_BASE64 );
if ( fields == NULL ) goto err_free;
content = mailmime_content_new_with_str( mime );
if ( content == NULL ) goto err_free_fields;
if ( mimetype.compare( "text/plain" ) == 0 ) {
param = mailmime_parameter_new( strdup( "charset" ),
strdup( "iso-8859-1" ) );
if ( param == NULL ) goto err_free_content;
err = clist_append( content->ct_parameters, param );
if ( err != MAILIMF_NO_ERROR ) goto err_free_param;
}
filePart = mailmime_new_empty( content, fields );
if ( filePart == NULL ) goto err_free_param;
err = mailmime_set_body_file( filePart, file );
if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
return filePart; // Success :)
err_free_filePart:
mailmime_free( filePart );
err_free_param:
if ( param != NULL ) mailmime_parameter_free( param );
err_free_content:
mailmime_content_free( content );
err_free_fields:
mailmime_fields_free( fields );
err_free:
free( name );
free( mime );
free( file );
qDebug( "buildFilePart - error" );
return NULL; // Error :(
}
void MailWrapper::addFileParts( mailmime *message, QList<Attachment> files )
{
Attachment *it;
for ( it = files.first(); it; it = files.next() ) {
qDebug( "Adding file" );
mailmime *filePart;
int err;
filePart = buildFilePart( it->getFileName(), it->getMimeType() );
if ( filePart == NULL ) goto err_free;
err = mailmime_smart_add_part( message, filePart );
if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
continue; // Success :)
err_free_filePart:
mailmime_free( filePart );
err_free:
qDebug( "addFileParts: error adding file:" );
qDebug( it->getFileName() );
}
}
mailmime *MailWrapper::createMimeMail( Mail *mail )
{
mailmime *message, *txtPart;
mailimf_fields *fields;
int err;
fields = createImfFields( mail );
if ( fields == NULL ) goto err_free;
message = mailmime_new_message_data( NULL );
if ( message == NULL ) goto err_free_fields;
mailmime_set_imf_fields( message, fields );
txtPart = buildTxtPart( mail->getMessage() );
if ( txtPart == NULL ) goto err_free_message;
err = mailmime_smart_add_part( message, txtPart );
if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
addFileParts( message, mail->getAttachments() );
return message; // Success :)
err_free_txtPart:
mailmime_free( txtPart );
err_free_message:
mailmime_free( message );
err_free_fields:
mailimf_fields_free( fields );
err_free:
qDebug( "createMimeMail: error" );
return NULL; // Error :(
}
mailimf_field *MailWrapper::getField( mailimf_fields *fields, int type )
{
mailimf_field *field;
clistiter *it;
it = clist_begin( fields->fld_list );
while ( it ) {
field = (mailimf_field *) it->data;
if ( field->fld_type == type ) {
return field;
}
it = it->next;
}
return NULL;
}
static void addRcpts( clist *list, mailimf_address_list *addr_list )
{
clistiter *it, *it2;
for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) {
mailimf_address *addr;
addr = (mailimf_address *) it->data;
if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) {
esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL );
} else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) {
clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list;
for ( it2 = clist_begin( l ); it2; it2 = it2->next ) {
mailimf_mailbox *mbox;
mbox = (mailimf_mailbox *) it2->data;
esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL );
}
}
}
}
clist *MailWrapper::createRcptList( mailimf_fields *fields )
{
clist *rcptList;
mailimf_field *field;
rcptList = esmtp_address_list_new();
field = getField( fields, MAILIMF_FIELD_TO );
if ( field && (field->fld_type == MAILIMF_FIELD_TO)
&& field->fld_data.fld_to->to_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_to->to_addr_list );
}
field = getField( fields, MAILIMF_FIELD_CC );
if ( field && (field->fld_type == MAILIMF_FIELD_CC)
&& field->fld_data.fld_cc->cc_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list );
}
field = getField( fields, MAILIMF_FIELD_BCC );
if ( field && (field->fld_type == MAILIMF_FIELD_BCC)
&& field->fld_data.fld_bcc->bcc_addr_list ) {
addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list );
}
return rcptList;
}
char *MailWrapper::getFrom( mailmime *mail )
{
char *from = NULL;
mailimf_field *ffrom;
ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM );
if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM)
&& ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) {
clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list;
clistiter *it;
for ( it = clist_begin( cl ); it; it = it->next ) {
mailimf_mailbox *mb = (mailimf_mailbox *) it->data;
from = strdup( mb->mb_addr_spec );
}
diff --git a/noncore/net/mail/mailwrapper.h b/noncore/net/mail/mailwrapper.h
index d78f8e9..02fe4b7 100644
--- a/noncore/net/mail/mailwrapper.h
+++ b/noncore/net/mail/mailwrapper.h
@@ -1,124 +1,126 @@
#ifndef MAILWRAPPER_H
#define MAILWRAPPER_H
#include <qpe/applnk.h>
#include <libetpan/mailmime.h>
#include <libetpan/mailimf.h>
#include <libetpan/mailsmtp.h>
#include <libetpan/mailstorage.h>
#include <libetpan/maildriver.h>
#include <qbitarray.h>
#include <qdatetime.h>
#include "settings.h"
class Attachment
{
public:
Attachment( DocLnk lnk );
virtual ~Attachment(){}
const QString getFileName()const{ return doc.file(); }
const QString getName()const{ return doc.name(); }
const QString getMimeType()const{ return doc.type(); }
const QPixmap getPixmap()const{ return doc.pixmap(); }
const int getSize()const { return size; }
DocLnk getDocLnk() { return doc; }
protected:
DocLnk doc;
int size;
};
class Mail
{
public:
Mail();
/* Possible that this destructor must not be declared virtual
* 'cause it seems that it will never have some child classes.
* in this case this object will not get a virtual table -> memory and
* speed will be a little bit better?
*/
virtual ~Mail(){}
void addAttachment( Attachment *att ) { attList.append( att ); }
const QList<Attachment>& getAttachments()const { return attList; }
void removeAttachment( Attachment *att ) { attList.remove( att ); }
const QString&getName()const { return name; }
void setName( QString s ) { name = s; }
const QString&getMail()const{ return mail; }
void setMail( const QString&s ) { mail = s; }
const QString&getTo()const{ return to; }
void setTo( const QString&s ) { to = s; }
const QString&getCC()const{ return cc; }
void setCC( const QString&s ) { cc = s; }
const QString&getBCC()const { return bcc; }
void setBCC( const QString&s ) { bcc = s; }
const QString&getMessage()const { return message; }
void setMessage( const QString&s ) { message = s; }
const QString&getSubject()const { return subject; }
void setSubject( const QString&s ) { subject = s; }
const QString&getReply()const{ return reply; }
void setReply( const QString&a ) { reply = a; }
private:
QList<Attachment> attList;
QString name, mail, to, cc, bcc, reply, subject, message;
};
class Folder : public QObject
{
Q_OBJECT
public:
Folder( const QString&init_name,const QString&sep );
const QString&getDisplayName()const { return nameDisplay; }
const QString&getName()const { return name; }
virtual bool may_select()const{return true;};
const QString&Separator()const;
protected:
QString nameDisplay, name, separator;
};
class IMAPFolder : public Folder
{
public:
IMAPFolder(const QString&name, const QString&sep, bool select=true,const QString&prefix="" );
virtual bool may_select()const{return m_MaySelect;}
private:
+ static QString decodeFolderName( const QString &name );
bool m_MaySelect;
+
};
class MailWrapper : public QObject
{
Q_OBJECT
public:
MailWrapper( Settings *s );
void sendMail( Mail mail );
private:
mailimf_mailbox *newMailbox(const QString&name,const QString&mail );
mailimf_address_list *parseAddresses(const QString&addr );
mailimf_fields *createImfFields( Mail *mail );
mailmime *buildTxtPart( QString str );
mailmime *buildFilePart( QString filename, QString mimetype );
void addFileParts( mailmime *message, QList<Attachment> files );
mailmime *createMimeMail( Mail *mail );
void smtpSend( mailmime *mail );
mailimf_field *getField( mailimf_fields *fields, int type );
clist *createRcptList( mailimf_fields *fields );
char *getFrom( mailmime *mail );
SMTPaccount *getAccount( QString from );
void writeToFile( QString file, mailmime *mail );
void readFromFile( QString file, char **data, size_t *size );
static QString mailsmtpError( int err );
static QString getTmpFile();
Settings *settings;
};
#endif