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 TELEPHONY_LOGI(
77 "SimNumberDecode::CharToBCD begin with:char'%{public}c' and bcdExtType:'%{public}d'", c, bcdExtType);
78 if (c >= '0' && c <= '9') {
79 result = c - '0';
80 TELEPHONY_LOGI("SimNumberDecode::CharToBCD end with:result '%{public}d'", result);
81 return true;
82 }
83 const std::string *extendedPtr = chooseExtendedByType(bcdExtType);
84 if (!extendedPtr) {
85 TELEPHONY_LOGE("Unknow bcdExtType:[%{public}d]", bcdExtType);
86 return false;
87 }
88 const std::string &extended = *extendedPtr;
89 const size_t chrIdx = extended.find(c);
90 if (chrIdx == std::string::npos) {
91 TELEPHONY_LOGE("invalid char for BCD %{public}d", c);
92 return false;
93 }
94 result = static_cast<uint8_t>(chrIdx + CHAR_START);
95 TELEPHONY_LOGI("SimNumberDecode::CharToBCD end with:result '%{public}d'", result);
96 return true;
97 }
98
BcdToChar(const uint8_t bcdCode,char & result,const int bcdExtType)99 bool SimNumberDecode::BcdToChar(const uint8_t bcdCode, char &result, const int bcdExtType)
100 {
101 TELEPHONY_LOGI("SimNumberDecode::BcdToChar begin with:bcdCode'%{public}d' and bcdExtType:'%{public}d'",
102 bcdCode, bcdExtType);
103 const int32_t surplus = static_cast<int32_t>(bcdCode) - CHAR_START;
104 if (surplus < INIT_VAL) {
105 result = '0' + bcdCode;
106 return true;
107 }
108 const std::string *extendedPtr = chooseExtendedByType(bcdExtType);
109 if (!extendedPtr) {
110 TELEPHONY_LOGE("Unknow bcdExtType:[%{public}d]", bcdExtType);
111 return false;
112 }
113 if (static_cast<size_t>(surplus) >= extendedPtr->size()) {
114 TELEPHONY_LOGE("Unknow bcdCode:[%{public}d]", bcdCode);
115 return false;
116 }
117 result = extendedPtr->at(surplus);
118 TELEPHONY_LOGI("SimNumberDecode::BcdToChar success end with result:'%{public}c'", result);
119 return true;
120 }
121
NumberConvertToBCD(const std::string & number,std::vector<uint8_t> & bcdCodes,const bool includeLen,const int bcdExtType)122 bool SimNumberDecode::NumberConvertToBCD(
123 const std::string &number, std::vector<uint8_t> &bcdCodes, const bool includeLen, const int bcdExtType)
124 {
125 TELEPHONY_LOGI(
126 "SimNumberDecode::NumberConvertToBCD begin_B with "
127 "number,isCludeLen:%{public}d,bcdExtType:%{public}d",
128 includeLen, bcdExtType);
129 const bool hasPlus = (number.find('+') != std::string::npos);
130 uint8_t length = number.length();
131 if (hasPlus) {
132 --length;
133 }
134 if (includeLen) {
135 bcdCodes.push_back(length);
136 }
137 bcdCodes.push_back(hasPlus ? FLAG_INTERNATIONAL : FLAG_UNKNOWN);
138
139 size_t count = INIT_VAL;
140 for (const auto &num : number) {
141 if (num == '+') {
142 continue;
143 }
144 uint8_t code = INIT_VAL;
145 if (!CharToBCD(num, code, bcdExtType)) {
146 TELEPHONY_LOGI("occur error in CharToBCD(num:'%{public}d',bcdExtType:'%{public}d')", num, bcdExtType);
147 return false;
148 }
149 if (count % EVEN == 1) {
150 bcdCodes.back() |= (code << FOUR_BIT);
151 } else {
152 bcdCodes.push_back(code);
153 }
154 ++count;
155 }
156 if (count % EVEN == 1) {
157 bcdCodes.back() |= HI_FOUR;
158 }
159 TELEPHONY_LOGI(
160 "SimNumberDecode::NumberConvertToBCD success end_B with result:'%{publci}s'", HexToStr(bcdCodes).c_str());
161 return true;
162 }
163
BCDConvertToString(const std::shared_ptr<unsigned char> bytesData,int offset,int length,int bcdExtType)164 std::string SimNumberDecode::BCDConvertToString(
165 const std::shared_ptr<unsigned char> bytesData, int offset, int length, int bcdExtType)
166 {
167 uint8_t *arr = bytesData.get();
168 if (!arr) {
169 TELEPHONY_LOGE("BCDConvertToString fail because bytesData is nullptr!!");
170 return "";
171 }
172 std::vector<uint8_t> bcdCode;
173 for (int i = INIT_VAL; i < length; ++i) {
174 bcdCode.push_back(arr[offset + i]);
175 }
176 std::string res;
177 if (!BCDConvertToString(bcdCode.begin(), bcdCode.end(), res, bcdExtType)) {
178 TELEPHONY_LOGE("occur error in BCDConvertToString for '%{public}s by bcdExtType:%{public}d",
179 HexToStr(bcdCode).c_str(), bcdExtType);
180 return "";
181 }
182 return res;
183 }
184
BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)185 bool SimNumberDecode::BCDSectionConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
186 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
187 {
188 TELEPHONY_LOGI(
189 "SimNumberDecode::BCDSectionConvertToString begin with codes:'%{public}s' and bcdExtType:'%{public}d'",
190 HexToStr(std::vector<uint8_t>(codeBeg, codeEnd)).c_str(), bcdExtType);
191 for (std::vector<uint8_t>::const_iterator it = codeBeg; it != codeEnd; ++it) {
192 uint8_t loFourBit = (*it & LO_FOUR);
193 char c = INIT_VAL;
194 if (!BcdToChar(loFourBit, 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 uint8_t hiFourBit = (*it >> SHIFT_FLAG) & HALF_BYTE;
201 if (hiFourBit == HALF_BYTE && (it + INC_ONE) == codeEnd) {
202 break;
203 }
204 if (!BcdToChar(hiFourBit, c, bcdExtType)) {
205 TELEPHONY_LOGE(
206 "occur error in BcdToChar(bcd:'%{public}d',bcdExtType:'%{public}d')", loFourBit, bcdExtType);
207 return false;
208 }
209 number.push_back(c);
210 }
211 return true;
212 }
213
BCDConvertToString(const std::vector<uint8_t>::const_iterator & codeBeg,const std::vector<uint8_t>::const_iterator & codeEnd,std::string & number,const int bcdExtType)214 bool SimNumberDecode::BCDConvertToString(const std::vector<uint8_t>::const_iterator &codeBeg,
215 const std::vector<uint8_t>::const_iterator &codeEnd, std::string &number, const int bcdExtType)
216 {
217 TELEPHONY_LOGI("SimNumberDecode::BCDConvertToString begin with codes:'%{public}s' and bcdExtType:'%{public}d'",
218 HexToStr(std::vector<uint8_t>(codeBeg, codeEnd)).c_str(), bcdExtType);
219 std::vector<uint8_t>::const_iterator it = codeBeg;
220 const bool prependPlus = (*it == FLAG_INTERNATIONAL);
221 ++it;
222 if (!BCDSectionConvertToString(it, codeEnd, number, bcdExtType)) {
223 TELEPHONY_LOGE(
224 "occur error to BCDSectionConvertToString by codes:'%{public}s' and bcdExtType:'%{public}d'",
225 HexToStr(std::vector<uint8_t>(it, codeEnd)).c_str(), bcdExtType);
226 return false;
227 }
228 if (!prependPlus) {
229 return true;
230 }
231 if (number.empty() || !IsValidNumberString(number)) {
232 TELEPHONY_LOGE("occur error at number after parse!! number");
233 return false;
234 }
235
236 std::string::const_iterator numIt = number.begin();
237 /* not start with [#*] just prepend '+' */
238 if (!IsSharpStar(number.front())) {
239 number.insert(number.begin(), '+');
240 return true;
241 }
242 ++numIt;
243 /* started with two [#*] ends with # ,just append a + */
244 if (IsSharpStar(*numIt) && (number.back() == '#')) {
245 number.push_back('+');
246 return true;
247 }
248 while ((numIt != number.end()) && IsPlusNumber(*numIt)) {
249 ++numIt;
250 }
251 /* start with [#*] ;assume the data after last;insert head of data a + */
252 if ((numIt != number.end()) && (numIt + INC_ONE != number.end()) && IsSharpStar(*numIt)) {
253 number.insert(numIt + INC_ONE, '+');
254 }
255 return true;
256 }
257 } // namespace Telephony
258 } // namespace OHOS
259