• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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