smsdecoder.cpp

来自「Qtopia下的邮件处理程序」· C++ 代码 · 共 879 行 · 第 1/2 页

CPP
879 行
字号
};class EmsAttachmentPart : public EmsPart{public:    QString source() const { return _source; }    void setSource( const QString& value ) { _source = value; }    QString name() const { return _name; }    void setName( const QString& value ) { _name = value; }    virtual void startFormat( EmsFormatter& formatter );private:    QString _source;    QString _name;};EmsFormatter::~EmsFormatter(){    delete _parts;}void EmsFormatter::addQuotedText( const QString& value, uint start, uint end ){    uint posn = start;    while ( posn < end ) {      switch ( (value[posn]).toAscii() ) {	    case '&':	    {		addText( value.mid( start, posn - start ) );		addText( "&amp;" );		start = posn + 1;	    }	    break;	    case '<':	    {		addText( value.mid( start, posn - start ) );		addText( "&lt;" );		start = posn + 1;	    }	    break;	    case '>':	    {		addText( value.mid( start, posn - start ) );		addText( "&gt;" );		start = posn + 1;	    }	    break;	    case '\r':	    {		addText( value.mid( start, posn - start ) );		addText("<br>");		if ( ( posn + 1 ) < end && value[posn + 1] == '\n' )		    ++posn;		start = posn + 1;	    }	    break;	    case '\n':	    {		addText( value.mid( start, posn - start ) );		addText("<br>");		start = posn + 1;	    }	    break;	    default:	break;	}	++posn;    }    if ( start < end ) {	addText( value.mid( start, end - start ) );    }}void EmsFormatter::addPart( EmsPart *part ){    EmsPart *current = _parts;    EmsPart *prev = 0;    while ( current != 0 ) {	if ( current->_start > part->_start ) {	    break;	}	if ( current->_start == part->_start ) {	    // Insert zero-length image and sound parts after	    // text formatting parts that refer to the range.	    // This makes the formatting apply to the image or	    // sound part as well.	    if ( current->_length <= part->_length )		break;	}	prev = current;	current = current->_next;    }    if ( prev ) {	part->_next = prev->_next;	prev->_next = part;    } else {	part->_next = _parts;	_parts = part;    }}void EmsFormatter::flushParts( const QString& text, bool final ){    uint posn;    uint last = 0;    EmsPart *part;    // Output parts that are interspersed with the text.    for ( posn = 0; posn < (uint)text.length(); ++posn ) {	part = _parts;	while ( part != 0 ) {	    if ( (uint)part->start() == posn ) {		if ( last < posn ) {		    addQuotedText( text, last, posn );		    last = posn;		}		part->startFormat( *this );	    }	    if ( (uint)( part->start() + part->length() ) == posn ) {		if ( last < posn ) {		    addQuotedText( text, last, posn );		    last = posn;		}		part->endFormat( *this );	    }	    part = part->_next;	}    }    // Output the remaining text.    if ( last < (uint)text.length() ) {	addQuotedText( text, last, text.length() );	last = text.length();    }    // Output any parts that appear after the end of the text.    part = _parts;    while ( part != 0 ) {	if ( (uint)part->start() >= last ) {	    part->startFormat( *this );	    part->endFormat( *this );	}	part = part->_next;    }    delete _parts;    _parts = 0;    // Flush the remaining close tags.    if ( final ) {	_text += _closeTags + _closeAlignmentTags;	_closeTags = QString();	_closeAlignmentTags = QString();	_alignment = 0;    } else {	_text += _closeTags;	_closeTags = QString();    }}EmsPart::~EmsPart(){    if ( _next )	delete _next;}void EmsPart::startFormat( EmsFormatter& ){    // Nothing to do here.}void EmsPart::endFormat( EmsFormatter& ){    // Nothing to do here.}void EmsTextFormattingPart::startFormat( EmsFormatter& formatter ){    QString pending;    QString pendingAlignment;    QString openTags;    QString openAlignmentTags;    QString closeTags;    QString closeAlignmentTags;    static const char *colorMap[16] = {	"000000", "808080", "800000", "808000", "008000", "008080",	"000080", "800080", "C0C0C0", "FFFFFF", "FF0000", "FFFF00",	"00FF00", "00FFFF", "0000FF", "FF00FF"    };    // Get the pending close tags to reset the previous text format.    pending = formatter.closeTags();    pendingAlignment = formatter.closeAlignmentTags();    // Build the new open and close tags for this range.    if ( ( _format & 0x03 ) == 0x01 ) {	openAlignmentTags = "<center>";	closeAlignmentTags = "</center>";    } else if ( ( _format & 0x03 ) == 0x02 ) {	openAlignmentTags = "<p align=\"right\">";	closeAlignmentTags = "</p>";    }    if ( _hasColors ) {	openTags += "<font color=\"#" +		    QString( colorMap[_colors & 0x0F] ) + "\">";	closeTags = "</font>" + closeTags;    }    if ( ( _format & 0x0C ) == 0x04 ) {	openTags += "<big>";	closeTags = "</big>" + closeTags;    } else if ( ( _format & 0x0C ) == 0x08 ) {	openTags += "<small>";	closeTags = "</small>" + closeTags;    }    if ( ( _format & 0x10 ) != 0x00 ) {	openTags += "<b>";	closeTags = "</b>" + closeTags;    }    if ( ( _format & 0x20 ) != 0x00 ) {	openTags += "<i>";	closeTags = "</i>" + closeTags;    }    if ( ( _format & 0x40 ) != 0x00 ) {	openTags += "<u>";	closeTags = "</u>" + closeTags;    }    if ( ( _format & 0x80 ) != 0x00 ) {	openTags += "<strike>";	closeTags = "</strike>" + closeTags;    }    // Update the current view of the tags.    if ( ( _format & 0x03 ) != formatter.alignment() ) {	pending += pendingAlignment;	openTags = openAlignmentTags + openTags;    }    formatter.setAlignment( _format & 0x03 );    formatter.setCloseTags( closeTags );    formatter.setCloseAlignmentTags( closeAlignmentTags );    // Add the formatting tags to output at this location.    formatter.addText( pending + openTags );}void EmsTextFormattingPart::endFormat( EmsFormatter& formatter ){    // If the length is zero, then we have set a default and we don't    // want to reset it until the next text formatting change.    if ( length() == 0 ) {	return;    }    // Add the accumulated format close tags, but not the alignment tags.    formatter.addText( formatter.closeTags() );    formatter.setCloseTags( QString() );}void EmsImagePart::startFormat( EmsFormatter& formatter ){    formatter.addText( "<img src=\"" + _source + "\">" );}void EmsAttachmentPart::startFormat( EmsFormatter& formatter ){    formatter.addText( "<a href=\"" + _source + "\">" + _name + "</a>" );}// Predefined EMS image types, from GSM 23.040, section 9.2.3.24.10.3.3.static const char * const predefinedImages[15] = {    "ironic",		    // No tr    "glad",		    // No tr    "skeptical",	    // No tr    "sad",		    // No tr    "wow",		    // No tr    "crying",		    // No tr    "winking",		    // No tr    "laughing",		    // No tr    "indifferent",	    // No tr    "kissing",		    // No tr    "confused",		    // No tr    "tongue",		    // No tr    "angry",		    // No tr    "glasses",		    // No tr    "devil"		    // No tr};void SMSDecoder::formatMessage( MailMessage& mail, const QSMSMessage& msg ){    QList<QSMSMessagePart> parts = msg.parts();    uint part;    bool hasDatagram = false;    QString mimeType;    uint position;    uint partNum = 1;    EmsFormatter formatter;    QString id;    for ( part = 0; part < (uint)parts.count(); ++part ) {	if ( parts[part].isText() ) {	    // Process the parts that relate to this text part.	    formatter.flushParts( parts[part].text() );	} else {	    mimeType = parts[part].mimeType();	    position = parts[part].position();	    if ( mimeType.startsWith( "application/x-qtopia-wdp" ) ) {		// The message contains a WDP datagram, which we		// need to process separately below.		hasDatagram = true;	    } else if ( mimeType.startsWith( "image/" ) ) {		// Process an inline image.		EmsImagePart *emsPart = new EmsImagePart();		emsPart->setStart( position );		id = "part" + QString::number( partNum ) + "@local";		emsPart->setSource( "cid:" + id );		formatter.addPart( emsPart );		MailMessagePart mpart;		mpart.setContentType( mimeType );		mpart.setContentID( "<" + id + ">" );		mpart.setEncodedBody		   ( MailMessage::encodeBase64( parts[part].data() ), Base64 );		mail.addMessagePart( mpart );		++partNum;	    } else if ( mimeType == "application/x-qtopia-sms-10" ) {		// EMS text formatting information.		QByteArray contents = parts[part].data();		if ( contents.count() >= 3 ) {		    EmsTextFormattingPart *emsPart;		    emsPart = new EmsTextFormattingPart();		    emsPart->setStart( contents[0] & 0xFF );		    emsPart->setLength( contents[1] & 0xFF );		    emsPart->setFormat( contents[2] & 0xFF );		    if ( contents.count() >= 4 ) {			emsPart->setColors( contents[3] & 0xFF );		    }		    formatter.addPart( emsPart );		}	    } else if ( mimeType ==			    "application/x-qtopia-predefined-animation" ) {		// EMS predefined animation.		if ( parts[part].data().count() > 0 ) {		    int imageNum = parts[part].data()[0] & 0xFF;		    if ( imageNum < 15 ) {			EmsImagePart *emsPart = new EmsImagePart();			emsPart->setStart( position );			emsPart->setSource			    ( QString( "x-sms-predefined:" ) + // No tr			      predefinedImages[imageNum] );			formatter.addPart( emsPart );		    }		}	    } else {		// Everything else is inserted inline as-is.		EmsAttachmentPart *emsPart = new EmsAttachmentPart();		emsPart->setStart( position );		id = "part" + QString::number( partNum ) + "@local";		emsPart->setSource( "cid:" + id );		emsPart->setName( QObject::tr("Attachment: ") + mimeType );		formatter.addPart( emsPart );		MailMessagePart mpart;		mpart.setContentType( mimeType );		mpart.setContentID( "<" + id + ">" );		mpart.setEncodedBody		   ( MailMessage::encodeBase64( parts[part].data() ), Base64 );		mpart.setName( "part" + QString::number( partNum ) );		mail.addMessagePart( mpart );		++partNum;	    }	}    }    // Flush the remaining parts and get the resultant text/html.    formatter.flushParts( "", true );    if ( formatter.text().length() != 0 ) {	MailMessagePart htmlPart;	QByteArray toUtf8 = formatter.text().toUtf8();	QByteArray array(toUtf8.length(),0);	memcpy( array.data(), toUtf8.data(), toUtf8.length() );	htmlPart.setContentType( "text/html; charset=utf-8" );	htmlPart.setEncodedBody	    ( MailMessage::encodeQuotedPrintable( array ),	      QuotedPrintable );	mail.setMultipartRelated( true );	mail.prependMessagePart( htmlPart );    }    // If we saw a WDP datagram, then we need to process it now.    if ( hasDatagram ) {	int port = msg.destinationPort();	QString type = SMSDecoder::mimeTypeForPort( port );	SMSDecoder *decoder;	MailMessagePart mpart;	if ( !type.isNull() ) {	    // We know the MIME type for this port number.	    mpart.setContentType( type );	    if ( type.startsWith( "text/" ) ) {		mpart.setEncodedBody		    ( MailMessage::encodeQuotedPrintable			    ( msg.applicationData() ),		      QuotedPrintable );	    } else {		mpart.setEncodedBody		    ( MailMessage::encodeBase64( msg.applicationData() ),		      Base64 );	    }	    mail.addMessagePart( mpart );	} else if ( ( decoder = SMSDecoder::decoder( port ) ) != 0 ) {	    // Use the decoder to turn the datagram into something useful.	    decoder->decode( mail, msg );	    delete decoder;	} else {	    // We don't know what to do with this kind of datagram.	    mpart.setContentType		( "application/x-smsapp-" + QString::number( port ) );	    mpart.setEncodedBody		( MailMessage::encodeBase64( msg.applicationData() ),		  Base64 );	    mail.addMessagePart( mpart );	}    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?