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