smsdecoder.cpp

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

CPP
879 行
字号
/******************************************************************************** Copyright (C) 2000-2006 TROLLTECH ASA. All rights reserved.**** This file is part of the Phone Edition of the Qtopia Toolkit.**** Licensees holding a valid license agreement from Trolltech or any of its** authorized distributors may use this file in accordance with** the License Agreement provided with the Licensed Software.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for**   information about Trolltech's Commercial License Agreements.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.********** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "smsdecoder.h"#include <qbuffer.h>#include <qtopiaphone/qphone.h>#include <qtopiaphone/qsmsrequest.h>#include <qtopiaphone/qsmsmessage.h>#include <qtopia/mail/mailmessage.h>#include <qtopia/wap/wbxmlreader.h>#include <qtopia/wap/otareader.h>#include <qtopia/wap/wsppdu.h>// Nokia-style application port numbers of interest.  Most based on the// "Nokia Smart Messaging Specification 3.0.0" and the "Nokia Over// the Air Settings Specification 7.0".#define	SMS_PORT_MIME_VCARD	    226#define	SMS_PORT_MIME_VCALENDAR	    228#define	SMS_PORT_WAP_PUSH	    2948#define	SMS_PORT_RING_TONE	    5505#define	SMS_PORT_OPERATOR_LOGO	    5506#define	SMS_PORT_CLI_LOGO	    5507#define	SMS_PORT_MULTIPART_MESSAGE  5514#define	SMS_PORT_WAP_VCARD	    9204#define	SMS_PORT_WAP_VCALENDAR	    9205#define	SMS_PORT_INTERNET_CONFIG    49999SMSDecoder::SMSDecoder(){}SMSDecoder::~SMSDecoder(){}QString SMSDecoder::mimeTypeForPort( int port ){    switch ( port ) {	case SMS_PORT_MIME_VCARD:	case SMS_PORT_WAP_VCARD:	    return "text/x-vcard";	case SMS_PORT_MIME_VCALENDAR:	case SMS_PORT_WAP_VCALENDAR:	    return "text/x-vcalendar";	case SMS_PORT_RING_TONE:	    return "audio/x-ota-ringtone";		    // FIXME    }    return QString();}SMSDecoder *SMSDecoder::decoder( int port ){    switch ( port ) {	case SMS_PORT_MULTIPART_MESSAGE:	    return new SMSMultipartDecoder();	case SMS_PORT_OPERATOR_LOGO:	    return new SMSLogoDecoder( true );	case SMS_PORT_CLI_LOGO:	    return new SMSLogoDecoder( false );	case SMS_PORT_INTERNET_CONFIG:	    return new SMSWbXmlDecoder		( new OtaReader( OtaReader::Nokia ),		  "text/x-wap-prov.browser-settings", true );	case SMS_PORT_WAP_PUSH:	    return new SMSWapPushDecoder();    }    return 0;}SMSMultipartDecoder::SMSMultipartDecoder(){}SMSMultipartDecoder::~SMSMultipartDecoder(){}// Type codes for multipart SMS messages.#define	SMS_MULTI_TEXT_LATIN1	    0x00#define	SMS_MULTI_TEXT_UNICODE	    0x01#define	SMS_MULTI_OTA_BITMAP	    0x02#define	SMS_MULTI_RING_TONE	    0x03#define	SMS_MULTI_PROFILE_NAME	    0x04#define	SMS_MULTI_RESERVED	    0x05#define	SMS_MULTI_SCREEN_SAVER	    0x06void SMSMultipartDecoder::decode( MailMessage& mail, const QSMSMessage& msg ){    QByteArray data = msg.applicationData();    uint posn;    uint type, len, index;    QByteArray part;    QString text;    // Check the version number on the front of the message.    if ( data.size() < 1 || data[0] != '0' )	return;    // Process each of the parts in turn.    posn = 1;    while ( (int)( posn + 3 ) <= data.size() ) {	type = data[posn] & 0xFF;	len = ((data[posn + 1] & 0xFF) << 8) | (data[posn + 2] & 0xFF);	if ( (int)( posn + 3 + len ) > data.size() ) {	    qDebug("invalid sms multipart message length");	    break;	}	part.resize(len);	memcpy( part.data(), data.data() + posn + 3, len );	text = QString();	switch ( type ) {	    case SMS_MULTI_TEXT_LATIN1:	    {		text = QString::fromLatin1( part.data(), (int)len );	    }	    break;	    case SMS_MULTI_TEXT_UNICODE:	    case SMS_MULTI_PROFILE_NAME:	    {		for ( index = 0; (index + 1) < len; index += 2 ) {		    text += (QChar)(((part.data()[index] & 0xFF) << 8) |				    (part.data()[index + 1] & 0xFF));		}	    }	    break;	    case SMS_MULTI_RING_TONE:	    {		MailMessagePart mpart;		mpart.setContentType( "audio/x-ota-ringtone" );		mpart.setEncodedBody		    ( MailMessage::encodeBase64( part ), Base64 );		mail.addMessagePart( mpart );	    }	    break;	    case SMS_MULTI_OTA_BITMAP:	    case SMS_MULTI_SCREEN_SAVER:	    {		MailMessagePart mpart;		mpart.setContentType( "image/x-ota-bitmap" );		mpart.setEncodedBody		    ( MailMessage::encodeBase64( part ), Base64 );		mail.addMessagePart( mpart );	    }	    break;	    default:	    {		qDebug("unknown sms multipart message type %x", (int)type);	    }	    break;	}	if ( !text.isNull() ) {	    QByteArray toUtf8 = text.toUtf8();     QByteArray array(toUtf8.length(),0);	    memcpy( array.data(), toUtf8.data(), toUtf8.length() );	    MailMessagePart mpart;	    mpart.setContentType( "text/plain; charset=utf-8" );	    mpart.setEncodedBody		( MailMessage::encodeQuotedPrintable( array ),		  QuotedPrintable );	    mail.addMessagePart( mpart );	}	posn += len + 3;    }}SMSLogoDecoder::SMSLogoDecoder( bool operatorHeader ){    this->operatorHeader = operatorHeader;}SMSLogoDecoder::~SMSLogoDecoder(){}void SMSLogoDecoder::decode( MailMessage& mail, const QSMSMessage& msg ){    QByteArray data = msg.applicationData();    uint start;    int mcc, mnc;    // Process the header (operator-style or CLI-style).    if ( operatorHeader ) {	// Check the header and version number.      if ( data.size() <= 4 || data[0] != ((char)0x30) )	    return;        // Extract the MCC and MNC, which are stored in BCD,	// terminated with 0x0F.    mcc = ( ( data[1] & 0x0F ) << 12 ) +          ( ( data[1] & 0xF0 ) << 4 ) +          ( ( data[2] & 0x0F ) << 4 ) +          ( ( data[2] & 0xF0 ) >> 4 );	while ( ( mcc & 0x0F ) == 0x0F )	    mcc >>= 4;	mcc = ( ( mcc >> 12 ) & 0x0F ) * 1000 +	      ( ( mcc >> 8 ) & 0x0F ) * 100 +	      ( ( mcc >> 4 ) & 0x0F ) * 10 +	      ( mcc & 0x0F );	mnc = ( ( data[3] & 0x0F ) << 4 ) +	      ( ( data[3] & 0xF0 ) >> 4 );	while ( ( mnc & 0x0F ) == 0x0F )	    mnc >>= 4;	mnc = ( ( mnc >> 4 ) & 0x0F ) * 10 +	      ( mnc & 0x0F );	// Skip a line feed at the end of the header if one is present	// (it may be omitted if the bitmap is large).	start = 4;    if ( data.size() > (int)start && data[start] == (char)0x0A ) {	    ++start;	}    } else {	// Check the CLI header size and contents.      if ( data.size() <= 1 || data[0] != (char)0x30 )	    return;	start = 1;	mcc = 0;	mnc = 0;    }    // Add the rest of the message as an OTA bitmap.    QByteArray bitmap;    bitmap.resize( data.size() - start );    memcpy( bitmap.data(), data.data() + start, data.size() - start );    MailMessagePart mpart;    if ( !mcc && !mnc ) {        mpart.setContentType( "image/x-ota-bitmap" );    } else {        mpart.setContentType( "image/x-ota-bitmap; mcc=" +			      QString::number( mcc ) + "; mnc=" +			      QString::number( mnc ) );    }    mpart.setEncodedBody	( MailMessage::encodeBase64( bitmap ), Base64 );    mail.addMessagePart( mpart );}SMSWbXmlDecoder::SMSWbXmlDecoder( WbXmlReader *reader, const QString& mimeType, bool pushHeader ){    this->reader = reader;    this->mimeType = mimeType;    this->pushHeader = pushHeader;}SMSWbXmlDecoder::~SMSWbXmlDecoder(){    delete reader;}void SMSWbXmlDecoder::decode( MailMessage& mail, const QSMSMessage& msg ){    QString xml;    if ( !pushHeader ) {	xml = reader->toXml( msg.applicationData());    } else {    QByteArray data = msg.applicationData();	QBuffer buffer( &data,0);	buffer.open( QIODevice::ReadOnly );	WspPduDecoder decoder( &buffer );	WspPush push = decoder.decodePush();	xml = reader->toXml( push.data() );    }    MailMessagePart mpart;    QByteArray toUtf8 = xml.toUtf8();    mpart.setContentType( mimeType );    mpart.setEncodedBody( toUtf8, EightBit );    mail.addMessagePart( mpart );}SMSWapPushDecoder::SMSWapPushDecoder(){}SMSWapPushDecoder::~SMSWapPushDecoder(){}void SMSWapPushDecoder::decode( MailMessage& mail, const QSMSMessage& msg ){    MailMessagePart mpart;    // Decode the push header.    QByteArray data = msg.applicationData();    QBuffer buffer(&data,0 );    buffer.open( QIODevice::ReadOnly );    WspPduDecoder decoder( &buffer );    WspPush push = decoder.decodePush();    // Recognise certain kinds of push messages.    const WspField *field = push.header( "Content-Type" );    QString mimeType = ( field ? field->value : QString() );    if ( mimeType.startsWith( "application/vnd.wap.connectivity-wbxml" ) ) {	QString xml;	WbXmlReader *reader = new OtaReader( OtaReader::Wap );	xml = reader->toXml( push.data() );	delete reader;	QByteArray toUtf8 = xml.toUtf8();	mpart.setContentType( "text/vnd.wap.connectivity-xml" );	mpart.setEncodedBody( toUtf8, EightBit );	mail.addMessagePart( mpart );	return;    }    // Add the contents of the push message as a body part.    mpart.setContentType( mimeType );    mpart.setEncodedBody	( MailMessage::encodeBase64( push.data() ), Base64 );    mail.addMessagePart( mpart );}// "Enhanced Messaging Service" formatter, according to GSM 23.040.class EmsPart;class EmsFormatter{public:    EmsFormatter() { _alignment = 0; _parts = 0; }    ~EmsFormatter();    QString closeTags() const { return _closeTags; }    void setCloseTags( const QString& value ) { _closeTags = value; }    QString closeAlignmentTags() const { return _closeAlignmentTags; }    void setCloseAlignmentTags( const QString& value )	{ _closeAlignmentTags = value; }    uint alignment() const { return _alignment; }    void setAlignment( uint value ) { _alignment = value; }    QString text() const { return _text; }    void addText( const QString& value ) { _text += value; }    void addPart( EmsPart *part );    void flushParts( const QString& text, bool final=false );private:    QString _closeTags;    QString _closeAlignmentTags;    uint _alignment;    QString _text;    EmsPart *_parts;    void addQuotedText( const QString& value, uint start, uint end );};class EmsPart{    friend class EmsFormatter;public:    EmsPart() { _start = 0; _length = 0; _next = 0; }    virtual ~EmsPart();    uint start() const { return _start; }    void setStart( uint value ) { _start = value; }    uint length() const { return _length; }    void setLength( uint value ) { _length = value; }    virtual void startFormat( EmsFormatter& formatter );    virtual void endFormat( EmsFormatter& formatter );private:    uint _start;    uint _length;    EmsPart *_next;};class EmsTextFormattingPart : public EmsPart{public:    EmsTextFormattingPart() { _format = 0; _colors = 0; _hasColors = false; }    uint format() const { return _format; }    void setFormat( uint value ) { _format = value; }    uint colors() const { return _colors; }    void setColors( uint value ) { _colors = value; _hasColors = true; }    virtual void startFormat( EmsFormatter& formatter );    virtual void endFormat( EmsFormatter& formatter );private:    uint _format;    uint _colors;    bool _hasColors;};class EmsImagePart : public EmsPart{public:    QString source() const { return _source; }    void setSource( const QString& value ) { _source = value; }    virtual void startFormat( EmsFormatter& formatter );private:    QString _source;

⌨️ 快捷键说明

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