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 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 offset,int length,int bcdExtType)155 std::string SimNumberDecode::BCDConvertToString(
156 const std::shared_ptr<unsigned char> bytesData, int offset, int length, int bcdExtType)
157 {
158 uint8_t *arr = bytesData.get();
159 if (!arr) {
160 TELEPHONY_LOGE("BCDConvertToString fail because bytesData is nullptr!!");
161 return "";
162 }
163 std::vector<uint8_t> bcdCode;
164 for (int i = INIT_VAL; i < length; ++i) {
165 bcdCode.push_back(arr[offset + i]);
166 }
167 std::string res;
168 if (!BCDConvertToString(bcdCode.begin(), bcdCode.end(), res, bcdExtType)) {
169 TELEPHONY_LOGE("occur error in BCDConvertToString for '%{public}s by bcdExtType:%{public}d",
170 HexToStr(bcdCode).c_str(), bcdExtType);
171 }
172 return res;
173 }
174
BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)175 bool SimNumberDecode::BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
176 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
177 {
178 for (std::vector<uint8_t>::const_iterator it = codeBeg; it != codeEnd; ++it) {
179 uint8_t loFourBit = (*it & LO_FOUR);
180 char c = INIT_VAL;
181 if (!BcdToChar(loFourBit, c, bcdExtType)) {
182 TELEPHONY_LOGE(
183 "occur error in BcdToChar(bcd:'%{public}d',bcdExtType:'%{public}d')", loFourBit, bcdExtType);
184 return false;
185 }
186 number.push_back(c);
187 uint8_t hiFourBit = (*it >> SHIFT_FLAG) & HALF_BYTE;
188 if (hiFourBit == HALF_BYTE && (it + INC_ONE) == codeEnd) {
189 break;
190 }
191 if (!BcdToChar(hiFourBit, c, bcdExtType)) {
192 TELEPHONY_LOGE(
193 "occur error in BcdToChar(bcd:'%{public}d',bcdExtType:'%{public}d')", loFourBit, bcdExtType);
194 return false;
195 }
196 number.push_back(c);
197 }
198 return true;
199 }
200
BCDConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)201 bool SimNumberDecode::BCDConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
202 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
203 {
204 if (codeBeg == codeEnd) {
205 TELEPHONY_LOGE("occur error by iterator");
206 return false;
207 }
208 std::vector<uint8_t>::const_iterator it = codeBeg;
209 const bool prependPlus = (*it == FLAG_INTERNATIONAL);
210 ++it;
211 if (!BCDSectionConvertToString(it, codeEnd, number, bcdExtType)) {
212 TELEPHONY_LOGE(
213 "occur error to BCDSectionConvertToString by codes:'%{public}s' and bcdExtType:'%{public}d'",
214 HexToStr(std::vector<uint8_t>(it, codeEnd)).c_str(), bcdExtType);
215 }
216 if (!prependPlus) {
217 return true;
218 }
219 if (number.empty() || !IsValidNumberString(number)) {
220 TELEPHONY_LOGE("occur error at number after parse!! number");
221 return false;
222 }
223
224 std::string::const_iterator numIt = number.begin();
225 /* not start with [#*] just prepend '+' */
226 if (!IsSharpStar(number.front())) {
227 number.insert(number.begin(), '+');
228 return true;
229 }
230 ++numIt;
231 /* started with two [#*] ends with # ,just append a + */
232 if (IsSharpStar(*numIt) && (number.back() == '#')) {
233 number.push_back('+');
234 return true;
235 }
236 while ((numIt != number.end()) && IsPlusNumber(*numIt)) {
237 ++numIt;
238 }
239 /* start with [#*] ;assume the data after last;insert head of data a + */
240 if ((numIt != number.end()) && (numIt + INC_ONE != number.end()) && IsSharpStar(*numIt)) {
241 number.insert(numIt + INC_ONE, '+');
242 }
243 return true;
244 }
245 } // namespace Telephony
246 } // namespace OHOS
247