• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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