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