1 /*
2 * Copyright (C) 2021 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 "sim_number_decode.h"
17 #include <set>
18 #include <sstream>
19 #include <iomanip>
20
21 using namespace std;
22
23 namespace OHOS {
24 namespace Telephony {
HexToStr(const std::vector<uint8_t> & arr)25 [[maybe_unused]] static std::string HexToStr(const std::vector<uint8_t> &arr)
26 {
27 std::stringstream ss;
28 for (const auto &v : arr) {
29 ss << std::hex << std::uppercase << std::setw(NEW_WIDTH) << std::setfill('0') << v;
30 }
31 return ss.str();
32 }
33
IsNumber(const char num)34 inline static bool IsNumber(const char num)
35 {
36 return (num >= '0' && num <= '9');
37 }
38
IsPlusNumber(const char num)39 inline static bool IsPlusNumber(const char num)
40 {
41 return IsNumber(num) || (num == '+');
42 }
43
IsSharpStar(const char num)44 inline static bool IsSharpStar(const char num)
45 {
46 return num == '#' || num == '*';
47 }
48
IsValidNumberChar(const char num)49 inline static bool IsValidNumberChar(const char num)
50 {
51 return IsPlusNumber(num) || IsSharpStar(num);
52 }
53
IsValidNumberString(const std::string & number)54 bool SimNumberDecode::IsValidNumberString(const std::string &number)
55 {
56 for (const auto &num : number) {
57 if (!IsValidNumberChar(num)) {
58 return false;
59 }
60 }
61 return true;
62 }
63
chooseExtendedByType(const int bcdExtType)64 const std::string *SimNumberDecode::chooseExtendedByType(const int bcdExtType)
65 {
66 if (bcdExtType == BCD_TYPE_ADN) {
67 return &BCD_ADN_EXTENTION;
68 } else if (bcdExtType == BCD_TYPE_CALLER) {
69 return &BCD_CALLER_EXTENTION;
70 }
71 return nullptr;
72 }
73
CharToBCD(const char c,uint8_t & result,const int bcdExtType)74 bool SimNumberDecode::CharToBCD(const char c, uint8_t &result, const int bcdExtType)
75 {
76 if (c >= '0' && c <= '9') {
77 result = c - '0';
78 return true;
79 }
80 const std::string *extendedPtr = chooseExtendedByType(bcdExtType);
81 if (!extendedPtr) {
82 TELEPHONY_LOGE("Unknow bcdExtType:[%{public}d]", bcdExtType);
83 return false;
84 }
85 const std::string &extended = *extendedPtr;
86 const size_t chrIdx = extended.find(c);
87 if (chrIdx == std::string::npos) {
88 TELEPHONY_LOGE("invalid char for BCD %{public}d", c);
89 return false;
90 }
91 result = static_cast<uint8_t>(chrIdx + CHAR_START);
92 return true;
93 }
94
BcdToChar(const uint8_t bcdCode,char & result,const int bcdExtType)95 bool SimNumberDecode::BcdToChar(const uint8_t bcdCode, char &result, const int bcdExtType)
96 {
97 const int32_t surplus = static_cast<int32_t>(bcdCode) - CHAR_START;
98 if (surplus < INIT_VAL) {
99 result = '0' + bcdCode;
100 return true;
101 }
102 const std::string *extendedPtr = chooseExtendedByType(bcdExtType);
103 if (!extendedPtr) {
104 TELEPHONY_LOGE("Unknow bcdExtType:[%{public}d]", bcdExtType);
105 return false;
106 }
107 if (static_cast<size_t>(surplus) >= extendedPtr->size()) {
108 TELEPHONY_LOGE("Unknow bcdCode:[%{public}d]", bcdCode);
109 return false;
110 }
111 result = extendedPtr->at(surplus);
112 return true;
113 }
114
NumberConvertToBCD(const std::string & number,std::vector<uint8_t> & bcdCodes,const bool includeLen,const int bcdExtType)115 bool SimNumberDecode::NumberConvertToBCD(
116 const std::string &number, std::vector<uint8_t> &bcdCodes, const bool includeLen, const int bcdExtType)
117 {
118 TELEPHONY_LOGI(
119 "SimNumberDecode::NumberConvertToBCD begin_B with "
120 "number,isCludeLen:%{public}d,bcdExtType:%{public}d",
121 includeLen, bcdExtType);
122 const bool hasPlus = (number.find('+') != std::string::npos);
123 uint8_t length = number.length();
124 if (hasPlus) {
125 --length;
126 }
127 if (includeLen) {
128 bcdCodes.push_back(length);
129 }
130 bcdCodes.push_back(hasPlus ? FLAG_INTERNATIONAL : FLAG_UNKNOWN);
131
132 size_t count = INIT_VAL;
133 for (const auto &num : number) {
134 if (num == '+') {
135 continue;
136 }
137 uint8_t code = INIT_VAL;
138 if (!CharToBCD(num, code, bcdExtType)) {
139 TELEPHONY_LOGI("occur error in CharToBCD(num:'%{public}d',bcdExtType:'%{public}d')", num, bcdExtType);
140 return false;
141 }
142 if (count % EVEN == 1) {
143 bcdCodes.back() |= (code << FOUR_BIT);
144 } else {
145 bcdCodes.push_back(code);
146 }
147 ++count;
148 }
149 if (count % EVEN == 1) {
150 bcdCodes.back() |= HI_FOUR;
151 }
152 return true;
153 }
154
BCDConvertToString(const std::shared_ptr<unsigned char> bytesData,int dataLength,int offset,int length,int bcdExtType)155 std::string SimNumberDecode::BCDConvertToString(
156 const std::shared_ptr<unsigned char> bytesData, int dataLength, int offset, int length, int bcdExtType)
157 {
158 uint8_t *arr = bytesData.get();
159 if (!arr) {
160 TELEPHONY_LOGE("BCDConvertToString fail because arr is nullptr!!");
161 return "";
162 }
163 if (offset + length > dataLength) {
164 TELEPHONY_LOGE("BCDConvertToString fail because bytesData length error!!");
165 return "";
166 }
167 std::vector<uint8_t> bcdCode;
168 for (int i = INIT_VAL; i < length; ++i) {
169 bcdCode.push_back(arr[offset + i]);
170 }
171 std::string res;
172 if (!BCDConvertToString(bcdCode.begin(), bcdCode.end(), res, bcdExtType)) {
173 TELEPHONY_LOGE("occur error in BCDConvertToString bcdExtType: %{public}d", bcdExtType);
174 }
175 return res;
176 }
177
BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)178 bool SimNumberDecode::BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
179 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
180 {
181 for (std::vector<uint8_t>::const_iterator it = codeBeg; it != codeEnd; ++it) {
182 uint8_t loFourBit = (*it & LO_FOUR);
183 char c = INIT_VAL;
184 if (!BcdToChar(loFourBit, c, bcdExtType)) {
185 TELEPHONY_LOGE(
186 "occur error in BcdToChar(bcd:'%{public}d',bcdExtType:'%{public}d')", loFourBit, bcdExtType);
187 return false;
188 }
189 number.push_back(c);
190 uint8_t hiFourBit = (*it >> SHIFT_FLAG) & HALF_BYTE;
191 if (hiFourBit == HALF_BYTE && (it + INC_ONE) == codeEnd) {
192 break;
193 }
194 if (!BcdToChar(hiFourBit, c, bcdExtType)) {
195 TELEPHONY_LOGE(
196 "occur error in BcdToChar(bcd:'%{public}d',bcdExtType:'%{public}d')", loFourBit, bcdExtType);
197 return false;
198 }
199 number.push_back(c);
200 }
201 return true;
202 }
203
BCDConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)204 bool SimNumberDecode::BCDConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
205 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
206 {
207 if (codeBeg == codeEnd) {
208 TELEPHONY_LOGE("occur error by iterator");
209 return false;
210 }
211 std::vector<uint8_t>::const_iterator it = codeBeg;
212 const bool prependPlus = (*it == FLAG_INTERNATIONAL);
213 ++it;
214 if (!BCDSectionConvertToString(it, codeEnd, number, bcdExtType)) {
215 TELEPHONY_LOGE("BCDConvertToString occur error to BCDSectionConvertToString bcdExtType: %{public}d",
216 bcdExtType);
217 }
218 if (!prependPlus) {
219 return true;
220 }
221 if (number.empty() || !IsValidNumberString(number)) {
222 TELEPHONY_LOGE("occur error at number after parse!! number");
223 return false;
224 }
225
226 std::string::const_iterator numIt = number.begin();
227 /* not start with [#*] just prepend '+' */
228 if (!IsSharpStar(number.front())) {
229 number.insert(number.begin(), '+');
230 return true;
231 }
232 ++numIt;
233 /* started with two [#*] ends with # ,just append a + */
234 if (IsSharpStar(*numIt) && (number.back() == '#')) {
235 number.push_back('+');
236 return true;
237 }
238 while ((numIt != number.end()) && IsPlusNumber(*numIt)) {
239 ++numIt;
240 }
241 /* start with [#*] ;assume the data after last;insert head of data a + */
242 if ((numIt != number.end()) && (numIt + INC_ONE != number.end()) && IsSharpStar(*numIt)) {
243 number.insert(numIt + INC_ONE, '+');
244 }
245 return true;
246 }
247
ExtensionBCDConvertToString(const std::shared_ptr<unsigned char> bytesData,int dataLength,int offset,int length,int bcdExtType)248 std::string SimNumberDecode::ExtensionBCDConvertToString(
249 const std::shared_ptr<unsigned char> bytesData, int dataLength, int offset, int length, int bcdExtType)
250 {
251 uint8_t *arr = bytesData.get();
252 if (!arr) {
253 TELEPHONY_LOGE("ExtensionBCDConvertToString fail because arr is nullptr!!");
254 return "";
255 }
256 if (offset + length > dataLength) {
257 TELEPHONY_LOGE("ExtensionBCDConvertToString fail because bytesData length error!!");
258 return "";
259 }
260 std::vector<uint8_t> bcdCode;
261 for (int i = INIT_VAL; i < length; ++i) {
262 bcdCode.push_back(arr[offset + i]);
263 }
264 std::string res;
265 if (!BCDSectionConvertToString(bcdCode.begin(), bcdCode.end(), res, bcdExtType)) {
266 TELEPHONY_LOGE("ExtensionBCDConvertToString occur error in BCDSectionConvertToString bcdExtType: %{public}d",
267 bcdExtType);
268 }
269 return res;
270 }
271 } // namespace Telephony
272 } // namespace OHOS
273