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 "gsm_sms_common_utils.h"
17
18 #include <ctime>
19
20 #include "gsm_pdu_hex_value.h"
21 #include "securec.h"
22 #include "telephony_log_wrapper.h"
23 #include "text_coder.h"
24
25 namespace OHOS {
26 namespace Telephony {
27 static constexpr uint8_t DIGITAL_STEP = 2;
28 static constexpr uint8_t SMS_ENCODE_GSM_BIT = 7;
29 static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
30 static constexpr uint8_t SMS_BYTE_BIT = 8;
31 static constexpr uint8_t MIN_REMAIN_LEN = 2;
32
Pack7bitChar(SmsWriteBuffer & buffer,const uint8_t * userData,uint8_t dataLen,uint8_t fillBits)33 bool GsmSmsCommonUtils::Pack7bitChar(SmsWriteBuffer &buffer, const uint8_t *userData, uint8_t dataLen, uint8_t fillBits)
34 {
35 if (userData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) {
36 TELEPHONY_LOGE("userData error.");
37 return false;
38 }
39 auto shift = fillBits;
40 if (shift > 0) {
41 buffer.MoveForward(1);
42 }
43 uint8_t srcIdx = 0;
44 while (srcIdx < dataLen) {
45 if (shift == 0) {
46 if (!buffer.WriteByte(userData[srcIdx])) {
47 TELEPHONY_LOGE("write data error.");
48 return false;
49 }
50 shift = SMS_ENCODE_GSM_BIT;
51 srcIdx++;
52 if (srcIdx >= dataLen) {
53 break;
54 }
55 }
56 if (shift > 1) {
57 if (!Pack7bitCharPartData(buffer, userData, srcIdx, shift)) {
58 TELEPHONY_LOGE("packet fail.");
59 return false;
60 }
61 shift--;
62 srcIdx++;
63 } else if (shift == 1) {
64 uint8_t oneByte = 0;
65 if (!buffer.GetValueFromIndex(buffer.GetIndex() - 1, oneByte)) {
66 TELEPHONY_LOGE("get data error.");
67 return false;
68 }
69 oneByte |= (userData[srcIdx] << shift);
70 if (!buffer.InsertByte(oneByte, (buffer.GetIndex() - 1))) {
71 TELEPHONY_LOGE("write data error.");
72 return false;
73 }
74 srcIdx++;
75 shift--;
76 }
77 }
78 return true;
79 }
80
Pack7bitCharPartData(SmsWriteBuffer & buffer,const uint8_t * userData,uint8_t & srcIdx,uint8_t & shift)81 bool GsmSmsCommonUtils::Pack7bitCharPartData(
82 SmsWriteBuffer &buffer, const uint8_t *userData, uint8_t &srcIdx, uint8_t &shift)
83 {
84 uint8_t oneByte = 0;
85 if (!buffer.GetValueFromIndex(buffer.GetIndex() - 1, oneByte)) {
86 TELEPHONY_LOGE("get data error.");
87 return false;
88 }
89 oneByte |= (userData[srcIdx] << shift);
90 if (!buffer.InsertByte(oneByte, (buffer.GetIndex() - 1))) {
91 TELEPHONY_LOGE("write data error.");
92 return false;
93 }
94 if (!buffer.GetTopValue(oneByte)) {
95 TELEPHONY_LOGE("get data error.");
96 return false;
97 }
98 uint8_t nextByte = userData[srcIdx] >> (SMS_BYTE_BIT - shift);
99 if (!buffer.WriteByte(oneByte | nextByte)) {
100 TELEPHONY_LOGE("write data error.");
101 return false;
102 }
103 return true;
104 }
105
Unpack7bitChar(SmsReadBuffer & buffer,uint8_t dataLen,uint8_t fillBits,uint8_t * unpackData,uint8_t unpackDataLen,uint8_t & dstIdx)106 bool GsmSmsCommonUtils::Unpack7bitChar(SmsReadBuffer &buffer, uint8_t dataLen, uint8_t fillBits, uint8_t *unpackData,
107 uint8_t unpackDataLen, uint8_t &dstIdx)
108 {
109 auto shift = fillBits;
110 if (unpackData == nullptr || dataLen >= unpackDataLen || fillBits > SMS_BYTE_BIT - 1) {
111 TELEPHONY_LOGE("data error.");
112 return false;
113 }
114 if (shift > 0) {
115 buffer.MoveForward(1);
116 }
117 for (; dstIdx < unpackDataLen; dstIdx++) {
118 if (shift == 0) {
119 uint8_t oneByte = 0;
120 if (!buffer.ReadByte(oneByte)) {
121 TELEPHONY_LOGI("data unpack finish.");
122 return true;
123 }
124 unpackData[dstIdx] = oneByte & HEX_VALUE_7F;
125 shift = SMS_ENCODE_GSM_BIT;
126 dstIdx++;
127 if (dstIdx >= unpackDataLen) {
128 break;
129 }
130 }
131
132 uint8_t oneByte = 0;
133 if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
134 TELEPHONY_LOGI("data unpack finish.");
135 return true;
136 }
137 uint8_t nextByte = 0;
138 if (!buffer.PickOneByte(nextByte)) {
139 TELEPHONY_LOGI("data unpack finish.");
140 unpackData[dstIdx] = (oneByte >> shift);
141 if (unpackData[dstIdx] != 0) {
142 dstIdx++;
143 }
144 return true;
145 }
146 unpackData[dstIdx] = (oneByte >> shift) + (nextByte << (SMS_BYTE_BIT - shift));
147 unpackData[dstIdx] &= HEX_VALUE_7F;
148 shift--;
149 if (shift > 0) {
150 buffer.MoveForward(1);
151 }
152 }
153 return true;
154 }
155
Unpack7bitCharForMiddlePart(const uint8_t * buffer,uint8_t dataLen,uint8_t * unpackData)156 bool GsmSmsCommonUtils::Unpack7bitCharForMiddlePart(const uint8_t *buffer, uint8_t dataLen, uint8_t *unpackData)
157 {
158 if (buffer == nullptr || unpackData == nullptr || dataLen <= 0) {
159 TELEPHONY_LOGE("data error.");
160 return false;
161 }
162 uint8_t maxAddressArrayIndex = 19;
163 bool flag = false;
164 for (uint8_t i = 0; i < dataLen; i++) {
165 uint8_t bitOffsetNumber = HEX_VALUE_07 * i;
166 uint8_t shiftNumber = bitOffsetNumber % HEX_VALUE_08;
167 uint8_t byteOffsetNumber = bitOffsetNumber / HEX_VALUE_08;
168 uint8_t currentValue = (HEX_VALUE_7F) & (buffer[byteOffsetNumber] >> shiftNumber);
169 if (shiftNumber > 1) {
170 currentValue &= HEX_VALUE_7F >> (shiftNumber - 1);
171 currentValue |= HEX_VALUE_7F & (buffer[byteOffsetNumber + 1] << (HEX_VALUE_08 - shiftNumber));
172 }
173 if (i > maxAddressArrayIndex) {
174 TELEPHONY_LOGE("Index is over the unpackData length");
175 return false;
176 }
177 if (flag) {
178 if (currentValue == HEX_VALUE_1B) {
179 unpackData[i] = ' ';
180 } else {
181 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
182 }
183 flag = false;
184 } else if (currentValue == HEX_VALUE_1B) {
185 flag = true;
186 } else {
187 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
188 }
189 }
190 return true;
191 }
192
DigitToBcd(const char * digit,uint8_t digitLen,uint8_t * bcd,uint8_t bcdLen,uint8_t & len)193 bool GsmSmsCommonUtils::DigitToBcd(const char *digit, uint8_t digitLen, uint8_t *bcd, uint8_t bcdLen, uint8_t &len)
194 {
195 if (digit == nullptr || bcd == nullptr || len >= bcdLen) {
196 TELEPHONY_LOGE("data error.");
197 return false;
198 }
199
200 len = 0;
201 for (uint8_t i = 0; i < digitLen; i++) {
202 uint8_t temp = static_cast<uint8_t>(digit[i] - '0');
203 if (len >= bcdLen) {
204 TELEPHONY_LOGE("len invalid.");
205 return false;
206 }
207 if ((i % DIGITAL_STEP) == 0) {
208 bcd[len] = temp & HEX_VALUE_0F;
209 } else {
210 bcd[len++] |= ((temp & HEX_VALUE_0F) << HEX_VALUE_04);
211 }
212 }
213
214 if (len + 1 >= bcdLen) {
215 TELEPHONY_LOGE("len invalid.");
216 return false;
217 }
218 if ((digitLen % DIGITAL_STEP) == 1) {
219 bcd[len++] |= HEX_VALUE_F0;
220 }
221 return true;
222 }
223
BcdToDigit(const uint8_t * bcd,uint8_t bcdLen,std::string & digit,uint8_t maxDigitLen)224 bool GsmSmsCommonUtils::BcdToDigit(const uint8_t *bcd, uint8_t bcdLen, std::string &digit, uint8_t maxDigitLen)
225 {
226 if (bcd == nullptr || bcdLen == 0 || maxDigitLen == 0) {
227 TELEPHONY_LOGE("data error.");
228 return false;
229 }
230 for (uint8_t i = 0; i < bcdLen; i++) {
231 uint8_t temp = bcd[i] & HEX_VALUE_0F;
232 if (digit.size() + MIN_REMAIN_LEN >= maxDigitLen) {
233 TELEPHONY_LOGE("digit size over max");
234 return false;
235 }
236 digit.push_back(BcdToChar(temp));
237 temp = (bcd[i] & HEX_VALUE_F0) >> HEX_VALUE_04;
238 if (temp == HEX_VALUE_0F) {
239 return true;
240 }
241 digit.push_back(BcdToChar(temp));
242 }
243 return true;
244 }
245
BcdToChar(const uint8_t c)246 char GsmSmsCommonUtils::BcdToChar(const uint8_t c)
247 {
248 char temp = static_cast<char>(c + '0');
249 return temp;
250 }
251 } // namespace Telephony
252 } // namespace OHOS