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 
23 namespace OHOS {
24 namespace Telephony {
25 using namespace std;
26 static constexpr uint16_t DEFAULT_PORT = -1;
27 static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
28 static constexpr uint8_t MAX_SMSC_LEN = 20;
29 static constexpr uint16_t MAX_TPDU_DATA_LEN = 255;
30 static constexpr uint16_t TAPI_TEXT_SIZE_MAX = 520;
31 
CalcReplyEncodeAddress(const std::string & replyAddress)32 uint8_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 
SetSmsTpduDestAddress(std::shared_ptr<struct SmsTpdu> & tPdu,const std::string & desAddr)55 int 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 
SetHeaderLang(int index,const DataCodingScheme codingType,const MSG_LANGUAGE_ID_T langId)91 int 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 
SetHeaderConcat(int index,const SmsConcat & concat)112 int 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 
SetHeaderReply(int index)140 int 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 
CreateDefaultSubmit(bool bStatusReport,const DataCodingScheme codingScheme)184 void 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 
CreateDefaultSubmitSmsTpdu(const std::string & dest,const std::string & sc,const std::string & text,bool bStatusReport,const DataCodingScheme codingScheme=DATA_CODING_7BIT)205 std::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 
CreateDataSubmitSmsTpdu(const std::string & desAddr,const std::string & scAddr,int32_t port,const uint8_t * data,uint32_t dataLen,uint8_t msgRef8bit,DataCodingScheme codingType,bool bStatusReport)217 std::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 
GetSubmitEncodeInfo(const std::string & sc,bool bMore)265 std::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 
GetSubmitEncodeInfoPartData(uint8_t * encodeSmscAddr,uint8_t encodeSmscLen,bool bMore)300 std::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 
CreateDeliverSmsTpdu()337 std::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 
CreateDeliverReportSmsTpdu()349 std::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 
CreateStatusReportSmsTpdu()362 std::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 
CreateMessage(const std::string & pdu)373 std::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 
PduAnalysis(const string & pdu)394 bool 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 
PduAnalysisMsg()430 bool 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 
AnalysisMsgDeliver(const SmsDeliver & deliver)451 void 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 
AnalysisMsgStatusReport(const SmsStatusReport & statusRep)465 void 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 
AnalysisMsgSubmit(const SmsSubmit & submit)478 void 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 
ConvertMessageDcs()490 void 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 
ConvertUserData()527 void 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 
ConvertUserPartData()563 void 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 
SetFullText(const std::string & text)591 void GsmSmsMessage::SetFullText(const std::string &text)
592 {
593     fullText_ = text;
594 }
595 
SetDestAddress(const std::string & address)596 void GsmSmsMessage::SetDestAddress(const std::string &address)
597 {
598     destAddress_ = address;
599 }
600 
SetDestPort(uint32_t port)601 void GsmSmsMessage::SetDestPort(uint32_t port)
602 {
603     destPort_ = port;
604 }
605 
GetFullText() const606 std::string GsmSmsMessage::GetFullText() const
607 {
608     return fullText_;
609 }
610 
GetReplyAddress() const611 std::string GsmSmsMessage::GetReplyAddress() const
612 {
613     return replyAddress_;
614 }
615 
GetDestAddress() const616 std::string GsmSmsMessage::GetDestAddress() const
617 {
618     return destAddress_;
619 }
620 
GetDestPort()621 uint16_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 
GetIsSmsText() const632 bool GsmSmsMessage::GetIsSmsText() const
633 {
634     return bSmsText_;
635 }
636 
GetGsm() const637 bool GsmSmsMessage::GetGsm() const
638 {
639     return true;
640 }
641 
GetIsTypeZeroInd() const642 bool GsmSmsMessage::GetIsTypeZeroInd() const
643 {
644     return (GetProtocolId() == 0x40);
645 }
646 
GetIsSIMDataTypeDownload() const647 bool GsmSmsMessage::GetIsSIMDataTypeDownload() const
648 {
649     int protocolId = GetProtocolId();
650     return GetMessageClass() == SMS_SIM_MESSAGE && (protocolId == 0x7f || protocolId == 0x7c);
651 }
652 
ConvertMsgTimeStamp(const struct SmsTimeStamp & times)653 void 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
IsSpecialMessage() const663 bool 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 
SetSmsCodingNationalType(SmsCodingNationalType smsCodingNationalType)682 void GsmSmsMessage::SetSmsCodingNationalType(SmsCodingNationalType smsCodingNationalType)
683 {
684     smsCodingNationalType_ = smsCodingNationalType;
685 }
686 
DecodeMessage(uint8_t * decodeData,unsigned int len,DataCodingScheme & codingType,const std::string & msgText,bool & bAbnormal,MSG_LANGUAGE_ID_T & langId)687 int 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