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