• 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 "sms_base_message.h"
17 
18 #include "securec.h"
19 #include "sms_mms_errors.h"
20 #include "sms_service_manager_client.h"
21 #include "telephony_errors.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 uint8_t PID_87 = 0xc0;
29 static constexpr uint8_t PID_7 = 0x40;
30 static constexpr uint8_t PID_10_LOW = 0x3f;
31 static constexpr int16_t WAP_PUSH_PORT = 2948;
32 static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
33 static constexpr uint8_t MAX_UCS2_DATA_LEN = 140;
34 static constexpr uint8_t BYTE_BITS = 8;
35 static constexpr uint8_t MAX_ADD_PARAM_LEN = 12;
36 static constexpr uint8_t GSM_BEAR_DATA_LEN = 140;
37 static constexpr uint8_t CHARSET_7BIT_BITS = 7;
38 static constexpr uint16_t TAPI_TEXT_SIZE_MAX = 520;
39 const std::string CT_SMSC = "10659401";
40 
GetSmscAddr() const41 string SmsBaseMessage::GetSmscAddr() const
42 {
43     return scAddress_;
44 }
45 
SetSmscAddr(const string & address)46 void SmsBaseMessage::SetSmscAddr(const string &address)
47 {
48     scAddress_ = address;
49 }
50 
GetOriginatingAddress() const51 string SmsBaseMessage::GetOriginatingAddress() const
52 {
53     return originatingAddress_;
54 }
55 
GetVisibleOriginatingAddress() const56 string SmsBaseMessage::GetVisibleOriginatingAddress() const
57 {
58     return originatingAddress_;
59 }
60 
GetMessageClass() const61 enum SmsMessageClass SmsBaseMessage::GetMessageClass() const
62 {
63     return msgClass_;
64 }
65 
GetVisibleMessageBody() const66 string SmsBaseMessage::GetVisibleMessageBody() const
67 {
68     return visibleMessageBody_;
69 }
70 
GetRawPdu() const71 std::vector<uint8_t> SmsBaseMessage::GetRawPdu() const
72 {
73     return rawPdu_;
74 }
75 
GetRawUserData() const76 std::string SmsBaseMessage::GetRawUserData() const
77 {
78     return rawUserData_;
79 }
80 
GetRawWapPushUserData() const81 std::string SmsBaseMessage::GetRawWapPushUserData() const
82 {
83     return rawWapPushUserData_;
84 }
85 
GetScTimestamp() const86 int64_t SmsBaseMessage::GetScTimestamp() const
87 {
88     return scTimestamp_;
89 }
90 
91 // 3GPP TS 23.040 V5.1.0 9.2.3.9 TP Protocol Identifier (TP PID)
IsReplaceMessage()92 bool SmsBaseMessage::IsReplaceMessage()
93 {
94     uint8_t temp = static_cast<uint8_t>(protocolId_);
95     uint8_t tempPid = temp & PID_10_LOW;
96     bReplaceMessage_ = ((temp & PID_87) == PID_7) && (tempPid > 0) && (tempPid < MAX_REPLY_PID);
97     return bReplaceMessage_;
98 }
99 
100 // Message Waiting Indication Status storage on the USIM
IsCphsMwi() const101 bool SmsBaseMessage::IsCphsMwi() const
102 {
103     return bCphsMwi_;
104 }
105 
106 // 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
IsMwiClear() const107 bool SmsBaseMessage::IsMwiClear() const
108 {
109     return bMwiClear_;
110 }
111 
112 // 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
IsMwiSet() const113 bool SmsBaseMessage::IsMwiSet() const
114 {
115     return bMwiSet_;
116 }
117 
118 // 3GPP TS 23.040 V5.1.0 3.2.6 Messages Waiting
IsMwiNotStore() const119 bool SmsBaseMessage::IsMwiNotStore() const
120 {
121     return bMwiNotStore_;
122 }
123 
GetStatus() const124 int SmsBaseMessage::GetStatus() const
125 {
126     return status_;
127 }
128 
IsSmsStatusReportMessage() const129 bool SmsBaseMessage::IsSmsStatusReportMessage() const
130 {
131     return bStatusReportMessage_;
132 }
133 
HasReplyPath() const134 bool SmsBaseMessage::HasReplyPath() const
135 {
136     return hasReplyPath_;
137 }
138 
GetProtocolId() const139 int SmsBaseMessage::GetProtocolId() const
140 {
141     return protocolId_;
142 }
143 
GetConcatMsg()144 std::shared_ptr<SmsConcat> SmsBaseMessage::GetConcatMsg()
145 {
146     smsConcat_ = nullptr;
147     for (int i = 0; i < smsUserData_.headerCnt; i++) {
148         if (smsUserData_.header[i].udhType == UDH_CONCAT_8BIT) {
149             smsConcat_ = std::make_shared<SmsConcat>();
150             if (smsConcat_ == nullptr) {
151                 TELEPHONY_LOGE("smsConcat is nullptr.");
152                 break;
153             }
154             smsConcat_->is8Bits = true;
155             smsConcat_->totalSeg = smsUserData_.header[i].udh.concat8bit.totalSeg;
156             smsConcat_->seqNum = smsUserData_.header[i].udh.concat8bit.seqNum;
157             smsConcat_->msgRef = smsUserData_.header[i].udh.concat8bit.msgRef;
158             break;
159         } else if (smsUserData_.header[i].udhType == UDH_CONCAT_16BIT) {
160             smsConcat_ = std::make_shared<SmsConcat>();
161             if (smsConcat_ == nullptr) {
162                 TELEPHONY_LOGE("smsConcat is nullptr.");
163                 break;
164             }
165             smsConcat_->is8Bits = false;
166             smsConcat_->totalSeg = smsUserData_.header[i].udh.concat16bit.totalSeg;
167             smsConcat_->seqNum = smsUserData_.header[i].udh.concat16bit.seqNum;
168             smsConcat_->msgRef = smsUserData_.header[i].udh.concat16bit.msgRef;
169             break;
170         }
171     }
172     return smsConcat_;
173 }
174 
GetPortAddress()175 std::shared_ptr<SmsAppPortAddr> SmsBaseMessage::GetPortAddress()
176 {
177     portAddress_ = nullptr;
178     for (int i = 0; i < smsUserData_.headerCnt; i++) {
179         if (smsUserData_.header[i].udhType == UDH_APP_PORT_8BIT) {
180             portAddress_ = std::make_shared<SmsAppPortAddr>();
181             if (portAddress_ == nullptr) {
182                 TELEPHONY_LOGE("portAddress_ is nullptr.");
183                 break;
184             }
185             portAddress_->is8Bits = true;
186             portAddress_->destPort = smsUserData_.header[i].udh.appPort8bit.destPort;
187             portAddress_->originPort = smsUserData_.header[i].udh.appPort8bit.originPort;
188             break;
189         } else if (smsUserData_.header[i].udhType == UDH_APP_PORT_16BIT) {
190             portAddress_ = std::make_shared<SmsAppPortAddr>();
191             if (portAddress_ == nullptr) {
192                 TELEPHONY_LOGE("portAddress_ is nullptr.");
193                 break;
194             }
195             portAddress_->is8Bits = false;
196             portAddress_->destPort = smsUserData_.header[i].udh.appPort16bit.destPort;
197             portAddress_->originPort = smsUserData_.header[i].udh.appPort16bit.originPort;
198             break;
199         }
200     }
201     return portAddress_;
202 }
203 
GetSpecialSmsInd()204 std::shared_ptr<SpecialSmsIndication> SmsBaseMessage::GetSpecialSmsInd()
205 {
206     specialSmsInd_ = nullptr;
207     for (int i = 0; i < smsUserData_.headerCnt; i++) {
208         if (smsUserData_.header[i].udhType == UDH_SPECIAL_SMS) {
209             specialSmsInd_ = std::make_shared<SpecialSmsIndication>();
210             if (specialSmsInd_ == nullptr) {
211                 TELEPHONY_LOGE("specialSmsInd_ is nullptr.");
212                 break;
213             }
214             specialSmsInd_->bStore = smsUserData_.header[i].udh.specialInd.bStore;
215             specialSmsInd_->msgInd = smsUserData_.header[i].udh.specialInd.msgInd;
216             specialSmsInd_->waitMsgNum = smsUserData_.header[i].udh.specialInd.waitMsgNum;
217             break;
218         }
219     }
220     return specialSmsInd_;
221 }
222 
IsConcatMsg()223 bool SmsBaseMessage::IsConcatMsg()
224 {
225     return (GetConcatMsg() == nullptr) ? false : true;
226 }
227 
IsWapPushMsg()228 bool SmsBaseMessage::IsWapPushMsg()
229 {
230     std::shared_ptr<SmsAppPortAddr> portAddress = GetPortAddress();
231     if (portAddress != nullptr && !portAddress->is8Bits) {
232         return portAddress->destPort == WAP_PUSH_PORT;
233     }
234     return false;
235 }
236 
ConvertMessageClass(enum SmsMessageClass msgClass)237 void SmsBaseMessage::ConvertMessageClass(enum SmsMessageClass msgClass)
238 {
239     switch (msgClass) {
240         case SMS_SIM_MESSAGE:
241             msgClass_ = SmsMessageClass::SMS_SIM_MESSAGE;
242             break;
243         case SMS_INSTANT_MESSAGE:
244             msgClass_ = SmsMessageClass::SMS_INSTANT_MESSAGE;
245             break;
246         case SMS_OPTIONAL_MESSAGE:
247             msgClass_ = SmsMessageClass::SMS_OPTIONAL_MESSAGE;
248             break;
249         case SMS_FORWARD_MESSAGE:
250             msgClass_ = SmsMessageClass::SMS_FORWARD_MESSAGE;
251             break;
252         default:
253             msgClass_ = SmsMessageClass::SMS_CLASS_UNKNOWN;
254             break;
255     }
256 }
257 
GetMsgRef()258 int SmsBaseMessage::GetMsgRef()
259 {
260     return msgRef_;
261 }
262 
GetSegmentSize(DataCodingScheme & codingScheme,int dataLen,bool bPortNum,MSG_LANGUAGE_ID_T & langId,int replyAddrLen) const263 int SmsBaseMessage::GetSegmentSize(
264     DataCodingScheme &codingScheme, int dataLen, bool bPortNum, MSG_LANGUAGE_ID_T &langId, int replyAddrLen) const
265 {
266     const int headerLen = 1;
267     const int concat = 5;
268     const int port = 6;
269     const int lang = 3;
270     const int reply = 2;
271     int headerSize = 0;
272     int segSize = 0;
273     int maxSize = 0;
274     if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
275         maxSize = MAX_GSM_7BIT_DATA_LEN;
276     } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
277         maxSize = MAX_UCS2_DATA_LEN;
278     }
279 
280     if (bPortNum == true) {
281         headerSize += port;
282     }
283 
284     if (langId != MSG_ID_RESERVED_LANG) {
285         headerSize += lang;
286     }
287 
288     if (replyAddrLen > 0) {
289         headerSize += reply;
290         headerSize += replyAddrLen;
291     }
292 
293     if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
294         if ((dataLen + headerSize) > maxSize) {
295             segSize =
296                 ((GSM_BEAR_DATA_LEN * BYTE_BITS) - ((headerLen + concat + headerSize) * BYTE_BITS)) / CHARSET_7BIT_BITS;
297         } else {
298             segSize = dataLen;
299         }
300     } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
301         if ((dataLen + headerSize) > maxSize) {
302             segSize = GSM_BEAR_DATA_LEN - (headerLen + concat + headerSize);
303         } else {
304             segSize = dataLen;
305         }
306     }
307 
308     return segSize;
309 }
310 
GetMaxSegmentSize(DataCodingScheme & codingScheme,int dataLen,bool bPortNum,MSG_LANGUAGE_ID_T & langId,int replyAddrLen) const311 int SmsBaseMessage::GetMaxSegmentSize(
312     DataCodingScheme &codingScheme, int dataLen, bool bPortNum, MSG_LANGUAGE_ID_T &langId, int replyAddrLen) const
313 {
314     const int headerLen = 1;
315     const int concat = 5;
316     const int port = 6;
317     const int lang = 3;
318     const int reply = 2;
319     int headerSize = 0;
320     int segSize = 0;
321     int maxSize = 0;
322     if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
323         maxSize = MAX_GSM_7BIT_DATA_LEN;
324     } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
325         maxSize = MAX_UCS2_DATA_LEN;
326     }
327     if (bPortNum) {
328         headerSize += port;
329     }
330     if (langId != MSG_ID_RESERVED_LANG) {
331         headerSize += lang;
332     }
333     if (replyAddrLen > 0) {
334         headerSize += reply;
335         headerSize += replyAddrLen;
336     }
337     if (codingScheme == DATA_CODING_7BIT || codingScheme == DATA_CODING_ASCII7BIT) {
338         if ((dataLen + headerSize) > maxSize) {
339             segSize =
340                 ((GSM_BEAR_DATA_LEN * BYTE_BITS) - ((headerLen + concat + headerSize) * BYTE_BITS)) / CHARSET_7BIT_BITS;
341         } else {
342             segSize = maxSize - headerSize;
343         }
344     } else if (codingScheme == DATA_CODING_8BIT || codingScheme == DATA_CODING_UCS2) {
345         if ((dataLen + headerSize) > maxSize) {
346             segSize = GSM_BEAR_DATA_LEN - (headerLen + concat + headerSize);
347         } else {
348             segSize = maxSize - headerSize;
349         }
350     }
351     return segSize;
352 }
353 
ConvertSpiltToUtf8(SplitInfo & split,const DataCodingScheme & codingType)354 void SmsBaseMessage::ConvertSpiltToUtf8(SplitInfo &split, const DataCodingScheme &codingType)
355 {
356     if (split.encodeData.size() <= 0) {
357         TELEPHONY_LOGE("data is null");
358         return;
359     }
360 
361     int dataSize = 0;
362     uint8_t buff[MAX_MSG_TEXT_LEN + 1] = { 0 };
363     switch (codingType) {
364         case DATA_CODING_7BIT: {
365             MsgLangInfo langInfo = {
366                 0,
367             };
368             langInfo.bSingleShift = false;
369             langInfo.bLockingShift = false;
370             dataSize = TextCoder::Instance().Gsm7bitToUtf8(
371                 buff, MAX_MSG_TEXT_LEN, split.encodeData.data(), split.encodeData.size(), langInfo);
372             break;
373         }
374         case DATA_CODING_UCS2: {
375             dataSize = TextCoder::Instance().Ucs2ToUtf8(
376                 buff, MAX_MSG_TEXT_LEN, split.encodeData.data(), split.encodeData.size());
377             break;
378         }
379         default: {
380             if (split.encodeData.size() > sizeof(buff)) {
381                 TELEPHONY_LOGE("AnalsisDeliverMsg data length invalid.");
382                 return;
383             }
384             if (memcpy_s(buff, sizeof(buff), split.encodeData.data(), split.encodeData.size()) != EOK) {
385                 TELEPHONY_LOGE("AnalsisDeliverMsg memcpy_s fail.");
386                 return;
387             }
388             dataSize = static_cast<int>(split.encodeData.size());
389             buff[dataSize] = '\0';
390             break;
391         }
392     }
393 
394     split.text.insert(0, reinterpret_cast<char *>(buff), dataSize);
395     TELEPHONY_LOGI("split text");
396 }
397 
SplitMessage(std::vector<struct SplitInfo> & splitResult,const std::string & text,bool force7BitCode,DataCodingScheme & codingType,bool bPortNum,const std::string & desAddr)398 void SmsBaseMessage::SplitMessage(std::vector<struct SplitInfo> &splitResult, const std::string &text,
399     bool force7BitCode, DataCodingScheme &codingType, bool bPortNum, const std::string &desAddr)
400 {
401     std::string msgText(text);
402     uint8_t decodeData[(MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1];
403     if (memset_s(decodeData, sizeof(decodeData), 0x00, sizeof(decodeData)) != EOK) {
404         TELEPHONY_LOGE("SplitMessage memset_s error!");
405         return;
406     }
407 
408     int encodeLen = 0;
409     bool bAbnormal = false;
410     MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
411     codingType = force7BitCode ? DATA_CODING_7BIT : DATA_CODING_AUTO;
412     if (CT_SMSC.compare(desAddr) == 0) {
413         codingType = DATA_CODING_8BIT;
414     }
415 
416     encodeLen = DecodeMessage(decodeData, sizeof(decodeData), codingType, msgText, bAbnormal, langId);
417     if (encodeLen <= 0) {
418         TELEPHONY_LOGE("encodeLen Less than or equal to 0");
419         return;
420     }
421 
422     int index = 0;
423     int segSize = 0;
424     int segCount = 0;
425     segSize = GetSegmentSize(codingType, encodeLen, bPortNum, langId, MAX_ADD_PARAM_LEN);
426     if (segSize > 0) {
427         segCount = ceil((double)encodeLen / (double)segSize);
428     }
429 
430     for (int i = 0; i < segCount; i++) {
431         int userDataLen = 0;
432         struct SplitInfo splitInfo;
433         splitInfo.langId = langId;
434         splitInfo.encodeType = codingType;
435         uint8_t textData[TAPI_TEXT_SIZE_MAX + 1];
436         (void)memset_s(textData, sizeof(textData), 0x00, sizeof(textData));
437         if ((i + 1) == segCount) {
438             userDataLen = encodeLen - (i * segSize);
439         } else {
440             userDataLen = segSize;
441         }
442         splitInfo.encodeData = std::vector<uint8_t>(&decodeData[index], &decodeData[index] + userDataLen);
443         ConvertSpiltToUtf8(splitInfo, codingType);
444         splitResult.push_back(splitInfo);
445         index += segSize;
446     }
447 }
448 
GetSmsSegmentsInfo(const std::string & message,bool force7BitCode,LengthInfo & lenInfo)449 int32_t SmsBaseMessage::GetSmsSegmentsInfo(const std::string &message, bool force7BitCode, LengthInfo &lenInfo)
450 {
451     uint8_t decodeData[(MAX_GSM_7BIT_DATA_LEN * MAX_SEGMENT_NUM) + 1];
452     if (memset_s(decodeData, sizeof(decodeData), 0x00, sizeof(decodeData)) != EOK) {
453         TELEPHONY_LOGE("SplitMessage memset_s error!");
454         return TELEPHONY_ERR_MEMSET_FAIL;
455     }
456     const uint8_t smsEncodingUnkown = 0;
457     const uint8_t smsEncoding7Bit = 1;
458     const uint8_t smsEncoding8Bit = 2;
459     const uint8_t smsEncoding16Bit = 3;
460     int encodeLen = 0;
461     bool bAbnormal = false;
462     MSG_LANGUAGE_ID_T langId = MSG_ID_RESERVED_LANG;
463     DataCodingScheme codingType = force7BitCode ? DATA_CODING_7BIT : DATA_CODING_AUTO;
464     encodeLen = DecodeMessage(decodeData, sizeof(decodeData), codingType, message, bAbnormal, langId);
465     if (encodeLen <= 0) {
466         TELEPHONY_LOGE("encodeLen Less than or equal to 0");
467         return SMS_MMS_DECODE_DATA_EMPTY;
468     }
469     int segSize = GetMaxSegmentSize(codingType, encodeLen, false, langId, MAX_ADD_PARAM_LEN);
470     TELEPHONY_LOGI("segSize = %{public}d", segSize);
471     lenInfo.msgEncodeCount = static_cast<uint16_t>(encodeLen);
472     if (codingType == DATA_CODING_7BIT || codingType == DATA_CODING_ASCII7BIT) {
473         lenInfo.dcs = smsEncoding7Bit;
474     } else if (codingType == DATA_CODING_UCS2) {
475         lenInfo.dcs = smsEncoding16Bit;
476     } else if (codingType == DATA_CODING_8BIT) {
477         lenInfo.dcs = smsEncoding8Bit;
478     } else {
479         lenInfo.dcs = smsEncodingUnkown;
480     }
481     if (lenInfo.dcs == smsEncoding16Bit) {
482         lenInfo.msgEncodeCount = lenInfo.msgEncodeCount / 2;
483         segSize = segSize / 2;
484     }
485     if (segSize != 0) {
486         lenInfo.msgRemainCount = static_cast<uint8_t>(((segSize - (lenInfo.msgEncodeCount % segSize))) % segSize);
487         lenInfo.msgSegCount = ceil(static_cast<double>(lenInfo.msgEncodeCount) / static_cast<double>(segSize));
488     }
489     return TELEPHONY_ERR_SUCCESS;
490 }
491 
GetIndexOnSim() const492 int32_t SmsBaseMessage::GetIndexOnSim() const
493 {
494     return indexOnSim_;
495 }
496 
SetIndexOnSim(int32_t index)497 void SmsBaseMessage::SetIndexOnSim(int32_t index)
498 {
499     indexOnSim_ = index;
500 }
501 } // namespace Telephony
502 } // namespace OHOS
503