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 + -
显示快捷键?