1 /*
2 * Copyright (C) 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_common_utils.h"
17
18 #include <ctime>
19 #include "securec.h"
20 #include "telephony_log_wrapper.h"
21
22 namespace OHOS {
23 namespace Telephony {
24 static constexpr uint8_t SMS_ENCODE_GSM_BIT = 7;
25 static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
26 static constexpr uint8_t SMS_BYTE_BIT = 8;
27 static constexpr uint16_t SEC_PER_HOUR = 3600;
28 static constexpr uint8_t BASE_GSM_YEAR = 100;
29 static constexpr uint8_t MAX_ABS_TIME_LEN = 32;
30 static constexpr uint8_t HEX_NUM_A = 0x0A;
31 static constexpr uint8_t HEX_NUM_B = 0x0B;
32 static constexpr uint8_t HEX_NUM_C = 0x0C;
33 static constexpr uint8_t MIN_PRINTABLE_CHAR = 32;
34 static constexpr uint8_t MAX_PRINTABLE_CHAR = 127;
35
Pack7bitChar(const uint8_t * userData,uint16_t dataLen,uint8_t fillBits,uint8_t * packData,uint16_t packLen)36 uint16_t SmsCommonUtils::Pack7bitChar(
37 const uint8_t *userData, uint16_t dataLen, uint8_t fillBits, uint8_t *packData, uint16_t packLen)
38 {
39 uint16_t dstIdx = 0;
40 if (userData == nullptr || packData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) {
41 TELEPHONY_LOGE("userData error.");
42 return dstIdx;
43 }
44
45 auto shift = fillBits;
46 if (shift > 0) {
47 dstIdx = 1;
48 }
49 uint16_t srcIdx = 0;
50 while (srcIdx < dataLen && dstIdx < packLen) {
51 if (shift == 0) {
52 packData[dstIdx] = userData[srcIdx];
53 shift = SMS_ENCODE_GSM_BIT;
54 srcIdx++;
55 dstIdx++;
56 if (srcIdx >= dataLen) {
57 break;
58 }
59 }
60 if (shift > 1) {
61 packData[dstIdx - 1] |= userData[srcIdx] << shift;
62 packData[dstIdx] = userData[srcIdx] >> (SMS_BYTE_BIT - shift);
63 srcIdx++;
64 dstIdx++;
65 shift--;
66 } else if (shift == 1) {
67 packData[dstIdx - 1] |= userData[srcIdx] << shift;
68 shift--;
69 srcIdx++;
70 }
71 }
72 return dstIdx;
73 }
74
Unpack7bitChar(const uint8_t * tpdu,uint16_t dataLen,uint8_t fillBits,uint8_t * unpackData,uint16_t unpackDataLen)75 uint16_t SmsCommonUtils::Unpack7bitChar(
76 const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen)
77 {
78 uint16_t srcIdx = 0;
79 uint16_t dstIdx = 0;
80 auto shift = fillBits;
81 if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) {
82 TELEPHONY_LOGE("userData error.");
83 return dstIdx;
84 }
85 if (shift > 0) {
86 srcIdx = 1;
87 }
88 for (; srcIdx < dataLen && dstIdx < unpackDataLen; dstIdx++) {
89 if (shift == 0) {
90 unpackData[dstIdx] = tpdu[srcIdx] & 0x7F;
91 shift = SMS_ENCODE_GSM_BIT;
92 srcIdx++;
93 dstIdx++;
94 if (dstIdx >= dataLen) {
95 dstIdx--;
96 break;
97 }
98 }
99 if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) {
100 unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift));
101 unpackData[dstIdx] &= 0x7F;
102 shift--;
103 if (shift > 0) {
104 srcIdx++;
105 }
106 }
107 }
108 return dstIdx;
109 }
110
Unpack7bitCharForCBPdu(const uint8_t * tpdu,uint16_t dataLen,uint8_t fillBits,uint8_t * unpackData,uint16_t unpackDataLen)111 uint16_t SmsCommonUtils::Unpack7bitCharForCBPdu(
112 const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen)
113 {
114 uint16_t srcIdx = 0;
115 uint16_t dstIdx = 0;
116 auto shift = fillBits;
117 if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) {
118 TELEPHONY_LOGE("userData error.");
119 return dstIdx;
120 }
121 if (shift > 0) {
122 srcIdx = 1;
123 }
124 for (; srcIdx < dataLen && dstIdx < unpackDataLen;) {
125 if (shift == 0) {
126 unpackData[dstIdx] = tpdu[srcIdx] & 0x7F;
127 shift = SMS_ENCODE_GSM_BIT;
128 srcIdx++;
129 dstIdx++;
130 }
131 if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) {
132 unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift));
133 unpackData[dstIdx] &= 0x7F;
134 shift--;
135 if (shift > 0) {
136 srcIdx++;
137 }
138 dstIdx++;
139 }
140 }
141 if (dstIdx >= unpackDataLen) {
142 TELEPHONY_LOGE("dstIdx:%{public}d", dstIdx);
143 return 0;
144 }
145 uint8_t value = 0;
146 if (shift == 0) {
147 value = tpdu[srcIdx] >> shift;
148 } else if (srcIdx > 1) {
149 value = tpdu[srcIdx - 1] >> shift;
150 }
151 if (value >= MIN_PRINTABLE_CHAR && value <= MAX_PRINTABLE_CHAR) {
152 unpackData[dstIdx] = value;
153 dstIdx++;
154 }
155 TELEPHONY_LOGI("dstIdx:%{public}d", dstIdx);
156 return dstIdx;
157 }
158
DigitToDtmfChar(const uint8_t c)159 uint8_t SmsCommonUtils::DigitToDtmfChar(const uint8_t c)
160 {
161 if (c == '0') {
162 return HEX_NUM_A;
163 } else if (c == '*') {
164 return HEX_NUM_B;
165 } else if (c == '#') {
166 return HEX_NUM_C;
167 } else {
168 return (c - '0');
169 }
170 }
171
DtmfCharToDigit(const uint8_t c)172 uint8_t SmsCommonUtils::DtmfCharToDigit(const uint8_t c)
173 {
174 switch (c) {
175 case HEX_NUM_B:
176 return '*';
177 case HEX_NUM_C:
178 return '#';
179 case HEX_NUM_A:
180 return '0';
181 default:
182 return (c + '0');
183 }
184 }
185
ConvertTime(const struct SmsTimeAbs & timeAbs)186 int64_t SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs)
187 {
188 time_t rawtime;
189 struct tm tmObj;
190 if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
191 return time(nullptr);
192 }
193 tmObj.tm_year = (timeAbs.year + BASE_GSM_YEAR);
194 tmObj.tm_mon = (timeAbs.month - 0x01);
195 tmObj.tm_mday = timeAbs.day;
196 tmObj.tm_hour = timeAbs.hour;
197 tmObj.tm_min = timeAbs.minute;
198 tmObj.tm_sec = timeAbs.second;
199 tmObj.tm_isdst = 0;
200 rawtime = mktime(&tmObj);
201 GetDisplayTime(rawtime);
202 rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04));
203 GetDisplayTime(rawtime);
204 /* timezone value is tiemzone + daylight. So should not add daylight */
205 rawtime -= timezone;
206 GetDisplayTime(rawtime);
207 return rawtime;
208 }
209
GetDisplayTime(const time_t & rawtime)210 void SmsCommonUtils::GetDisplayTime(const time_t &rawtime)
211 {
212 struct tm tmObj;
213 char displayTime[MAX_ABS_TIME_LEN];
214 if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
215 TELEPHONY_LOGE("GetDisplayTime memset fail.");
216 return;
217 }
218
219 if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) {
220 TELEPHONY_LOGE("GetDisplayTime memset fail.");
221 return;
222 }
223
224 localtime_r(&rawtime, &tmObj);
225 if (strftime(displayTime, MAX_ABS_TIME_LEN, "%Y-%02m-%02d %T %z", &tmObj) <= 0) {
226 TELEPHONY_LOGE("strftime error.");
227 return;
228 }
229 TELEPHONY_LOGI("displayTime [%{public}s]", displayTime);
230 }
231 } // namespace Telephony
232 } // namespace OHOS
233