Beispiel #1
0
// Get the multipart identifier information for a message.
static bool getMultipartInfo( const QSMSMessage& msg, QString& multiId,
                              uint& part, uint& numParts )
{
    QByteArray headers = msg.headers();
    int posn = 0;
    uint tag;
    int len;
    while ( ( posn + 2 ) <= headers.size() ) {
        tag = (unsigned char)(headers[posn]);
        len = (unsigned char)(headers[posn + 1]);
        if ( ( posn + len + 2 ) > headers.size() )
            break;
        if ( tag == 0 && len >= 3 ) {
            // Concatenated message with 8-bit identifiers.
            multiId = msg.sender() + "&" +
                      QString::number
                        ( (uint)(unsigned char)(headers[posn + 2]) );
            numParts = (unsigned char)(headers[posn + 3]);
            part     = (unsigned char)(headers[posn + 4]);
            if ( numParts && part && part <= numParts )
                return true;
        } else if ( tag == 8 && len >= 4 ) {
            // Concatenated message with 16-bit identifiers.
            multiId = msg.sender() + "&" +
                      QString::number
                        ( ( (uint)(unsigned char)(headers[posn + 2]) << 8 ) +
                            (uint)(unsigned char)(headers[posn + 3]) );
            numParts = (unsigned char)(headers[posn + 4]);
            part     = (unsigned char)(headers[posn + 5]);
            if ( numParts && part && part <= numParts )
                return true;
        }
        posn += 2 + len;
    }
    return false;
}
Beispiel #2
0
void SmsClient::fetched( const QString& id, const QSMSMessage& message )
{
    if (!id.isEmpty()) {
        QMailMessage mail;
        QString subject;
        QString body;
        int part;

        // Construct a full identity for the message.  This should be
        // unique enough to identify messages on different SIM's.
        QDateTime dt = message.timestamp();
        QString identity = QString("sms:%1:%2%3%4%5%6%7:>%8")
                                .arg( simIdentity )
                                .arg( dt.date().year(), 4 )
                                .arg( dt.date().month(), 2 )
                                .arg( dt.date().day(), 2 )
                                .arg( dt.time().hour(), 2 )
                                .arg( dt.time().minute(), 2 )
                                .arg( dt.time().second(), 2 )
                                .arg( id );

        // Add it to the active list, so that we know what's on the
        // inserted SIM right now, as opposed to the cached copy in
        // the mailbox folder.
        activeIds += identity;
        timeStamps += dt;

        // If we already have this message in the mailbox, then ignore it.
        if ( account ) {
            QStringList list = account->getUidlList();
            if ( list.contains( identity ) ) {
                if ( account->deleteMail() )
                    deleteImmediately( id );
                req->nextMessage();
                return;
            }
            list += identity;
            account->setUidlList( list );
        }
        mail.setServerUid( identity );

        // If the sender is not set, but the recipient is, then this
        // is probably an outgoing message that was reflected back
        // by the phone simulator.
        if( !message.sender().isEmpty() )
            mail.setHeaderField( "From", message.sender() );
        else if( !message.recipient().isEmpty() )
            mail.setHeaderField( "From", message.recipient() );

        // Extract the subject and body.
        extractSubjectAndBody( message.text(), subject, body );

        // Set the subject from the first few words of the text.
        mail.setSubject( subject );

        // Determine if the entire body is text, or if it contains attachments.
        bool hasAttachments = false;
        QList<QSMSMessagePart> parts = message.parts();
        for ( part = 0; part < parts.count(); ++part ) {
            if ( !(parts[part].isText()) ) {
                hasAttachments = true;
                break;
            }
        }
        if( !hasAttachments ) {
            QMailMessageContentType type("text/plain; charset=UTF-8");
            mail.setBody( QMailMessageBody::fromData( body, type, QMailMessageBody::Base64 ) );
        } else {
            SMSDecoder::formatMessage( mail, message );
        }

        // Set the reception date.
        QDateTime date = message.timestamp();
        if (!date.isValid())
            date = QDateTime::currentDateTime();
        mail.setDate( QMailTimeStamp( date ) );

        // Synthesize some other headers
        QString smsType;
        switch(message.messageType()) {
            case QSMSMessage::Normal:
                smsType = "normal"; break;
            case QSMSMessage::CellBroadCast:
                smsType = "broadcast"; break;
            case QSMSMessage::StatusReport:
                smsType = "status-report"; break;
            default:
                smsType = "unknown"; break;
        }
        mail.setHeaderField( "X-Sms-Type", smsType );

        QMailId id;
        mail.setId( id );

        mail.setStatus( QMailMessage::Incoming, true);
        mail.setStatus( QMailMessage::Downloaded, true);
        mail.setFromAccount( account->id() );
        mail.setFromMailbox( "" );
        mail.setMessageType( QMailMessage::Sms );

        // Is this necessary?
        QByteArray mailStr = mail.toRfc2822();
        mail.setSize( mailStr.length() );

        emit newMessage(mail);
        
        // If the "deleteMail" flag is set, then delete the message
        // from the SIM immediately, rather than waiting for later.
        if ( account && account->deleteMail() )
            deleteImmediately( QString::number(id.toULongLong()) );

        req->nextMessage();

        sawNewMessage = true;
    } else {
        smsFetching = false;
        if ( sawNewMessage ) {
            // Check again, just in case another new message arrived
            // while we were performing the fetch.
            req->check();
            return;
        }

        emit allMessagesReceived();

        // Make sure there are always 5 free slots on the SIM card
        // so there is enough space for the reception of new messages.
        if ( account && !account->deleteMail()
             && (req->totalMessages() - req->usedMessages()) < 5
             && req->totalMessages() >= 5
             && !timeStamps.isEmpty() ) {
            int toBeDeleted = 5 - (req->totalMessages() - req->usedMessages());
            while ( toBeDeleted-- > 0 && activeIds.size() > 0 ) {
                QDateTime dt = timeStamps[0];
                int index = 0;
                for (int i = 1; i < timeStamps.size(); ++i) {
                    if (timeStamps[i] < dt) {
                        dt = timeStamps[i];
                        index = i;
                    }
                }
                deleteImmediately( activeIds[index] );
                activeIds.removeAt( index );
                timeStamps.removeAt( index );
            }
        }
    }
}
Beispiel #3
0
void SmsReader::onRequestSmsCommand()
{
    AtCommand *cmd = qobject_cast<AtCommand*>(sender());
    if (cmd) {
        QHash<QString, QList<QSMSMessage> > multiSms;
        AtResult res = cmd->getCommandResult();
        if (res.resultCode() == AtResult::OK) {
            m_incomingMessages.clear();
            QStringList lines = res.content().split("\n");
            int messageId = -1;
            QRegExp messageIdExtractor("^\\+CMGL:\\s*(\\d+)");
            Q_FOREACH(const QString &line, lines) {
                if (messageId < 0) {
                    // expected "CMGL: 0,1,,123", where first number is messageId
                    if (messageIdExtractor.indexIn(line) >= 0) {
                        bool ok;
                        messageId = messageIdExtractor.cap(1).toInt(&ok);
                        if (!ok) {
                            messageId = -1;
                        }
                    }
                } else {
                    // expected pdu
                    QSMSMessage smsMsg = QSMSMessage::fromPdu(QByteArray::fromHex(line.toLatin1()));
                    if (!smsMsg.sender().isEmpty()) {
                        QString multiId;
                        uint part;
                        uint partCount;
                        smsMsg.setMessageIds({messageId});
                        if (getMultipartInfo(smsMsg, multiId, part, partCount)) {
                            smsMsg.setMessagePartNumber(part);
                            multiSms[multiId].append(smsMsg);
                        } else {
                            m_incomingMessages.append(smsMsg);
                        }
                    }
                    messageId = -1;
                }
            }
            QHashIterator<QString, QList<QSMSMessage> > it(multiSms);
            while (it.hasNext()) {
                it.next();
                QList<QSMSMessage> mess = it.value();
                if (mess.count() > 1) {
                    QString multiId;
                    uint part;
                    uint partCount;
                    if (getMultipartInfo(mess.at(0), multiId, part, partCount)) {
                        if (partCount == (uint)mess.count()) {
                            // we have all part of sms message
                            QList<int> smsIds;
                            qSort(mess.begin(), mess.end(), [](const QSMSMessage &m1, const QSMSMessage &m2) {
                                return m1.messagePartNumber() < m2.messagePartNumber();
                            });
                            QString smsText;
                            QSMSMessage newMes;
                            for (const QSMSMessage &smsMess : mess) {
                                smsIds.append(smsMess.messageIds().at(0));
                                smsText.append(smsMess.text());
                                newMes.setTimestamp(smsMess.timestamp());
                                newMes.setSender(smsMess.sender());
                            }
                            newMes.setText(smsText);
                            newMes.setMessageIds(smsIds);
                            m_incomingMessages.append(newMes);
                        }
                    }
                }
            }
            logMsg(QString("Request sms command: we have %0 sms").arg(m_incomingMessages.count()));
            if (count() > 0) {
                emit incomingSms();
            }
        } else {