1/*
2 * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "gsm_sms_message.h"
17
18#include "core_manager_inner.h"
19#include "securec.h"
20#include "telephony_log_wrapper.h"
21#include "text_coder.h"
22
23namespace OHOS {
24namespace Telephony {
25using namespace std;
26static constexpr uint16_t DEFAULT_PORT = -1;
27static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
28static constexpr uint8_t MAX_SMSC_LEN = 20;
29static constexpr uint16_t MAX_TPDU_DATA_LEN = 255;
30static constexpr uint16_t TAPI_TEXT_SIZE_MAX = 520;
31
32uint8_t GsmSmsMessage::CalcReplyEncodeAddress(const std::string &replyAddress)
33{
34    std::string encodedAddr;
35    if (replyAddress.length() > 0) {
36        struct AddressNumber replyAddr = {};
37        replyAddr.ton = TYPE_NATIONAL;
38        replyAddr.npi = SMS_NPI_ISDN;
39        int ret = memset_s(replyAddr.address, sizeof(replyAddr.address), 0x00, MAX_ADDRESS_LEN + 1);
40        if (ret != EOK) {
41            TELEPHONY_LOGE("CalcReplyEncodeAddress memset_s error!");
42            return 0;
43        }
44        ret = memcpy_s(replyAddr.address, sizeof(replyAddr.address), replyAddress.c_str(), MAX_ADDRESS_LEN);
45        if (ret != EOK) {
46            TELEPHONY_LOGE("CalcReplyEncodeAddress memory_s error!");
47            return 0;
48        }
49        GsmSmsParamCodec codec;
50        codec.EncodeAddressPdu(&replyAddr, encodedAddr);
51    }
52    return encodedAddr.size();
53}
54
55int GsmSmsMessage::SetSmsTpduDestAddress(std::shared_ptr<struct SmsTpdu> &tPdu, const std::string &desAddr)
56{
57    int ret = 0;
58    int addLen = 0;
59    if (tPdu == nullptr) {
60        TELEPHONY_LOGE("TPdu is null.");
61        return addLen;
62    }
63    addLen = static_cast<int>(desAddr.length());
64    tPdu->data.submit.destAddress.ton = TYPE_UNKNOWN;
65    tPdu->data.submit.destAddress.npi = SMS_NPI_ISDN;
66    if (addLen < MAX_ADDRESS_LEN) {
67        ret = memcpy_s(tPdu->data.submit.destAddress.address, sizeof(tPdu->data.submit.destAddress.address),
68            desAddr.c_str(), addLen);
69        if (ret != EOK) {
70            TELEPHONY_LOGE("SetSmsTpduDestAddress memcpy_s error!");
71            return addLen;
72        }
73        tPdu->data.submit.destAddress.address[addLen] = '\0';
74    } else {
75        if (desAddr[0] == '+') {
76            ret = memcpy_s(tPdu->data.submit.destAddress.address, sizeof(tPdu->data.submit.destAddress.address),
77                desAddr.c_str(), MAX_ADDRESS_LEN);
78        } else {
79            ret = memcpy_s(tPdu->data.submit.destAddress.address, sizeof(tPdu->data.submit.destAddress.address),
80                desAddr.c_str(), MAX_ADDRESS_LEN - 1);
81        }
82        if (ret != EOK) {
83            TELEPHONY_LOGE("SetSmsTpduDestAddress memcpy_s error!");
84            return addLen;
85        }
86        tPdu->data.submit.destAddress.address[MAX_ADDRESS_LEN] = '\0';
87    }
88    return addLen;
89}
90
91int GsmSmsMessage::SetHeaderLang(int index, const DataCodingScheme codingType, const MSG_LANGUAGE_ID_T langId)
92{
93    int ret = 0;
94    if (smsTpdu_ == nullptr) {
95        TELEPHONY_LOGE("TPdu is null.");
96        return ret;
97    }
98    switch (smsTpdu_->tpduType) {
99        case SMS_TPDU_SUBMIT:
100            if (codingType == DATA_CODING_7BIT && langId != MSG_ID_RESERVED_LANG) {
101                smsTpdu_->data.submit.userData.header[index].udhType = UDH_SINGLE_SHIFT;
102                smsTpdu_->data.submit.userData.header[index].udh.singleShift.langId = langId;
103                ret++;
104            }
105            break;
106        default:
107            break;
108    }
109    return ret;
110}
111
112int GsmSmsMessage::SetHeaderConcat(int index, const SmsConcat &concat)
113{
114    int ret = 0;
115    if (smsTpdu_ == nullptr) {
116        TELEPHONY_LOGE("TPdu is null.");
117        return ret;
118    }
119    switch (smsTpdu_->tpduType) {
120        case SMS_TPDU_SUBMIT:
121            if (concat.is8Bits) {
122                smsTpdu_->data.submit.userData.header[index].udhType = UDH_CONCAT_8BIT;
123                smsTpdu_->data.submit.userData.header[index].udh.concat8bit.msgRef = concat.msgRef;
124                smsTpdu_->data.submit.userData.header[index].udh.concat8bit.totalSeg = concat.totalSeg;
125                smsTpdu_->data.submit.userData.header[index].udh.concat8bit.seqNum = concat.seqNum;
126            } else {
127                smsTpdu_->data.submit.userData.header[index].udhType = UDH_CONCAT_16BIT;
128                smsTpdu_->data.submit.userData.header[index].udh.concat16bit.msgRef = concat.msgRef;
129                smsTpdu_->data.submit.userData.header[index].udh.concat16bit.totalSeg = concat.totalSeg;
130                smsTpdu_->data.submit.userData.header[index].udh.concat16bit.seqNum = concat.seqNum;
131            }
132            ret++;
133            break;
134        default:
135            break;
136    }
137    return ret;
138}
139
140int GsmSmsMessage::SetHeaderReply(int index)
141{
142    int ret = 0;
143    std::string reply = GetReplyAddress();
144    if (reply.length() == 0) {
145        TELEPHONY_LOGE("address is null.");
146        return ret;
147    }
148    if (smsTpdu_ == nullptr) {
149        TELEPHONY_LOGE("smsTpdu_ is null.");
150        return ret;
151    }
152    switch (smsTpdu_->tpduType) {
153        case SMS_TPDU_SUBMIT: {
154            smsTpdu_->data.submit.bReplyPath = true;
155            smsTpdu_->data.submit.userData.header[index].udhType = UDH_ALTERNATE_REPLY_ADDRESS;
156            smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.ton = TYPE_NATIONAL;
157            smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.npi = SMS_NPI_ISDN;
158            ret = memset_s(smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.address,
159                sizeof(smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.address), 0x00,
160                MAX_ADDRESS_LEN + 1);
161            if (ret != EOK) {
162                TELEPHONY_LOGE("SetHeaderReply memset_s error!");
163                return ret;
164            }
165            if (sizeof(smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.address) < reply.length()) {
166                TELEPHONY_LOGE("reply length exceed maxinum");
167                return ret;
168            }
169            ret = memcpy_s(smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.address,
170                sizeof(smsTpdu_->data.submit.userData.header[index].udh.alternateAddress.address), reply.c_str(),
171                reply.length());
172            if (ret != EOK) {
173                TELEPHONY_LOGE("SetHeaderReply memcpy_s error!");
174                return ret;
175            }
176            break;
177        }
178        default:
179            break;
180    }
181    return ret;
182}
183
184void GsmSmsMessage::CreateDefaultSubmit(bool bStatusReport, const DataCodingScheme codingScheme)
185{
186    smsTpdu_ = std::make_shared<struct SmsTpdu>();
187    if (smsTpdu_ == nullptr) {
188        TELEPHONY_LOGE("Make tPdu is fail.");
189        return;
190    }
191    smsTpdu_->tpduType = SMS_TPDU_SUBMIT;
192    smsTpdu_->data.submit.bHeaderInd = false;
193    smsTpdu_->data.submit.bRejectDup = false;
194    smsTpdu_->data.submit.bStatusReport = bStatusReport;
195    smsTpdu_->data.submit.bReplyPath = false;
196    smsTpdu_->data.submit.msgRef = 0;
197    smsTpdu_->data.submit.dcs.bCompressed = false;
198    smsTpdu_->data.submit.dcs.msgClass = SmsMessageClass::SMS_CLASS_UNKNOWN;
199    smsTpdu_->data.submit.dcs.codingGroup = CODING_GENERAL_GROUP;
200    smsTpdu_->data.submit.dcs.codingScheme = codingScheme;
201    smsTpdu_->data.submit.pid = SMS_NORMAL_PID;
202    smsTpdu_->data.submit.vpf = SMS_VPF_NOT_PRESENT;
203}
204
205std::shared_ptr<struct SmsTpdu> GsmSmsMessage::CreateDefaultSubmitSmsTpdu(const std::string &dest,
206    const std::string &sc, const std::string &text, bool bStatusReport,
207    const DataCodingScheme codingScheme = DATA_CODING_7BIT)
208{
209    SetFullText(text);
210    SetSmscAddr(sc);
211    SetDestAddress(dest);
212    CreateDefaultSubmit(bStatusReport, codingScheme);
213    SetSmsTpduDestAddress(smsTpdu_, dest);
214    return smsTpdu_;
215}
216
217std::shared_ptr<struct SmsTpdu> GsmSmsMessage::CreateDataSubmitSmsTpdu(const std::string &desAddr,
218    const std::string &scAddr, int32_t port, const uint8_t *data, uint32_t dataLen, uint8_t msgRef8bit,
219    DataCodingScheme codingType, bool bStatusReport)
220{
221    SetSmscAddr(scAddr);
222    SetDestAddress(desAddr);
223    CreateDefaultSubmit(bStatusReport, codingType);
224    SetSmsTpduDestAddress(smsTpdu_, desAddr);
225    int endcodeLen = 0;
226    MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
227    uint8_t encodeData[(MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1];
228    if (memset_s(encodeData, sizeof(encodeData), 0x00, sizeof(encodeData)) != EOK) {
229        TELEPHONY_LOGE("failed to initialize!");
230        return nullptr;
231    }
232    const uint8_t *pMsgText = data;
233    uint8_t *pDestText = encodeData;
234    endcodeLen = TextCoder::Instance().Utf8ToGsm7bit(
235        pDestText, ((MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1), pMsgText, static_cast<int16_t>(dataLen), langId);
236    if (smsTpdu_ == nullptr) {
237        TELEPHONY_LOGE("smsTpdu_ is nullptr!");
238        return nullptr;
239    }
240    if (memset_s(smsTpdu_->data.submit.userData.data, sizeof(smsTpdu_->data.submit.userData.data), 0x00,
241            sizeof(smsTpdu_->data.submit.userData.data)) != EOK) {
242        TELEPHONY_LOGE("memset_s is error!");
243        return nullptr;
244    }
245    if ((unsigned int)endcodeLen >= sizeof(smsTpdu_->data.submit.userData.data)) {
246        endcodeLen = sizeof(smsTpdu_->data.submit.userData.data) -1;
247        if (memcpy_s(smsTpdu_->data.submit.userData.data, sizeof(smsTpdu_->data.submit.userData.data), encodeData,
248                sizeof(smsTpdu_->data.submit.userData.data)) != EOK) {
249            TELEPHONY_LOGE("memcpy_s is error!");
250            return nullptr;
251        }
252    } else {
253        if (memcpy_s(smsTpdu_->data.submit.userData.data, sizeof(smsTpdu_->data.submit.userData.data), encodeData,
254                endcodeLen) != EOK) {
255            TELEPHONY_LOGE("memcpy_s is error!");
256            return nullptr;
257        }
258    }
259    smsTpdu_->data.submit.userData.data[endcodeLen] = 0;
260    smsTpdu_->data.submit.userData.length = (int)dataLen;
261    smsTpdu_->data.submit.msgRef = msgRef8bit;
262    return smsTpdu_;
263}
264
265std::shared_ptr<struct EncodeInfo> GsmSmsMessage::GetSubmitEncodeInfo(const std::string &sc, bool bMore)
266{
267    uint8_t encodeSmscAddr[MAX_SMSC_LEN];
268    if (memset_s(encodeSmscAddr, sizeof(encodeSmscAddr), 0x00, sizeof(encodeSmscAddr)) != EOK) {
269        TELEPHONY_LOGE("memset_s error.");
270        return nullptr;
271    }
272
273    uint8_t encodeSmscLen = 0;
274    if ((!sc.empty()) && (sc.length() < MAX_SMSC_LEN)) {
275        struct AddressNumber pAddress;
276        if (memset_s(&pAddress.address, sizeof(pAddress.address), 0x00, sizeof(pAddress.address)) != EOK) {
277            TELEPHONY_LOGE("GetSubmitEncodeInfo memset_s error!");
278            return nullptr;
279        }
280        if (sc.length() > sizeof(pAddress.address)) {
281            return nullptr;
282        }
283        if (memcpy_s(&pAddress.address, sizeof(pAddress.address), sc.data(), sc.length()) != EOK) {
284            TELEPHONY_LOGE("GetSubmitEncodeInfo memcpy_s error!");
285            return nullptr;
286        }
287        pAddress.address[sc.length()] = '\0';
288        if (sc[0] == '+') {
289            pAddress.ton = TYPE_INTERNATIONAL;
290        } else {
291            pAddress.ton = TYPE_UNKNOWN;
292        }
293        pAddress.npi = SMS_NPI_ISDN; /* app cannot set this value */
294        GsmSmsParamCodec codec;
295        encodeSmscLen = codec.EncodeSmscPdu(&pAddress, encodeSmscAddr, sizeof(encodeSmscAddr));
296    }
297    return GetSubmitEncodeInfoPartData(encodeSmscAddr, encodeSmscLen, bMore);
298}
299
300std::shared_ptr<struct EncodeInfo> GsmSmsMessage::GetSubmitEncodeInfoPartData(
301    uint8_t *encodeSmscAddr, uint8_t encodeSmscLen, bool bMore)
302{
303    std::shared_ptr<struct EncodeInfo> info = std::make_shared<struct EncodeInfo>();
304    auto tpduCodec = std::make_shared<GsmSmsTpduCodec>();
305    if (tpduCodec == nullptr) {
306        TELEPHONY_LOGE("tpduCodec nullptr.");
307        return nullptr;
308    }
309    char tpduBuf[MAX_TPDU_DATA_LEN];
310    if (memset_s(tpduBuf, sizeof(tpduBuf), 0x00, sizeof(tpduBuf)) != EOK) {
311        TELEPHONY_LOGE("memset_s error.");
312        return nullptr;
313    }
314
315    uint16_t bufLen = 0;
316    bool ret = tpduCodec->EncodeSmsPdu(smsTpdu_, tpduBuf, sizeof(tpduBuf), bufLen);
317    if (ret && bufLen > 0 && info != nullptr) {
318        if (encodeSmscLen > sizeof(info->smcaData_)) {
319            TELEPHONY_LOGE("GetSubmitEncodeInfo data length invalid.");
320            return nullptr;
321        }
322        if (memcpy_s(info->smcaData_, sizeof(info->smcaData_), encodeSmscAddr, encodeSmscLen) != EOK) {
323            TELEPHONY_LOGE("GetSubmitEncodeInfo encodeSmscAddr memcpy_s error!");
324            return nullptr;
325        }
326        if (memcpy_s(info->tpduData_, sizeof(info->tpduData_), tpduBuf, bufLen) != EOK) {
327            TELEPHONY_LOGE("GetSubmitEncodeInfo memcpy_s error!");
328            return nullptr;
329        }
330        info->smcaLen = encodeSmscLen;
331        info->tpduLen = bufLen;
332        info->isMore_ = bMore;
333    }
334    return info;
335}
336
337std::shared_ptr<struct SmsTpdu> GsmSmsMessage::CreateDeliverSmsTpdu()
338{
339    smsTpdu_ = std::make_shared<struct SmsTpdu>();
340    if (smsTpdu_ == nullptr) {
341        TELEPHONY_LOGE("Make smsTpdu fail.");
342        return smsTpdu_;
343    }
344    smsTpdu_->tpduType = SMS_TPDU_DELIVER;
345    smsTpdu_->data.deliver.bHeaderInd = false;
346    return smsTpdu_;
347}
348
349std::shared_ptr<struct SmsTpdu> GsmSmsMessage::CreateDeliverReportSmsTpdu()
350{
351    smsTpdu_ = std::make_shared<struct SmsTpdu>();
352    if (smsTpdu_ == nullptr) {
353        TELEPHONY_LOGE("Make smsTpdu fail.");
354        return smsTpdu_;
355    }
356    smsTpdu_->tpduType = SMS_TPDU_DELIVER_REP;
357    smsTpdu_->data.deliverRep.bHeaderInd = false;
358    smsTpdu_->data.deliverRep.paramInd = 0x00;
359    return smsTpdu_;
360}
361
362std::shared_ptr<struct SmsTpdu> GsmSmsMessage::CreateStatusReportSmsTpdu()
363{
364    smsTpdu_ = std::make_shared<struct SmsTpdu>();
365    if (smsTpdu_ == nullptr) {
366        TELEPHONY_LOGE("Make smsTpdu fail.");
367        return smsTpdu_;
368    }
369    smsTpdu_->tpduType = SMS_TPDU_STATUS_REP;
370    return smsTpdu_;
371}
372
373std::shared_ptr<GsmSmsMessage> GsmSmsMessage::CreateMessage(const std::string &pdu)
374{
375    std::shared_ptr<GsmSmsMessage> message = std::make_shared<GsmSmsMessage>();
376    if (message == nullptr) {
377        TELEPHONY_LOGE("Make message fail.");
378        return message;
379    }
380    message->smsTpdu_ = std::make_shared<struct SmsTpdu>();
381    if (message->smsTpdu_ == nullptr) {
382        TELEPHONY_LOGE("Make smsTpdu fail.");
383        return message;
384    }
385    (void)memset_s(message->smsTpdu_.get(), sizeof(struct SmsTpdu), 0x00, sizeof(struct SmsTpdu));
386    std::string pduData = StringUtils::HexToString(pdu);
387    message->rawPdu_ = StringUtils::HexToByteVector(pdu);
388    if (message->PduAnalysis(pduData)) {
389        return message;
390    }
391    return nullptr;
392}
393
394bool GsmSmsMessage::PduAnalysis(const string &pdu)
395{
396    if (smsTpdu_ == nullptr || pdu.empty() || pdu.length() > MAX_TPDU_DATA_LEN) {
397        TELEPHONY_LOGE("GsmSmsMessage::PduAnalysis smsTpdu is null");
398        return false;
399    }
400    struct AddressNumber smsc;
401    if (memset_s(&smsc, sizeof(struct AddressNumber), 0x00, sizeof(struct AddressNumber)) != EOK) {
402        TELEPHONY_LOGE("PduAnalysis memset_s error!");
403        return false;
404    }
405    GsmSmsParamCodec codec;
406    uint8_t smscLen = codec.DecodeSmscPdu(reinterpret_cast<const uint8_t *>(pdu.c_str()), pdu.length(), smsc);
407    if (smscLen >= pdu.length()) {
408        TELEPHONY_LOGE("PduAnalysis pdu is invalid!");
409        return false;
410    } else if (smscLen > 0) {
411        scAddress_ = smsc.address;
412    }
413    uint8_t tempPdu[TAPI_TEXT_SIZE_MAX + 1] = { 0 };
414    if (sizeof(tempPdu) + smscLen < pdu.length()) {
415        TELEPHONY_LOGE("pdu length exceed maxinum");
416        return false;
417    }
418    if (memcpy_s(tempPdu, sizeof(tempPdu), (pdu.c_str() + smscLen), pdu.length() - smscLen) != EOK) {
419        TELEPHONY_LOGE("PduAnalysis memset_s error!");
420        return false;
421    }
422    auto tpduCodec = std::make_shared<GsmSmsTpduCodec>();
423    if (!tpduCodec->DecodeSmsPdu(tempPdu, pdu.length() - smscLen, smsTpdu_.get())) {
424        TELEPHONY_LOGE("DecodeSmsPdu fail");
425        return false;
426    }
427    return PduAnalysisMsg();
428}
429
430bool GsmSmsMessage::PduAnalysisMsg()
431{
432    bool result = true;
433    switch (smsTpdu_->tpduType) {
434        case SMS_TPDU_DELIVER:
435            AnalysisMsgDeliver(smsTpdu_->data.deliver);
436            break;
437        case SMS_TPDU_STATUS_REP:
438            AnalysisMsgStatusReport(smsTpdu_->data.statusRep);
439            break;
440        case SMS_TPDU_SUBMIT:
441            AnalysisMsgSubmit(smsTpdu_->data.submit);
442            break;
443        default:
444            TELEPHONY_LOGE("tpduType is unknown.");
445            result = false;
446            break;
447    }
448    return result;
449}
450
451void GsmSmsMessage::AnalysisMsgDeliver(const SmsDeliver &deliver)
452{
453    protocolId_ = (int)(deliver.pid);
454    hasReplyPath_ = deliver.bReplyPath;
455    bStatusReportMessage_ = deliver.bStatusReport;
456    bMoreMsg_ = deliver.bMoreMsg;
457    bHeaderInd_ = deliver.bHeaderInd;
458    originatingAddress_ = deliver.originAddress.address;
459    headerCnt_ = deliver.userData.headerCnt;
460    ConvertMsgTimeStamp(deliver.timeStamp);
461    ConvertMessageDcs();
462    ConvertUserData();
463}
464
465void GsmSmsMessage::AnalysisMsgStatusReport(const SmsStatusReport &statusRep)
466{
467    protocolId_ = (int)(statusRep.pid);
468    msgRef_ = statusRep.msgRef;
469    bMoreMsg_ = statusRep.bMoreMsg;
470    bStatusReportMessage_ = statusRep.bStatusReport;
471    bHeaderInd_ = statusRep.bHeaderInd;
472    status_ = statusRep.status;
473    ConvertMsgTimeStamp(statusRep.timeStamp);
474    ConvertMessageDcs();
475    ConvertUserData();
476}
477
478void GsmSmsMessage::AnalysisMsgSubmit(const SmsSubmit &submit)
479{
480    protocolId_ = static_cast<int>(submit.pid);
481    hasReplyPath_ = submit.bReplyPath;
482    msgRef_ = submit.msgRef;
483    bStatusReportMessage_ = submit.bStatusReport;
484    bHeaderInd_ = submit.bHeaderInd;
485    ConvertMsgTimeStamp(submit.validityPeriod);
486    ConvertMessageDcs();
487    ConvertUserData();
488}
489
490void GsmSmsMessage::ConvertMessageDcs()
491{
492    if (smsTpdu_ == nullptr) {
493        TELEPHONY_LOGE("GsmSmsMessage::ConvertMessageDcs smsTpdu is null");
494        return;
495    }
496    switch (smsTpdu_->tpduType) {
497        case SMS_TPDU_DELIVER:
498            bCompressed_ = smsTpdu_->data.deliver.dcs.bCompressed;
499            codingScheme_ = smsTpdu_->data.deliver.dcs.codingScheme;
500            codingGroup_ = smsTpdu_->data.deliver.dcs.codingGroup;
501            bIndActive_ = smsTpdu_->data.deliver.dcs.bIndActive;
502            bMwi_ = smsTpdu_->data.deliver.dcs.bMWI;
503            bMwiSense_ = smsTpdu_->data.deliver.dcs.bIndActive; /* Indicates vmail notification set/clear */
504            ConvertMessageClass(smsTpdu_->data.deliver.dcs.msgClass);
505            break;
506        case SMS_TPDU_STATUS_REP:
507            bCompressed_ = smsTpdu_->data.statusRep.dcs.bCompressed;
508            codingScheme_ = smsTpdu_->data.statusRep.dcs.codingScheme;
509            codingGroup_ = smsTpdu_->data.statusRep.dcs.codingGroup;
510            bIndActive_ = smsTpdu_->data.statusRep.dcs.bIndActive;
511            ConvertMessageClass(smsTpdu_->data.statusRep.dcs.msgClass);
512            break;
513        case SMS_TPDU_SUBMIT:
514            bCompressed_ = smsTpdu_->data.submit.dcs.bCompressed;
515            codingScheme_ = smsTpdu_->data.submit.dcs.codingScheme;
516            codingGroup_ = smsTpdu_->data.submit.dcs.codingGroup;
517            bIndActive_ = smsTpdu_->data.submit.dcs.bIndActive;
518            bMwi_ = smsTpdu_->data.submit.dcs.bMWI;
519            bMwiSense_ = smsTpdu_->data.submit.dcs.bIndActive;
520            ConvertMessageClass(smsTpdu_->data.submit.dcs.msgClass);
521            break;
522        default:
523            break;
524    }
525}
526
527void GsmSmsMessage::ConvertUserData()
528{
529    int ret = 0;
530    if (smsTpdu_ == nullptr ||
531        (memset_s(&smsUserData_, sizeof(struct SmsUDPackage), 0x00, sizeof(struct SmsUDPackage)) != EOK)) {
532        TELEPHONY_LOGE("nullptr or memset_s error.");
533        return;
534    }
535    size_t udLen = sizeof(SmsUDPackage);
536    size_t tpduLen = sizeof(SmsTpud);
537    switch (smsTpdu_->tpduType) {
538        case SMS_TPDU_DELIVER:
539            headerDataLen_ = smsTpdu_->data.deliver.userData.length;
540            ret = memcpy_s(&smsUserData_, udLen, &(smsTpdu_->data.deliver.userData), udLen);
541            if (ret == EOK) {
542                ret = memcpy_s(&smsWapPushUserData_, tpduLen, &(smsTpdu_->data.deliver.udData), tpduLen);
543            }
544            break;
545        case SMS_TPDU_STATUS_REP:
546            headerDataLen_ = smsTpdu_->data.statusRep.userData.length;
547            ret = memcpy_s(&smsUserData_, udLen, &(smsTpdu_->data.statusRep.userData), udLen);
548            break;
549        case SMS_TPDU_SUBMIT:
550            headerDataLen_ = smsTpdu_->data.submit.userData.length;
551            ret = memcpy_s(&smsUserData_, udLen, &(smsTpdu_->data.submit.userData), udLen);
552            break;
553        default:
554            break;
555    }
556    if (ret != EOK) {
557        TELEPHONY_LOGE("memset_s error.");
558        return;
559    }
560    ConvertUserPartData();
561}
562
563void GsmSmsMessage::ConvertUserPartData()
564{
565    if (smsUserData_.length == 0) {
566        TELEPHONY_LOGE("user data length error.");
567        return;
568    }
569    uint8_t buff[MAX_MSG_TEXT_LEN + 1] = { 0 };
570    if (codingScheme_ == DATA_CODING_7BIT) {
571        MsgLangInfo langInfo;
572        auto langId = smsUserData_.header[0].udh.singleShift.langId;
573        if (langId != 0) {
574            langInfo.bSingleShift = true;
575            langInfo.singleLang = langId;
576        }
577        int dataSize = TextCoder::Instance().Gsm7bitToUtf8(
578            buff, MAX_MSG_TEXT_LEN, reinterpret_cast<uint8_t *>(smsUserData_.data), smsUserData_.length, langInfo);
579        visibleMessageBody_.insert(0, reinterpret_cast<char *>(buff), dataSize);
580    } else if (codingScheme_ == DATA_CODING_UCS2) {
581        int dataSize = TextCoder::Instance().Ucs2ToUtf8(
582            buff, MAX_MSG_TEXT_LEN, reinterpret_cast<uint8_t *>(smsUserData_.data), smsUserData_.length);
583        visibleMessageBody_.insert(0, reinterpret_cast<char *>(buff), dataSize);
584    } else if (codingScheme_ == DATA_CODING_8BIT) {
585        visibleMessageBody_.insert(0, static_cast<char *>(smsUserData_.data), smsUserData_.length);
586    }
587    rawUserData_.insert(0, static_cast<char *>(smsUserData_.data), smsUserData_.length);
588    rawWapPushUserData_.insert(0, smsWapPushUserData_.ud, smsWapPushUserData_.udl);
589}
590
591void GsmSmsMessage::SetFullText(const std::string &text)
592{
593    fullText_ = text;
594}
595
596void GsmSmsMessage::SetDestAddress(const std::string &address)
597{
598    destAddress_ = address;
599}
600
601void GsmSmsMessage::SetDestPort(uint32_t port)
602{
603    destPort_ = port;
604}
605
606std::string GsmSmsMessage::GetFullText() const
607{
608    return fullText_;
609}
610
611std::string GsmSmsMessage::GetReplyAddress() const
612{
613    return replyAddress_;
614}
615
616std::string GsmSmsMessage::GetDestAddress() const
617{
618    return destAddress_;
619}
620
621uint16_t GsmSmsMessage::GetDestPort()
622{
623    std::shared_ptr<SmsAppPortAddr> portAddress = GetPortAddress();
624    if (portAddress == nullptr) {
625        TELEPHONY_LOGE("PortAddress is null!");
626        return DEFAULT_PORT;
627    }
628    destPort_ = static_cast<uint16_t>(portAddress->destPort);
629    return destPort_;
630}
631
632bool GsmSmsMessage::GetIsSmsText() const
633{
634    return bSmsText_;
635}
636
637bool GsmSmsMessage::GetGsm() const
638{
639    return true;
640}
641
642bool GsmSmsMessage::GetIsTypeZeroInd() const
643{
644    return (GetProtocolId() == 0x40);
645}
646
647bool GsmSmsMessage::GetIsSIMDataTypeDownload() const
648{
649    int protocolId = GetProtocolId();
650    return GetMessageClass() == SMS_SIM_MESSAGE && (protocolId == 0x7f || protocolId == 0x7c);
651}
652
653void GsmSmsMessage::ConvertMsgTimeStamp(const struct SmsTimeStamp &times)
654{
655    if (times.format == SMS_TIME_ABSOLUTE) {
656        scTimestamp_ = SmsCommonUtils::ConvertTime(times.time.absolute);
657    } else {
658        scTimestamp_ = time(nullptr);
659    }
660}
661
662// from 3GPP TS 23.040 V5.1.0 9.2.3.24.2 Special SMS Message Indication
663bool GsmSmsMessage::IsSpecialMessage() const
664{
665    bool result = false;
666    if (GetIsTypeZeroInd()) {
667        TELEPHONY_LOGI("GsmSmsMessage:: IsTypeZeroInd");
668        result = true;
669    }
670    // 9.2.3.9 TP Protocol Identifier (TP PID)
671    if (GetIsSIMDataTypeDownload()) {
672        TELEPHONY_LOGI("GsmSmsMessage:: GetIsSIMDataTypeDownload");
673        result = true;
674    }
675    if (IsMwiSet() || IsMwiClear()) {
676        TELEPHONY_LOGI("GsmSmsMessage::Mwi Message");
677        result = true;
678    }
679    return result;
680}
681
682void GsmSmsMessage::SetSmsCodingNationalType(SmsCodingNationalType smsCodingNationalType)
683{
684    smsCodingNationalType_ = smsCodingNationalType;
685}
686
687int GsmSmsMessage::DecodeMessage(uint8_t *decodeData, unsigned int len, DataCodingScheme &codingType,
688    const std::string &msgText, bool &bAbnormal, MSG_LANGUAGE_ID_T &langId)
689{
690    int decodeLen = 0;
691    int dataLen = static_cast<int>(msgText.length());
692    const unsigned int maxDecodeLen = len;
693    const uint8_t *pMsgText = reinterpret_cast<const uint8_t *>(msgText.c_str());
694
695    if (msgText.empty()) {
696        TELEPHONY_LOGE("msgText empty.");
697        return decodeLen;
698    }
699
700    switch (codingType) {
701        case DATA_CODING_7BIT: {
702            decodeLen = TextCoder::Instance().Utf8ToGsm7bit(
703                decodeData, maxDecodeLen, const_cast<uint8_t *>(pMsgText), dataLen, langId);
704            break;
705        }
706        case DATA_CODING_8BIT: {
707            if (static_cast<unsigned int>(dataLen) > maxDecodeLen) {
708                TELEPHONY_LOGE("DecodeMessage data length invalid.");
709                return decodeLen;
710            }
711            if (memcpy_s(decodeData, maxDecodeLen, pMsgText, dataLen) != EOK) {
712                TELEPHONY_LOGE("SplitMessage SMS_CHARSET_8BIT memcpy_s error!");
713                return decodeLen;
714            }
715            decodeLen = dataLen;
716            break;
717        }
718        case DATA_CODING_UCS2: {
719            decodeLen = TextCoder::Instance().Utf8ToUcs2(decodeData, maxDecodeLen, pMsgText, dataLen);
720            break;
721        }
722        case DATA_CODING_AUTO:
723        default: {
724            DataCodingScheme encodeType = DATA_CODING_AUTO;
725            decodeLen = TextCoder::Instance().GsmUtf8ToAuto(decodeData, maxDecodeLen, pMsgText, dataLen,
726                encodeType, smsCodingNationalType_, langId);
727            codingType = encodeType;
728            break;
729        }
730    }
731    TELEPHONY_LOGI("DecodeMessage, message coding type is %{public}d", codingType);
732    return decodeLen;
733}
734} // namespace Telephony
735} // namespace OHOS
736