1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sms_cb_message.h"
18
19 #include <string>
20
21 #include "cdma_sms_types.h"
22 #include "msg_text_convert.h"
23 #include "securec.h"
24 #include "sms_common_utils.h"
25 #include "string_utils.h"
26 #include "telephony_log_wrapper.h"
27
28 namespace OHOS {
29 namespace Telephony {
operator ==(const SmsCbMessage & other) const30 bool SmsCbMessage::operator==(const SmsCbMessage &other) const
31 {
32 if (cbHeader_ == nullptr || other.cbHeader_ == nullptr) {
33 TELEPHONY_LOGE("cbHeader_ is nullptr.");
34 return false;
35 }
36 return cbHeader_->serialNum.geoScope == other.cbHeader_->serialNum.geoScope &&
37 cbHeader_->serialNum.msgCode == other.cbHeader_->serialNum.msgCode &&
38 cbHeader_->msgId == other.cbHeader_->msgId;
39 }
40
CreateCbMessage(const std::string & pdu)41 std::shared_ptr<SmsCbMessage> SmsCbMessage::CreateCbMessage(const std::string &pdu)
42 {
43 bool result = false;
44 std::shared_ptr<SmsCbMessage> message = std::make_shared<SmsCbMessage>();
45 if (message != nullptr) {
46 result = message->PduAnalysis(StringUtils::HexToByteVector(pdu));
47 }
48 return (result ? message : nullptr);
49 }
50
CreateCbMessage(const std::vector<unsigned char> & pdu)51 std::shared_ptr<SmsCbMessage> SmsCbMessage::CreateCbMessage(const std::vector<unsigned char> &pdu)
52 {
53 bool result = false;
54 std::shared_ptr<SmsCbMessage> message = std::make_shared<SmsCbMessage>();
55 if (message != nullptr) {
56 result = message->PduAnalysis(pdu);
57 }
58 return (result ? message : nullptr);
59 }
60
GetCbHeader() const61 std::shared_ptr<SmsCbMessage::SmsCbMessageHeader> SmsCbMessage::GetCbHeader() const
62 {
63 return cbHeader_;
64 }
65
GetCbMessageRaw() const66 std::string SmsCbMessage::GetCbMessageRaw() const
67 {
68 return messageRaw_;
69 }
70
IsSinglePageMsg() const71 bool SmsCbMessage::IsSinglePageMsg() const
72 {
73 return cbHeader_ != nullptr && (cbHeader_->totalPages == 1);
74 }
75
76 /**
77 * @brief PduAnalysis Cell Broadcast Message
78 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.1.1 9.1.2 section Protocols and Protocol Architecture
79 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.3 Parameters
80 * @param pdu [in]
81 * @return true [out]
82 * @return false [out]
83 */
PduAnalysis(const std::vector<unsigned char> & pdu)84 bool SmsCbMessage::PduAnalysis(const std::vector<unsigned char> &pdu)
85 {
86 cbHeader_ = std::make_shared<SmsCbMessage::SmsCbMessageHeader>();
87 if (cbHeader_ == nullptr) {
88 TELEPHONY_LOGE("cbHeader_ is nullptr.");
89 return false;
90 }
91 int offset = 0;
92 // from 3GPP TS 23.041 V4.1.0 (2001-06) 9.1.1 9.1.2 section Protocols and Protocol Architecture
93 if (pdu.size() <= (MAX_CBMSG_PAGE_SIZE + SMS_CB_HEADER_SIZE)) {
94 cbHeader_->cbMsgType = SMS_CBMSG_TYPE_CBS;
95 cbHeader_->cbNetType = SMS_NETTEXT_CB_MSG_GSM;
96 offset = Decode2gHeader(pdu);
97 } else {
98 cbHeader_->cbMsgType = pdu[offset];
99 cbHeader_->cbNetType = SMS_NETTEXT_CB_MSG_UMTS;
100 offset = Decode3gHeader(pdu);
101 }
102 if (offset == 0 || pdu.size() <= (std::size_t)offset) {
103 TELEPHONY_LOGE("offset out of bound.");
104 return false;
105 }
106 TELEPHONY_LOGI("header offse = %{public}d", offset);
107 std::vector<unsigned char> bodyPdu(pdu.begin() + offset, pdu.end());
108 if (cbHeader_->bEtwsMessage && cbHeader_->cbEtwsType == SMS_NETTEXT_ETWS_PRIMARY) {
109 DecodeEtwsMsg(bodyPdu);
110 return true;
111 }
112 switch (cbHeader_->cbNetType) {
113 case SMS_NETTEXT_CB_MSG_GSM:
114 Decode2gCbMsg(bodyPdu);
115 break;
116 case SMS_NETTEXT_CB_MSG_UMTS:
117 Decode3gCbMsg(bodyPdu);
118 break;
119 default:
120 break;
121 }
122 return true;
123 }
124
125 /**
126 * @brief Decode2gHeader GSM Cell Broadcast Message Header
127 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4 Message Format on the Radio Network – MS/UE Interface
128 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.1.2 Message Parameter
129 * @param pdu [in]
130 * @return int [out]
131 */
Decode2gHeader(const std::vector<unsigned char> & pdu)132 int SmsCbMessage::Decode2gHeader(const std::vector<unsigned char> &pdu)
133 {
134 int offset = 0;
135 unsigned char temp;
136 if (pdu.size() < SMS_CB_HEADER_SIZE) {
137 TELEPHONY_LOGE("pdu size less than min.");
138 return offset;
139 }
140 if (cbHeader_ == nullptr) {
141 TELEPHONY_LOGE("cbHeader_ is nullptr.");
142 return offset;
143 }
144 cbHeader_->bEtwsMessage = false;
145 temp = pdu[offset++];
146 cbHeader_->serialNum.geoScope = (temp & 0xC0) >> 0x06;
147 cbHeader_->serialNum.msgCode = (temp & 0x3F) << 0x04;
148
149 temp = pdu[offset++];
150 cbHeader_->serialNum.msgCode |= (temp & 0xF0) >> 0x04;
151 cbHeader_->serialNum.updateNum = temp & 0x0F;
152
153 temp = pdu[offset++];
154 cbHeader_->msgId = (temp << 0x08) | pdu[offset++];
155 if ((cbHeader_->msgId & 0xFFF8) == SMS_ETWS_BASE_MASK && pdu.size() <= MAX_ETWS_SIZE) {
156 cbHeader_->cbEtwsType = SMS_NETTEXT_ETWS_PRIMARY;
157 cbHeader_->bEtwsMessage = true;
158 temp = pdu[offset++];
159 cbHeader_->warningType = (temp << 0x08) | pdu[offset++];
160 } else {
161 unsigned char dcs = pdu[offset++];
162 temp = pdu[offset++];
163 cbHeader_->totalPages = temp & 0x0f;
164 cbHeader_->page = (temp & 0xF0) >> 0x04;
165
166 unsigned short iosTemp = pdu[offset++];
167 iosTemp |= (pdu[offset++] << BYTE_BIT);
168 DecodeCbMsgDCS(dcs, iosTemp, cbHeader_->dcs);
169 cbHeader_->langType = cbHeader_->dcs.langType;
170 cbHeader_->recvTime = static_cast<time_t>(GetRecvTime());
171 if (cbHeader_->totalPages > MAX_CBMSG_PAGE_NUM) {
172 TELEPHONY_LOGE("CB Page Count is over MAX[%{public}d]", cbHeader_->totalPages);
173 offset = 0;
174 }
175 if ((cbHeader_->msgId & 0xFFF8) == SMS_ETWS_BASE_MASK) {
176 cbHeader_->bEtwsMessage = true;
177 cbHeader_->cbEtwsType = SMS_NETTEXT_ETWS_SECONDARY_GSM;
178 cbHeader_->warningType = cbHeader_->msgId - SMS_ETWS_BASE_MASK;
179 }
180 offset -= 0x02;
181 }
182 return offset;
183 }
184
185 /**
186 * @brief Decode3gHeader UMTS Cell Broadcast Message Header
187 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.2.1 General Description
188 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.2.2 Message Parameter
189 * @param pdu [in]
190 * @return int [out]
191 */
Decode3gHeader(const std::vector<unsigned char> & pdu)192 int SmsCbMessage::Decode3gHeader(const std::vector<unsigned char> &pdu)
193 {
194 int offset = 0;
195 unsigned char temp;
196 if (pdu.size() < SMS_CB_HEADER_SIZE) {
197 TELEPHONY_LOGE("pdu size less than min.");
198 return offset;
199 }
200 if (cbHeader_ == nullptr) {
201 TELEPHONY_LOGE("cbHeader_ is nullptr.");
202 return offset;
203 }
204 offset++; // cbMsgType
205
206 temp = pdu[offset++];
207 cbHeader_->msgId = (temp << 0x08) | pdu[offset++];
208
209 temp = pdu[offset++];
210 cbHeader_->serialNum.geoScope = (temp & 0xC0) >> 0x06;
211 cbHeader_->serialNum.msgCode = (temp & 0x3F) << 0x04;
212
213 temp = pdu[offset++];
214 cbHeader_->serialNum.msgCode |= (temp & 0xF0) >> 0x04;
215 cbHeader_->serialNum.updateNum = temp & 0x0F;
216
217 unsigned char dcs = pdu[offset++];
218 cbHeader_->totalPages = pdu[offset++];
219
220 unsigned short iosTemp = pdu[offset++];
221 iosTemp |= (pdu[offset++] << BYTE_BIT);
222 DecodeCbMsgDCS(dcs, iosTemp, cbHeader_->dcs);
223 cbHeader_->langType = cbHeader_->dcs.langType;
224 cbHeader_->recvTime = static_cast<time_t>(GetRecvTime());
225 offset -= 0x02;
226 return offset;
227 }
228
229 /**
230 * @brief Decode2gCbMsg GSM Content of Message
231 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.2.2 Message Parameter
232 * @param pdu [in]
233 */
Decode2gCbMsg(const std::vector<unsigned char> & pdu)234 void SmsCbMessage::Decode2gCbMsg(const std::vector<unsigned char> &pdu)
235 {
236 int offset = 0;
237 int dataLen = static_cast<int>(pdu.size());
238 if (cbHeader_ == nullptr) {
239 TELEPHONY_LOGE("decode2gCbMsg null header");
240 return;
241 }
242 TELEPHONY_LOGI("Decode2gCbMsg codingScheme ==%{public}d", cbHeader_->dcs.codingScheme);
243 switch (cbHeader_->dcs.codingScheme) {
244 case SMS_CODING_7BIT: {
245 dataLen = (dataLen * BYTE_BIT) / ENCODE_GSM_BIT;
246 unsigned char pageData[MAX_CBMSG_PAGE_SIZE * BYTE_BIT / ENCODE_GSM_BIT] = {0};
247 int unpackLen = SmsCommonUtils::Unpack7bitChar(pdu.data(), dataLen, 0x00, pageData,
248 MAX_CBMSG_PAGE_SIZE * BYTE_BIT / ENCODE_GSM_BIT);
249
250 if (cbHeader_->dcs.iso639Lang[0]) {
251 unpackLen = unpackLen - SmsCbMessage::SMS_CB_IOS639LANG_SIZE;
252 offset = SmsCbMessage::SMS_CB_IOS639LANG_SIZE;
253 }
254 messageRaw_.insert(0, (const char *)&pageData[offset], unpackLen);
255 break;
256 }
257 case SMS_CODING_8BIT:
258 case SMS_CODING_UCS2: {
259 if (cbHeader_->dcs.iso639Lang[0]) {
260 offset = 0x02;
261 dataLen -= offset;
262 }
263
264 if (dataLen > 0) {
265 messageRaw_.insert(0, (const char *)(pdu.data() + offset), dataLen);
266 }
267 break;
268 }
269 default:
270 break;
271 }
272 }
273
274 /**
275 * @brief Decode3gCbMsg UMTS CB Data
276 * 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.2.2.5 CB Data
277 * @param pdu [in]
278 */
Decode3gCbMsg(const std::vector<unsigned char> & pdu)279 void SmsCbMessage::Decode3gCbMsg(const std::vector<unsigned char> &pdu)
280 {
281 if (cbHeader_ == nullptr) {
282 TELEPHONY_LOGE("Decode3gCbMsg cbHeader null err.");
283 return;
284 }
285 switch (cbHeader_->dcs.codingScheme) {
286 case SMS_CODING_7BIT: {
287 TELEPHONY_LOGI("SMS_CODING_7BIT totalPages %{public}d", cbHeader_->totalPages);
288 Decode3g7Bit(pdu);
289 break;
290 }
291 case SMS_CODING_8BIT:
292 case SMS_CODING_UCS2: {
293 TELEPHONY_LOGI("SMS_CODING_UCS2 totalPages %{public}d", cbHeader_->totalPages);
294 Decode3gUCS2(pdu);
295 break;
296 }
297 default:
298 break;
299 }
300 cbHeader_->totalPages = 1;
301 }
302
Decode3g7Bit(const std::vector<unsigned char> & pdu)303 void SmsCbMessage::Decode3g7Bit(const std::vector<unsigned char> &pdu)
304 {
305 if (pdu.size() <= 0) {
306 TELEPHONY_LOGE("pdu size is invalid.");
307 return;
308 }
309 unsigned int offset = 0;
310 int dataLen = 0;
311 const int pduLen = static_cast<int>(pdu.size());
312 const unsigned char *tpdu = pdu.data();
313 for (unsigned char i = 0; i < cbHeader_->totalPages; ++i) {
314 unsigned char pageLenOffset = (unsigned char)((i + 1) * MAX_CBMSG_PAGE_SIZE + i);
315 if (pduLen < pageLenOffset) {
316 TELEPHONY_LOGE("CB Msg Size err [%{pulbic}d]", pduLen);
317 messageRaw_.clear();
318 return;
319 }
320 dataLen = tpdu[pageLenOffset];
321 offset = static_cast<unsigned int>((i * MAX_CBMSG_PAGE_SIZE) + i);
322 if (dataLen > MAX_CBMSG_PAGE_SIZE) {
323 TELEPHONY_LOGE("CB Msg Size is over MAX [%{pulbic}d]", dataLen);
324 messageRaw_.clear();
325 return;
326 }
327 int unpackLen = 0;
328 dataLen = (dataLen * BYTE_BIT) / ENCODE_GSM_BIT;
329 unsigned char pageData[MAX_CBMSG_PAGE_SIZE * BYTE_BIT / ENCODE_GSM_BIT] = {0};
330 unpackLen = SmsCommonUtils::Unpack7bitChar(&tpdu[offset], dataLen, 0x00, pageData,
331 MAX_CBMSG_PAGE_SIZE * BYTE_BIT / ENCODE_GSM_BIT);
332 messageRaw_.insert(messageRaw_.size(), (const char *)pageData, unpackLen);
333 }
334 }
335
Decode3gUCS2(const std::vector<unsigned char> & pdu)336 void SmsCbMessage::Decode3gUCS2(const std::vector<unsigned char> &pdu)
337 {
338 if (pdu.size() <= 0) {
339 TELEPHONY_LOGE("pdu size is invalid.");
340 return;
341 }
342 int dataLen = 0;
343 unsigned int offset = 0;
344 const int pduLen = static_cast<int>(pdu.size());
345 const unsigned char *tpdu = pdu.data();
346 for (unsigned char i = 0; i < cbHeader_->totalPages; ++i) {
347 unsigned char pageLenOffset = (unsigned char)((i + 1) * MAX_CBMSG_PAGE_SIZE + i);
348 if (pduLen < pageLenOffset) {
349 TELEPHONY_LOGE("CB Msg Size err [%{pulbic}d]", pduLen);
350 messageRaw_.clear();
351 return;
352 }
353 if (cbHeader_->dcs.iso639Lang[0]) {
354 dataLen = tpdu[pageLenOffset] - 0x02;
355 offset = (i * MAX_CBMSG_PAGE_SIZE) + i + 0x02;
356 } else {
357 dataLen = tpdu[pageLenOffset];
358 offset = static_cast<unsigned int>((i * MAX_CBMSG_PAGE_SIZE) + i);
359 }
360 if (dataLen > 0 && dataLen <= MAX_CBMSG_PAGE_SIZE) {
361 messageRaw_.insert(messageRaw_.size(), (const char *)&tpdu[offset], dataLen);
362 }
363 }
364 }
365
DecodeEtwsMsg(const std::vector<unsigned char> & pdu)366 void SmsCbMessage::DecodeEtwsMsg(const std::vector<unsigned char> &pdu)
367 {
368 int offset = 0;
369 if (pdu.size() > MAX_ETWS_SIZE) {
370 TELEPHONY_LOGE("ETWS Msg Size is over MAX [%{public}zu]", pdu.size());
371 return;
372 }
373 messageRaw_.insert(0, (const char *)(pdu.data() + offset), static_cast<int>(pdu.size()) - offset);
374 }
375
ConvertToUTF8(const std::string & raw,std::string & message) const376 void SmsCbMessage::ConvertToUTF8(const std::string &raw, std::string &message) const
377 {
378 if (cbHeader_ == nullptr) {
379 TELEPHONY_LOGE("ConvertToUTF8 cbHeader null err.");
380 return;
381 }
382 if (cbHeader_->bEtwsMessage && cbHeader_->cbEtwsType == SMS_NETTEXT_ETWS_PRIMARY) {
383 message.assign(raw);
384 } else {
385 MsgTextConvert *textCvt = MsgTextConvert::Instance();
386 if (textCvt == nullptr) {
387 TELEPHONY_LOGE("MsgTextConvert Instance nullptr");
388 return;
389 }
390 int codeSize = 0;
391 MsgLangInfo langInfo = {
392 0,
393 };
394 unsigned char outBuf[MAX_CB_MSG_TEXT_LEN + 1] = {0};
395 if (cbHeader_->dcs.codingScheme == SMS_CODING_7BIT) {
396 codeSize = textCvt->ConvertGSM7bitToUTF8(
397 outBuf, sizeof(outBuf), (unsigned char *)raw.data(), raw.length(), &langInfo);
398 } else if (cbHeader_->dcs.codingScheme == SMS_CODING_UCS2) {
399 codeSize =
400 textCvt->ConvertUCS2ToUTF8(outBuf, sizeof(outBuf), (unsigned char *)raw.data(), raw.length());
401 } else {
402 message.assign(raw);
403 return;
404 }
405 outBuf[codeSize] = '\0';
406 message.insert(0, (const char *)outBuf, codeSize);
407 }
408 }
409
EncodeCbSerialNum(const SmsCBMessageSerialNum & snFields)410 unsigned short SmsCbMessage::EncodeCbSerialNum(const SmsCBMessageSerialNum &snFields)
411 {
412 unsigned short serialNum = 0;
413 serialNum = ((snFields.geoScope & 0x03) << 0x0E) | ((snFields.msgCode & 0x03FF) << 0x04) |
414 (snFields.updateNum & 0x0F);
415 return serialNum;
416 }
417
CMASClass(const unsigned short messageId) const418 int SmsCbMessage::CMASClass(const unsigned short messageId) const
419 {
420 int ret = 0;
421 switch (messageId) {
422 case CMAS_PRESIDENTIAL_DEFUALT:
423 case CMAS_PRESIDENTIAL_SPANISH:
424 ret = MSG_CMAS_PRESIDENTIAL;
425 break;
426 case CMAS_EXTREME_OBSERVED_DEFUALT:
427 case CMAS_EXTREME_OBSERVED_SPANISH:
428 case CMAS_EXTREME_LIKELY_DEFUALT:
429 case CMAS_EXTREME_LIKELY_SPANISH:
430 ret = MSG_CMAS_EXTREME;
431 break;
432 case CMAS_SERVER_EXTERME_OBSERVED_DEFUALT:
433 case CMAS_SERVER_EXTREME_OBSERVED_SPANISH:
434 case CMAS_SERVER_EXTERME_LIKELY_DEFUALT:
435 case CMAS_SERVER_EXTERME_LIKELY_SPANISH:
436 case CMAS_SERVER_SERVER_OBSERVED_DEFUALT:
437 case CMAS_SERVER_SERVER_OBSERVED_SPANISH:
438 case CMAS_SERVER_SERVER_LIKELY_DEFUALT:
439 case CMAS_SERVER_SERVER_LIKELY_SPANISH:
440 case CMAS_SERVER_SERVER_EXPECTED_OBSERVED_DEFUALT:
441 case CMAS_SERVER_SERVER_EXPECTED_OBSERVED_SPANISH:
442 case CMAS_SERVER_SERVER_EXPECTED_LIKELY_DEFUALT:
443 case CMAS_SERVER_SERVER_EXPECTED_LIKELY_SPANISH:
444 ret = MSG_CMAS_SEVERE;
445 break;
446 case CMAS_AMBER_ALERT_DEFUALT:
447 case CMAS_AMBER_ALERT_SPANISH:
448 ret = MSG_CMAS_AMBER;
449 break;
450 case CMAS_RMT_ALERT_DEFUALT:
451 case CMAS_RMT_ALERT_SPANISH:
452 ret = MSG_CMAS_TEST;
453 break;
454 case CMAS_EXERCISE_ALERT_DEFUALT:
455 case CMAS_EXERCISE_ALERT_SPANISH:
456 ret = MSG_CMAS_EXERCISE;
457 break;
458 case CMAS_OPERATOR_ALERT_DEFUALT:
459 case CMAS_OPERATOR_ALERT_SPANISH:
460 ret = MSG_CMAS_OPERATOR_DEFINED;
461 break;
462 default:
463 break;
464 }
465 return ret;
466 }
467
468 /**
469 * @brief DecodeIos639Dcs
470 * from 3GPP TS 23.038 V4.3.0 (2001-09) 6.1.1 section
471 * Control characters
472 * @param dcsData
473 * @param iosData
474 * @param pDcs
475 */
DecodeIos639Dcs(const unsigned char dcsData,const unsigned short iosData,SmsCbMessageDcs & pDcs) const476 void SmsCbMessage::DecodeIos639Dcs(
477 const unsigned char dcsData, const unsigned short iosData, SmsCbMessageDcs &pDcs) const
478 {
479 unsigned char dcsLow = (dcsData & 0x0F);
480 switch (dcsLow) {
481 case 0x00:
482 case 0x01: {
483 pDcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
484 pDcs.codingScheme = (dcsData & 0x01) ? SMS_CODING_UCS2 : SMS_CODING_7BIT;
485 pDcs.langType = SMS_CBMSG_LANG_ISO639;
486 unsigned char hight = (iosData >> BYTE_BIT);
487 unsigned char low = iosData;
488 // from 3GPP TS 23.038 V4.3.0 (2001-09) 6.1.1 section Control characters
489 if (hight && low) {
490 pDcs.iso639Lang[0x00] = hight & 0x7F;
491 pDcs.iso639Lang[0x01] = (hight & 0X80) >> 0x07;
492 pDcs.iso639Lang[0x01] |= (low & 0X3F) << 0x01;
493 pDcs.iso639Lang[0x02] = 0x13; /* CR */
494 } else {
495 pDcs.iso639Lang[0x00] = 0x45; /* E */
496 pDcs.iso639Lang[0x01] = 0x4E; /* N */
497 pDcs.iso639Lang[0x02] = 0x13; /* CR */
498 }
499 break;
500 }
501 default:
502 break;
503 }
504 }
505
506 /**
507 * @brief DecodeGeneralDcs
508 * from 3GPP TS 23.038 V4.3.0 (2001-09) 6 section
509 * CBS Data Coding Scheme
510 * @param dcsData
511 * @param iosData
512 * @param pDcs
513 */
DecodeGeneralDcs(const unsigned char dcsData,SmsCbMessageDcs & pDcs) const514 void SmsCbMessage::DecodeGeneralDcs(const unsigned char dcsData, SmsCbMessageDcs &pDcs) const
515 {
516 pDcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
517 pDcs.bCompressed = (dcsData & 0x20) ? true : false;
518 if (dcsData & 0x10) {
519 pDcs.classType = (dcsData & 0x03);
520 }
521 unsigned char tmpScheme = (dcsData & 0x0C) >> 0x02;
522 switch (tmpScheme) {
523 case 0x00:
524 pDcs.codingScheme = SMS_CODING_7BIT;
525 break;
526 case 0x01:
527 pDcs.codingScheme = SMS_CODING_8BIT;
528 break;
529 case 0x02:
530 pDcs.codingScheme = SMS_CODING_UCS2;
531 break;
532 default:
533 break;
534 }
535 }
536
537 /**
538 * @brief DecodeCbMsgDCS
539 * from 3GPP TS 23.038 V4.3.0 (2001-09) 6 section
540 * CBS Data Coding Scheme
541 * @param dcsData
542 * @param iosData
543 * @param pDcs
544 */
DecodeCbMsgDCS(const unsigned char dcsData,const unsigned short iosData,SmsCbMessageDcs & pDcs) const545 void SmsCbMessage::DecodeCbMsgDCS(
546 const unsigned char dcsData, const unsigned short iosData, SmsCbMessageDcs &pDcs) const
547 {
548 pDcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
549 pDcs.classType = SMS_CLASS_UNKNOWN;
550 pDcs.bCompressed = false;
551 pDcs.codingScheme = SMS_CODING_7BIT;
552 pDcs.langType = SMS_CBMSG_LANG_UNSPECIFIED;
553 (void)memset_s(pDcs.iso639Lang, sizeof(pDcs.iso639Lang), 0x00, sizeof(pDcs.iso639Lang));
554 pDcs.bUDH = false;
555 pDcs.rawData = dcsData;
556 unsigned char codingGroup = (dcsData & 0xF0) >> 0x04;
557 switch (codingGroup) {
558 case 0x00:
559 case 0x02:
560 case 0x03:
561 pDcs.codingGroup = SMS_CBMSG_CODGRP_GENERAL_DCS;
562 pDcs.langType = dcsData;
563 break;
564 case 0x01:
565 DecodeIos639Dcs(dcsData, iosData, pDcs);
566 break;
567 case 0x04:
568 case 0x05:
569 case 0x06:
570 case 0x07:
571 DecodeGeneralDcs(dcsData, pDcs);
572 break;
573 case 0x09:
574 pDcs.bUDH = true;
575 pDcs.classType = dcsData & 0x03;
576 pDcs.codingScheme = (dcsData & 0x0C) >> 0x02;
577 break;
578 case 0x0E:
579 pDcs.codingGroup = SMS_CBMSG_CODGRP_WAP;
580 break;
581 case 0x0F:
582 pDcs.codingGroup = SMS_CBMSG_CODGRP_CLASS_CODING;
583 pDcs.codingScheme = (dcsData & 0x04) ? SMS_CODING_8BIT : SMS_CODING_7BIT;
584 pDcs.classType = dcsData & 0x03;
585 break;
586 default:
587 TELEPHONY_LOGE("codingGrp: [0x%{public}x]", codingGroup);
588 break;
589 }
590 }
591
GetRecvTime() const592 unsigned long SmsCbMessage::GetRecvTime() const
593 {
594 time_t recvTime = time(NULL);
595 return (unsigned long)recvTime;
596 }
597
ToString() const598 std::string SmsCbMessage::ToString() const
599 {
600 if (cbHeader_ == nullptr) {
601 TELEPHONY_LOGE("cbHeader_ is nullptr");
602 return "SmsCbMessage Header nullptr";
603 }
604 std::string msgId("msgId:" + std::to_string(cbHeader_->msgId));
605 std::string langType("\nlangType:" + std::to_string(cbHeader_->langType));
606 std::string isEtwsMessage("\nisEtws:" + std::to_string(cbHeader_->bEtwsMessage));
607 std::string cbMsgType("\ncbMsgType:" + std::to_string(cbHeader_->cbMsgType));
608 std::string warningType("\nwarningType:" + std::to_string(cbHeader_->warningType));
609 std::string serialNum("\nserialNum: geoScope " + std::to_string(cbHeader_->serialNum.geoScope) +
610 "| updateNum " + std::to_string(cbHeader_->serialNum.updateNum) + "| msgCode " +
611 std::to_string(cbHeader_->serialNum.msgCode));
612 std::string page(
613 "\ntotalpage: " + std::to_string(cbHeader_->totalPages) + " page:" + std::to_string(cbHeader_->page));
614 std::string recvTime("\nrecvTime: " + std::to_string(cbHeader_->recvTime));
615 std::string dcsRaw("\ndcsRaw: " + std::to_string(cbHeader_->dcs.rawData));
616 std::string msgBody;
617 ConvertToUTF8(messageRaw_, msgBody);
618 return msgId.append(langType)
619 .append(isEtwsMessage)
620 .append(cbMsgType)
621 .append(warningType)
622 .append(serialNum)
623 .append(page)
624 .append(recvTime)
625 .append(dcsRaw)
626 .append("\nbody:")
627 .append(msgBody);
628 }
629
GetFormat(int8_t & format) const630 bool SmsCbMessage::GetFormat(int8_t &format) const
631 {
632 if (cbHeader_ == nullptr) {
633 TELEPHONY_LOGE("cbHeader_ is nullptr");
634 return false;
635 }
636 constexpr uint8_t FORMAT_3GPP = 1;
637 format = FORMAT_3GPP;
638 return true;
639 }
640
GetPriority(int8_t & priority) const641 bool SmsCbMessage::GetPriority(int8_t &priority) const
642 {
643 if (cbHeader_ == nullptr) {
644 TELEPHONY_LOGE("cbHeader_ is nullptr");
645 return false;
646 }
647 const uint16_t pwsFirstId = 0x1100;
648 const uint16_t pwsLastId = 0x18FF;
649 const int8_t SmsPriorityNormal = 0x00;
650 const int8_t SmsPriorityEmergency = 0x03;
651 if (cbHeader_->msgId >= pwsFirstId && cbHeader_->msgId <= pwsLastId) {
652 priority = SmsPriorityEmergency;
653 } else {
654 priority = SmsPriorityNormal;
655 }
656 return true;
657 }
658
GetGeoScope(uint8_t & gs) const659 bool SmsCbMessage::GetGeoScope(uint8_t &gs) const
660 {
661 if (cbHeader_ == nullptr) {
662 TELEPHONY_LOGE("cbHeader_ is nullptr");
663 return false;
664 }
665 gs = cbHeader_->serialNum.geoScope;
666 return true;
667 }
668
GetSerialNum(uint16_t & serial) const669 bool SmsCbMessage::GetSerialNum(uint16_t &serial) const
670 {
671 if (cbHeader_ == nullptr) {
672 TELEPHONY_LOGE("cbHeader_ is nullptr");
673 return false;
674 }
675 serial = ((cbHeader_->serialNum.geoScope & 0x03) << 0x0E) |
676 ((cbHeader_->serialNum.msgCode & 0x03FF) << 0x04) | (cbHeader_->serialNum.updateNum & 0x0F);
677 return true;
678 }
679
GetServiceCategory(uint16_t & category) const680 bool SmsCbMessage::GetServiceCategory(uint16_t &category) const
681 {
682 if (cbHeader_ == nullptr) {
683 TELEPHONY_LOGE("cbHeader_ is nullptr");
684 return false;
685 }
686 category = cbHeader_->msgId;
687 return true;
688 }
689
GetWarningType(uint16_t & warnType) const690 bool SmsCbMessage::GetWarningType(uint16_t &warnType) const
691 {
692 if (cbHeader_ == nullptr) {
693 TELEPHONY_LOGE("cbHeader_ is nullptr");
694 return false;
695 }
696 warnType = cbHeader_->warningType;
697 return true;
698 }
699
IsEtwsPrimary(bool & isPrimary) const700 bool SmsCbMessage::IsEtwsPrimary(bool &isPrimary) const
701 {
702 if (cbHeader_ == nullptr) {
703 TELEPHONY_LOGE("cbHeader_ is nullptr");
704 return false;
705 }
706 isPrimary = (cbHeader_->cbEtwsType == SMS_NETTEXT_ETWS_PRIMARY);
707 return true;
708 }
709
IsEtwsMessage(bool & isEtws) const710 bool SmsCbMessage::IsEtwsMessage(bool &isEtws) const
711 {
712 if (cbHeader_ == nullptr) {
713 TELEPHONY_LOGE("cbHeader_ is nullptr");
714 return false;
715 }
716 const uint16_t etwsType = 0x1100;
717 const uint16_t etwsTypeMask = 0xFFF8;
718 isEtws = ((cbHeader_->msgId & etwsTypeMask) == etwsType);
719 return true;
720 }
721
IsCmasMessage(bool & isCmas) const722 bool SmsCbMessage::IsCmasMessage(bool &isCmas) const
723 {
724 if (cbHeader_ == nullptr) {
725 TELEPHONY_LOGE("cbHeader_ is nullptr");
726 return false;
727 }
728 const uint16_t cmasFirstId = 0x1112;
729 const uint16_t cmasLastId = 0x112F;
730 isCmas = ((cbHeader_->msgId >= cmasFirstId) && (cbHeader_->msgId <= cmasLastId));
731 return true;
732 }
733
IsEtwsEmergencyUserAlert(bool & isUserAlert) const734 bool SmsCbMessage::IsEtwsEmergencyUserAlert(bool &isUserAlert) const
735 {
736 uint16_t serial = 0;
737 if (!GetSerialNum(serial)) {
738 TELEPHONY_LOGE("Get serial num fail.");
739 return false;
740 }
741 const uint16_t emergencyUserAlert = 0x2000;
742 isUserAlert = ((serial & emergencyUserAlert) != 0);
743 return true;
744 }
745
IsEtwsPopupAlert(bool & isPopupAlert) const746 bool SmsCbMessage::IsEtwsPopupAlert(bool &isPopupAlert) const
747 {
748 uint16_t serial = 0;
749 if (!GetSerialNum(serial)) {
750 TELEPHONY_LOGE("Get serial num fail.");
751 return false;
752 }
753 const uint16_t etwsPopup = 0x1000;
754 isPopupAlert = ((serial & etwsPopup) != 0);
755 return true;
756 }
757
GetCmasSeverity(int8_t & severity) const758 bool SmsCbMessage::GetCmasSeverity(int8_t &severity) const
759 {
760 uint16_t msgId = 0;
761 if (!GetMessageId(msgId)) {
762 TELEPHONY_LOGE("Get message id fail.");
763 return false;
764 }
765 switch (static_cast<SmsCmasMessageType>(msgId)) {
766 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_DEFUALT:
767 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_SPANISH:
768 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_DEFUALT:
769 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_SPANISH:
770 case SmsCmasMessageType::CMAS_SERVER_EXTERME_OBSERVED_DEFUALT:
771 case SmsCmasMessageType::CMAS_SERVER_EXTREME_OBSERVED_SPANISH:
772 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_DEFUALT:
773 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_SPANISH:
774 severity = SMS_CMAE_SEVERITY_EXTREME;
775 break;
776 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_DEFUALT:
777 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_SPANISH:
778 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_DEFUALT:
779 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_SPANISH:
780 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_DEFUALT:
781 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_SPANISH:
782 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_DEFUALT:
783 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_SPANISH:
784 severity = SMS_CMAE_SEVERITY_SEVERE;
785 break;
786 default:
787 severity = SMS_CMAE_SEVERITY_RESERVED;
788 break;
789 }
790 return true;
791 }
792
GetCmasUrgency(int8_t & urgency) const793 bool SmsCbMessage::GetCmasUrgency(int8_t &urgency) const
794 {
795 uint16_t msgId = 0;
796 if (!GetMessageId(msgId)) {
797 TELEPHONY_LOGE("Get message id fail.");
798 return false;
799 }
800 switch (static_cast<SmsCmasMessageType>(msgId)) {
801 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_DEFUALT:
802 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_SPANISH:
803 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_DEFUALT:
804 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_SPANISH:
805 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_DEFUALT:
806 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_SPANISH:
807 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_DEFUALT:
808 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_SPANISH:
809 urgency = SMS_CMAE_URGENCY_IMMEDIATE;
810 break;
811 case SmsCmasMessageType::CMAS_SERVER_EXTERME_OBSERVED_DEFUALT:
812 case SmsCmasMessageType::CMAS_SERVER_EXTREME_OBSERVED_SPANISH:
813 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_DEFUALT:
814 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_SPANISH:
815 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_DEFUALT:
816 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_SPANISH:
817 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_DEFUALT:
818 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_SPANISH:
819 urgency = SMS_CMAE_URGENCY_EXPECTED;
820 break;
821 default:
822 urgency = SMS_CMAE_URGENCY_RESERVED;
823 break;
824 }
825 return true;
826 }
827
GetCmasCertainty(int8_t & certainty) const828 bool SmsCbMessage::GetCmasCertainty(int8_t &certainty) const
829 {
830 uint16_t msgId = 0;
831 if (!GetMessageId(msgId)) {
832 TELEPHONY_LOGE("Get message id fail.");
833 return false;
834 }
835 switch (static_cast<SmsCmasMessageType>(msgId)) {
836 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_DEFUALT:
837 case SmsCmasMessageType::CMAS_EXTREME_OBSERVED_SPANISH:
838 case SmsCmasMessageType::CMAS_SERVER_EXTERME_OBSERVED_DEFUALT:
839 case SmsCmasMessageType::CMAS_SERVER_EXTREME_OBSERVED_SPANISH:
840 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_DEFUALT:
841 case SmsCmasMessageType::CMAS_SERVER_SERVER_OBSERVED_SPANISH:
842 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_DEFUALT:
843 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_OBSERVED_SPANISH:
844 certainty = SMS_CMAE_CERTAINTY_OBSERVED;
845 break;
846 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_DEFUALT:
847 case SmsCmasMessageType::CMAS_EXTREME_LIKELY_SPANISH:
848 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_DEFUALT:
849 case SmsCmasMessageType::CMAS_SERVER_EXTERME_LIKELY_SPANISH:
850 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_DEFUALT:
851 case SmsCmasMessageType::CMAS_SERVER_SERVER_LIKELY_SPANISH:
852 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_DEFUALT:
853 case SmsCmasMessageType::CMAS_SERVER_SERVER_EXPECTED_LIKELY_SPANISH:
854 certainty = SMS_CMAE_CERTAINTY_LIKELY;
855 break;
856 default:
857 certainty = SMS_CMAE_CERTAINTY_RESERVED;
858 break;
859 }
860 return true;
861 }
862
GetCmasCategory(int8_t & cmasCategory) const863 bool SmsCbMessage::GetCmasCategory(int8_t &cmasCategory) const
864 {
865 if (cbHeader_ == nullptr) {
866 TELEPHONY_LOGE("cbHeader_ is nullptr");
867 return false;
868 }
869 cmasCategory = SMS_CMAE_CTG_RESERVED;
870 return true;
871 }
872
GetCmasResponseType(int8_t & cmasRes) const873 bool SmsCbMessage::GetCmasResponseType(int8_t &cmasRes) const
874 {
875 if (cbHeader_ == nullptr) {
876 TELEPHONY_LOGE("cbHeader_ is nullptr");
877 return false;
878 }
879 cmasRes = SMS_CMAE_RESP_TYPE_RESERVED;
880 return true;
881 }
882
GetMessageId(uint16_t & msgId) const883 bool SmsCbMessage::GetMessageId(uint16_t &msgId) const
884 {
885 if (cbHeader_ == nullptr) {
886 TELEPHONY_LOGE("cbHeader_ is nullptr");
887 return false;
888 }
889 msgId = cbHeader_->msgId;
890 return true;
891 }
892
GetCmasMessageClass(int8_t & cmasClass) const893 bool SmsCbMessage::GetCmasMessageClass(int8_t &cmasClass) const
894 {
895 uint16_t msgId = 0;
896 if (!GetMessageId(msgId)) {
897 TELEPHONY_LOGE("Get message id fail.");
898 return false;
899 }
900 cmasClass = CMASClass(msgId);
901 return true;
902 }
903
GetMsgType(uint8_t & msgType) const904 bool SmsCbMessage::GetMsgType(uint8_t &msgType) const
905 {
906 if (cbHeader_ == nullptr) {
907 TELEPHONY_LOGE("cbHeader_ is nullptr");
908 return false;
909 }
910 msgType = cbHeader_->cbMsgType;
911 return true;
912 }
913
GetLangType(uint8_t & lan) const914 bool SmsCbMessage::GetLangType(uint8_t &lan) const
915 {
916 if (cbHeader_ == nullptr) {
917 TELEPHONY_LOGE("cbHeader_ is nullptr");
918 return false;
919 }
920 lan = cbHeader_->langType;
921 return true;
922 }
923
GetDcs(uint8_t & dcs) const924 bool SmsCbMessage::GetDcs(uint8_t &dcs) const
925 {
926 if (cbHeader_ == nullptr) {
927 TELEPHONY_LOGE("cbHeader_ is nullptr");
928 return false;
929 }
930 dcs = cbHeader_->dcs.codingScheme;
931 return true;
932 }
933
GetReceiveTime(long & recvTime) const934 bool SmsCbMessage::GetReceiveTime(long &recvTime) const
935 {
936 if (cbHeader_ == nullptr) {
937 TELEPHONY_LOGE("cbHeader_ is nullptr");
938 return false;
939 }
940 recvTime = cbHeader_->recvTime;
941 return true;
942 }
943 } // namespace Telephony
944 } // namespace OHOS