• 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 "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 < dataLen; dstIdx++) {
118         if (shift == 0) {
119             uint8_t oneByte = 0;
120             if (!buffer.ReadByte(oneByte)) {
121                 TELEPHONY_LOGE("ReadByte error");
122                 return true;
123             }
124             unpackData[dstIdx] = oneByte & HEX_VALUE_7F;
125             shift = SMS_ENCODE_GSM_BIT;
126             dstIdx++;
127             if (dstIdx >= dataLen) {
128                 break;
129             }
130         }
131 
132         uint8_t oneByte = 0;
133         if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
134             TELEPHONY_LOGE("PickOneByteFromIndex error");
135             return true;
136         }
137         if (shift == 1) {
138             unpackData[dstIdx] = (oneByte >> shift);
139             unpackData[dstIdx] &= HEX_VALUE_7F;
140         } else {
141             uint8_t nextByte = 0;
142             if (!buffer.PickOneByte(nextByte)) {
143                 TELEPHONY_LOGE("PickOneByte error");
144                 return true;
145             }
146             unpackData[dstIdx] = (oneByte >> shift) + (nextByte << (SMS_BYTE_BIT - shift));
147             unpackData[dstIdx] &= HEX_VALUE_7F;
148         }
149         shift--;
150         if (shift > 0) {
151             buffer.MoveForward(1);
152         }
153     }
154     return true;
155 }
156 
Unpack7bitCharForMiddlePart(const uint8_t * buffer,uint8_t dataLen,uint8_t * unpackData)157 bool GsmSmsCommonUtils::Unpack7bitCharForMiddlePart(const uint8_t *buffer, uint8_t dataLen, uint8_t *unpackData)
158 {
159     if (buffer == nullptr || unpackData == nullptr || dataLen <= 0) {
160         TELEPHONY_LOGE("data error.");
161         return false;
162     }
163     uint8_t maxAddressArrayIndex = 19;
164     bool flag = false;
165     for (uint8_t i = 0; i < dataLen; i++) {
166         uint8_t bitOffsetNumber = HEX_VALUE_07 * i;
167         uint8_t shiftNumber = bitOffsetNumber % HEX_VALUE_08;
168         uint8_t byteOffsetNumber = bitOffsetNumber / HEX_VALUE_08;
169         uint8_t currentValue = (HEX_VALUE_7F) & (buffer[byteOffsetNumber] >> shiftNumber);
170         if (shiftNumber > 1) {
171             currentValue &= HEX_VALUE_7F >> (shiftNumber - 1);
172             currentValue |= HEX_VALUE_7F & (buffer[byteOffsetNumber + 1] << (HEX_VALUE_08 - shiftNumber));
173         }
174         if (i > maxAddressArrayIndex) {
175             TELEPHONY_LOGE("Index is over the unpackData length");
176             return false;
177         }
178         if (flag) {
179             if (currentValue == HEX_VALUE_1B) {
180                 unpackData[i] = ' ';
181             } else {
182                 unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
183             }
184             flag = false;
185         } else if (currentValue == HEX_VALUE_1B) {
186             flag = true;
187         } else {
188             unpackData[i] = TextCoder::Instance().GetUCS2Value(currentValue);
189         }
190     }
191     return true;
192 }
193 
charToBcd(const char c)194 uint8_t GsmSmsCommonUtils::charToBcd(const char c)
195 {
196     if (c == '*') {
197         return HEX_VALUE_0A;
198     } else if (c == '#') {
199         return HEX_VALUE_0B;
200     } else if (c == '+') {
201         return HEX_VALUE_FE;
202     } else {
203         return static_cast<uint8_t>(c - '0');
204     }
205 }
206 
DigitToBcd(const char * digit,uint8_t digitLen,uint8_t * bcd,uint8_t bcdLen,uint8_t & len)207 bool GsmSmsCommonUtils::DigitToBcd(const char *digit, uint8_t digitLen, uint8_t *bcd, uint8_t bcdLen, uint8_t &len)
208 {
209     if (digit == nullptr || bcd == nullptr || len >= bcdLen) {
210         TELEPHONY_LOGE("data error.");
211         return false;
212     }
213     len = 0;
214     for (uint8_t i = 0; i < digitLen; i++) {
215         uint8_t temp = charToBcd(digit[i]);
216         if (temp != HEX_VALUE_FE) {
217             if (len >= bcdLen) {
218                 TELEPHONY_LOGE("len invalid.");
219                 return false;
220             }
221             if ((i % DIGITAL_STEP) == 0) {
222                 bcd[len] = temp & HEX_VALUE_0F;
223             } else {
224                 bcd[len++] |= ((temp & HEX_VALUE_0F) << HEX_VALUE_04);
225             }
226         }
227     }
228 
229     if (len + 1 >= bcdLen) {
230         TELEPHONY_LOGE("len invalid.");
231         return false;
232     }
233     if ((digitLen % DIGITAL_STEP) == 1) {
234         bcd[len++] |= HEX_VALUE_F0;
235     }
236     return true;
237 }
238 
BcdToDigit(const uint8_t * bcd,uint8_t bcdLen,std::string & digit,uint8_t maxDigitLen)239 bool GsmSmsCommonUtils::BcdToDigit(const uint8_t *bcd, uint8_t bcdLen, std::string &digit, uint8_t maxDigitLen)
240 {
241     if (bcd == nullptr || bcdLen == 0 || maxDigitLen == 0) {
242         TELEPHONY_LOGE("data error.");
243         return false;
244     }
245     for (uint8_t i = 0; i < bcdLen; i++) {
246         uint8_t temp = bcd[i] & HEX_VALUE_0F;
247         if (digit.size() + MIN_REMAIN_LEN >= maxDigitLen) {
248             TELEPHONY_LOGE("digit size over max");
249             return false;
250         }
251         digit.push_back(BcdToChar(temp));
252         temp = (bcd[i] & HEX_VALUE_F0) >> HEX_VALUE_04;
253         if (temp == HEX_VALUE_0F) {
254             return true;
255         }
256         digit.push_back(BcdToChar(temp));
257     }
258     return true;
259 }
260 
BcdToChar(const uint8_t b)261 char GsmSmsCommonUtils::BcdToChar(const uint8_t b)
262 {
263     if (b == HEX_VALUE_0A) {
264         return '*';
265     } else if (b == HEX_VALUE_0B) {
266         return '#';
267     }
268     return static_cast<char>('0' + b);
269 }
270 } // namespace Telephony
271 } // namespace OHOS