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_common_utils.h"
18
19 #include <ctime>
20 #include "securec.h"
21 #include "telephony_log_wrapper.h"
22
23 namespace OHOS {
24 namespace Telephony {
Pack7bitChar(const unsigned char * userData,int dataLen,int fillBits,unsigned char * packData)25 int SmsCommonUtils::Pack7bitChar(const unsigned char *userData, int dataLen, int fillBits, unsigned char *packData)
26 {
27 int srcIdx = 0;
28 int dstIdx = 0;
29 auto shift = static_cast<unsigned int>(fillBits);
30
31 if (userData == nullptr || packData == nullptr) {
32 return dstIdx;
33 }
34
35 if (shift > 0) {
36 dstIdx = 1;
37 }
38 while (srcIdx < dataLen) {
39 if (shift == 0) {
40 packData[dstIdx] = userData[srcIdx];
41 shift = SmsCommonUtils::SMS_ENCODE_GSM_BIT;
42 srcIdx++;
43 dstIdx++;
44 if (srcIdx >= dataLen) {
45 break;
46 }
47 }
48 if (shift > 1) {
49 packData[dstIdx - 1] |= userData[srcIdx] << shift;
50 packData[dstIdx] = userData[srcIdx] >> (SmsCommonUtils::SMS_BYTE_BIT - shift);
51 shift--;
52 srcIdx++;
53 dstIdx++;
54 } else if (shift == 1) {
55 packData[dstIdx - 1] |= static_cast<unsigned int>(userData[srcIdx]) << shift;
56 srcIdx++;
57 shift--;
58 }
59 }
60 return dstIdx;
61 }
62
Unpack7bitChar(const unsigned char * tpdu,unsigned char dataLen,int fillBits,unsigned char * unpackData,unsigned int unpackDataLen)63 int SmsCommonUtils::Unpack7bitChar(const unsigned char *tpdu, unsigned char dataLen, int fillBits,
64 unsigned char *unpackData, unsigned int unpackDataLen)
65 {
66 int srcIdx = 0;
67 int dstIdx = 0;
68 auto shift = static_cast<unsigned int>(fillBits);
69 if (unpackData == nullptr || tpdu == nullptr || dataLen > unpackDataLen) {
70 return dstIdx;
71 }
72 if (shift > 0) {
73 srcIdx = 1;
74 }
75 for (; dstIdx < dataLen; dstIdx++) {
76 if (shift == 0) {
77 unpackData[dstIdx] = tpdu[srcIdx] & 0x7F;
78 shift = SmsCommonUtils::SMS_ENCODE_GSM_BIT;
79 srcIdx++;
80 dstIdx++;
81 if (dstIdx >= dataLen) {
82 break;
83 }
84 }
85 if (shift > 0) {
86 unpackData[dstIdx] =
87 ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SmsCommonUtils::SMS_BYTE_BIT - shift));
88 unpackData[dstIdx] &= 0x7F;
89 shift--;
90 if (shift > 0) {
91 srcIdx++;
92 }
93 }
94 }
95 return dstIdx;
96 }
97
DigitToBcd(const char * digit,int digitLen,unsigned char * bcd)98 int SmsCommonUtils::DigitToBcd(const char *digit, int digitLen, unsigned char *bcd)
99 {
100 int offset = 0;
101 unsigned char temp;
102 if (digit == nullptr || bcd == nullptr) {
103 return offset;
104 }
105 for (int i = 0; i < digitLen; i++) {
106 switch (digit[i]) {
107 case '*':
108 temp = 0x0A;
109 break;
110 case '#':
111 temp = 0x0B;
112 break;
113 case 'P':
114 case 'p':
115 temp = 0x0C;
116 break;
117 default:
118 temp = digit[i] - '0';
119 break;
120 }
121 if ((i % SmsCommonUtils::SMS_HEX_BYTE_STEP) == 0) {
122 bcd[offset] = temp & 0x0F;
123 } else {
124 bcd[offset++] |= ((temp & 0x0F) << 0x04);
125 }
126 }
127
128 if ((digitLen % SmsCommonUtils::SMS_HEX_BYTE_STEP) == 1) {
129 bcd[offset++] |= 0xF0;
130 }
131 return offset;
132 }
133
BcdToDigit(const unsigned char * bcd,int bcdLen,char * digit)134 int SmsCommonUtils::BcdToDigit(const unsigned char *bcd, int bcdLen, char *digit)
135 {
136 int offset = 0;
137 unsigned char temp;
138 if (bcd == nullptr || digit == nullptr) {
139 return offset;
140 }
141 for (int i = 0; i < bcdLen; i++) {
142 temp = bcd[i] & 0x0F;
143 digit[offset++] = BcdToChar(temp);
144 temp = (bcd[i] & 0xF0) >> 0x04;
145 if (temp == 0x0F) {
146 digit[offset] = '\0';
147 return offset;
148 }
149 digit[offset++] = BcdToChar(temp);
150 }
151 digit[offset] = '\0';
152 return offset;
153 }
154
BcdToDigitCdma(const unsigned char * bcd,int bcdLen,char * digit)155 int SmsCommonUtils::BcdToDigitCdma(const unsigned char *bcd, int bcdLen, char *digit)
156 {
157 int offset = 0;
158 unsigned char temp;
159 if (bcd == nullptr || digit == nullptr) {
160 return offset;
161 }
162
163 for (int i = 0; i < bcdLen; i++) {
164 temp = (bcd[i] & 0xF0) >> 0x04;
165 digit[offset++] = BcdToChar(temp);
166 temp = bcd[i] & 0x0F;
167 if (temp == 0x0F) {
168 digit[offset] = '\0';
169 return offset;
170 }
171 digit[offset++] = BcdToChar(temp);
172 }
173 digit[offset] = '\0';
174 return offset;
175 }
176
BcdToChar(const unsigned char c)177 char SmsCommonUtils::BcdToChar(const unsigned char c)
178 {
179 char temp = 0;
180 switch (c) {
181 case 0x0A:
182 temp = '*';
183 break;
184 case 0x0B:
185 temp = '#';
186 break;
187 case 0x0C:
188 temp = 'P';
189 break;
190 default:
191 temp = c + '0';
192 break;
193 }
194 return temp;
195 }
196
ConvertDigitToDTMF(const char * digit,int digitLen,int startBit,unsigned char * dtmf)197 int SmsCommonUtils::ConvertDigitToDTMF(const char *digit, int digitLen, int startBit, unsigned char *dtmf)
198 {
199 int shift = startBit;
200 int offset = 0;
201 int srcIdx = 0;
202 uint8_t smsMaxShift = 4;
203 unsigned char temp;
204 if (digit == nullptr || dtmf == nullptr) {
205 TELEPHONY_LOGE("digit or dtmf is nullptr.");
206 return offset;
207 }
208 /* shift 1 and shift 2 are supported in this spec. */
209 if (shift >= smsMaxShift) {
210 TELEPHONY_LOGE("Invalid Param value shift : %{public}d", shift);
211 return offset;
212 }
213
214 for (int i = 0; i < digitLen; i++) {
215 temp = DigitToDtmfChar(digit[srcIdx]);
216 temp &= 0x0F;
217 if (shift == 0) {
218 if (i % SmsCommonUtils::SMS_HEX_BYTE_STEP == 0x01) {
219 dtmf[offset] |= temp;
220 offset++;
221 } else {
222 dtmf[offset] |= temp << 0x04;
223 }
224 } else if (shift >= 0x01 && shift < smsMaxShift) {
225 if (i % SmsCommonUtils::SMS_HEX_BYTE_STEP == 0x01) {
226 dtmf[offset] |= (temp >> shift);
227 dtmf[offset + 0x01] = temp << (SmsCommonUtils::SMS_BYTE_BIT - shift);
228 offset++;
229 } else {
230 dtmf[offset] |= (char)(temp << (SmsCommonUtils::SMS_BYTE_BIT - shift - smsMaxShift));
231 }
232 }
233 srcIdx++;
234 }
235 return offset;
236 }
237
DigitToDtmfChar(const unsigned char c)238 unsigned char SmsCommonUtils::DigitToDtmfChar(const unsigned char c)
239 {
240 switch (c) {
241 case '*':
242 return 0x0B;
243 case '#':
244 return 0x0C;
245 case '0':
246 return 0x0A;
247 default:
248 return (c - '0');
249 }
250 }
251
ConvertTime(const struct SmsTimeAbs & timeAbs)252 long SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs)
253 {
254 time_t rawtime;
255 struct tm tmInfo;
256 if (memset_s(&tmInfo, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
257 return time(nullptr);
258 }
259 tmInfo.tm_year = (timeAbs.year + BASE_GSM_YEAR);
260 tmInfo.tm_mon = (timeAbs.month - 0x01);
261 tmInfo.tm_mday = timeAbs.day;
262 tmInfo.tm_hour = timeAbs.hour;
263 tmInfo.tm_min = timeAbs.minute;
264 tmInfo.tm_sec = timeAbs.second;
265 tmInfo.tm_isdst = 0;
266 rawtime = mktime(&tmInfo);
267 DisplayTime(rawtime);
268 rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04));
269 DisplayTime(rawtime);
270 /* timezone value is tiemzone + daylight. So should not add daylight */
271 #ifdef __MSG_DAYLIGHT_APPLIED__
272 rawtime -= (timezone - daylight * SEC_PER_HOUR);
273 #else
274 rawtime -= timezone;
275 #endif
276 DisplayTime(rawtime);
277 return rawtime;
278 }
279
DisplayTime(const time_t & rawtime)280 void SmsCommonUtils::DisplayTime(const time_t &rawtime)
281 {
282 struct tm tmInfo;
283 const uint8_t maxAbsTimeLen = 32;
284 char displayTime[maxAbsTimeLen];
285 if (memset_s(&tmInfo, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
286 TELEPHONY_LOGE("DisplayTime memset fail.");
287 return;
288 }
289
290 if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) {
291 TELEPHONY_LOGE("DisplayTime memset fail.");
292 return;
293 }
294
295 localtime_r(&rawtime, &tmInfo);
296 if (strftime(displayTime, maxAbsTimeLen, "%Y-%02m-%02d %T %z", &tmInfo) <= 0) {
297 TELEPHONY_LOGE("strftime error.");
298 return;
299 }
300 TELEPHONY_LOGI("displayTime [%{public}s]", displayTime);
301 }
302 } // namespace Telephony
303 } // namespace OHOS