• 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 #include "code_rule.h"
16 #include "i18n_hilog.h"
17 #include "phonenumbers/phonenumberutil.h"
18 #include "phonenumbers/phonenumber.h"
19 #include "phonenumbers/shortnumberinfo.h"
20 
21 namespace OHOS {
22 namespace Global {
23 namespace I18n {
24 using i18n::phonenumbers::PhoneNumberMatch;
25 using i18n::phonenumbers::PhoneNumber;
26 using i18n::phonenumbers::PhoneNumberUtil;
27 using i18n::phonenumbers::ShortNumberInfo;
28 
CodeRule(std::string & isValidType)29 CodeRule::CodeRule(std::string& isValidType)
30 {
31     this->isValidType = isValidType;
32 }
33 
CountDigits(icu::UnicodeString & str)34 int CodeRule::CountDigits(icu::UnicodeString& str)
35 {
36     int count = 0;
37     int len = str.length();
38     for (int i = 0; i < len; i++) {
39         if (u_isdigit(str[i])) {
40             count++;
41         }
42     }
43     return count;
44 }
IsValid(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)45 PhoneNumberMatch* CodeRule::IsValid(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
46 {
47     if (isValidType == "PreSuf") {
48         return IsValidPreSuf(possibleNumber, message);
49     } else if (isValidType == "Code") {
50         return IsValidCode(possibleNumber, message);
51     } else if (isValidType == "Rawstr") {
52         return IsValidRawstr(possibleNumber, message);
53     }
54     return IsValidDefault(possibleNumber, message);
55 }
56 
57 // Check the preifx or suffix of possibleNumber
IsValidPreSuf(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)58 PhoneNumberMatch* CodeRule::IsValidPreSuf(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
59 {
60     if (possibleNumber->start() - 1 >= 0) {
61         return IsValidStart(possibleNumber, message);
62     }
63     if (possibleNumber->end() <= message.length() - 1) {
64         return IsValidEnd(possibleNumber, message);
65     }
66     return possibleNumber;
67 }
68 
69 // check the suffix of possibleNumber
IsValidEnd(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)70 PhoneNumberMatch* CodeRule::IsValidEnd(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
71 {
72     icu::UnicodeString after = message.tempSubString(possibleNumber->end());
73     bool isTwo = true;
74     int len = after.length();
75     // check the 1st and 2nd char of the suffix.
76     for (int i = 0; i < len; i++) {
77         UChar32 afterChar = after[i];
78         if (i == 0 && !u_isUUppercase(afterChar)) {
79             isTwo = false;
80             break;
81         }
82         // 2 is the third position in the string.
83         if (i < 2 && u_isUAlphabetic(afterChar)) {
84             if (u_isUUppercase(afterChar)) {
85                 continue;
86             } else {
87                 isTwo = false;
88                 break;
89             }
90         }
91         // 1 and 2 are the second and third position in the string, respectively.
92         if (i == 1 || i == 2) {
93             if (afterChar == '-' || afterChar == '\'') {
94                 isTwo = false;
95                 break;
96             } else if (u_isdigit(afterChar) || u_isspace(afterChar)) {
97                 break;
98             } else if (!u_isUAlphabetic(afterChar)) {
99                 break;
100             } else {
101                 isTwo = false;
102                 break;
103             }
104         }
105     }
106     return isTwo ? nullptr : possibleNumber;
107 }
108 
109 // check the prefix of possibleNumber
IsValidStart(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)110 PhoneNumberMatch* CodeRule::IsValidStart(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
111 {
112     icu::UnicodeString before = message.tempSubString(0, possibleNumber->start());
113     bool isTwo = true;
114     int len = before.length();
115     for (int i = 0; i < len; i++) {
116         char beforeChar = before[len - 1 - i];
117         if (i == 0 && !u_isUUppercase(beforeChar)) {
118             isTwo = false;
119             break;
120         }
121         // 2 is the third position in the string.
122         if (i < 2 && u_isUAlphabetic(beforeChar)) {
123             if (u_isUUppercase(beforeChar)) {
124                 continue;
125             } else {
126                 isTwo = false;
127                 break;
128             }
129         }
130         if (beforeChar == '-' || beforeChar == '\'') {
131             isTwo = false;
132             break;
133         } else if (u_isdigit(beforeChar) || u_isspace(beforeChar)) {
134             break;
135         } else if (!u_isUAlphabetic(beforeChar)) {
136             break;
137         } else {
138             isTwo = false;
139             break;
140         }
141     }
142     return isTwo ? nullptr : possibleNumber;
143 }
144 
IsValidDefault(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)145 PhoneNumberMatch* CodeRule::IsValidDefault(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
146 {
147     return possibleNumber;
148 }
149 
PrefixValid(icu::UnicodeString & number,int length)150 bool CodeRule::PrefixValid(icu::UnicodeString& number, int length)
151 {
152     icu::UnicodeString preNumber = number.tempSubString(0, length);
153     if (length == 1) {
154         if (number[0] == '0' || number[0] == '1' || number[0] == '+') {
155             return true;
156         }
157     // 3 indicates the first three digits of a phone number.
158     } else if (length == 3) {
159         if (preNumber == "400" || preNumber == "800") {
160             return true;
161         }
162     // 5 indicates the first five digits of a phone number.
163     } else if (length == 5) {
164         if (preNumber == "11808" || preNumber == "17909" || preNumber == "12593" ||
165             preNumber == "17951" || preNumber == "17911") {
166             return true;
167         }
168     }
169     return false;
170 }
171 
NumberValid(icu::UnicodeString & number)172 bool CodeRule::NumberValid(icu::UnicodeString& number)
173 {
174     if (number.length() < 1) {
175         return false;
176     }
177     int lengthOne = 1;
178     // 3 indicates the first three digits of a phone number.
179     int lengthThree = 3;
180     // 11 is the number of digits in the phone number.
181     if (number[0] == '1' && CountDigits(number) > 11) {
182         // 5 indicates the first five digits of a phone number.
183         int lengthFive = 5;
184         if (!PrefixValid(number, lengthFive)) {
185             return false;
186         }
187     // 12 is the number of digits, 0 and 1 indicate the first and second position, respectively.
188     } else if (number[0] == '0' && CountDigits(number) > 12 && number[1] != '0') {
189         return false;
190     // 10 is the number of digits in the phone number.
191     } else if (PrefixValid(number, lengthThree) && CountDigits(number) != 10) {
192         return false;
193     // 9 is the number of digits in the phone number.
194     } else if (!PrefixValid(number, lengthOne) && !PrefixValid(number, lengthThree) && CountDigits(number) >= 9) {
195         if (number.trim()[0] != '9' && number.trim()[0] != '1') {
196             return false;
197         }
198     // 4 is the number of digits in the phone number.
199     } else if (CountDigits(number) <= 4) {
200         return false;
201     }
202     return true;
203 }
204 
IsValidCode(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)205 PhoneNumberMatch* CodeRule::IsValidCode(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
206 {
207     if (possibleNumber == nullptr) {
208         return nullptr;
209     }
210     icu::UnicodeString number = possibleNumber->raw_string().c_str();
211     // Processes the ;ext= extention number format
212     int32_t ind = number.trim().indexOf(";ext=");
213     if (ind != -1) {
214         number = number.trim().tempSubString(0, ind);
215     }
216     if (number[0] == '(' || number[0] == '[') {
217         StartWithBrackets(number);
218     }
219     if (!NumberValid(number)) {
220         return nullptr;
221     }
222     return possibleNumber;
223 }
224 
IsValidRawstr(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)225 PhoneNumberMatch* CodeRule::IsValidRawstr(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
226 {
227     if (possibleNumber == nullptr) {
228         return nullptr;
229     }
230     icu::UnicodeString number = possibleNumber->raw_string().c_str();
231     // Processes the ;ext= extention number format
232     int32_t ind = number.trim().indexOf(";ext=");
233     if (ind != -1) {
234         number = number.trim().tempSubString(0, ind);
235     }
236     if (number[0] == '(' || number[0] == '[') {
237         number = number.tempSubString(1);
238     }
239     // 8 and 4 is the number of digits in the phone number.
240     if ((number[0] != '0' && CountDigits(number) == 8) || CountDigits(number) <= 4) {
241         return nullptr;
242     }
243     return possibleNumber;
244 }
245 
246 // Handle phone number starting with '(' or '['
StartWithBrackets(icu::UnicodeString & number)247 void CodeRule::StartWithBrackets(icu::UnicodeString& number)
248 {
249     icu::UnicodeString right = "";
250     if (number[0] == '(') {
251         right = ')';
252     }
253     if (number[0] == '[') {
254         right = ']';
255     }
256     int neind = number.indexOf(right);
257     if (neind != -1) {
258         icu::UnicodeString phoneStr = number.tempSubString(0, neind);
259         int phoneLength = CountDigits(phoneStr);
260         icu::UnicodeString extraStr = number.tempSubString(neind);
261         int extra = CountDigits(extraStr);
262         // 4 is the number of numbers in parentheses, 1 and 2 are the number of numbers outside parentheses.
263         bool flag = (phoneLength > 4) && (extra == 1 || extra == 2);
264         number = flag ? number.tempSubString(1, neind - 1) : number.tempSubString(1);
265     } else {
266         number = number.tempSubString(1);
267     }
268 }
269 
Handle(PhoneNumberMatch * phoneNumberMatch,icu::UnicodeString & message)270 PhoneNumberMatch* CodeRule::Handle(PhoneNumberMatch* phoneNumberMatch, icu::UnicodeString& message)
271 {
272     if (phoneNumberMatch == nullptr) {
273         return nullptr;
274     }
275     return IsValid(phoneNumberMatch, message);
276 }
277 } // namespace I18n
278 } // namespace Global
279 } // namespace OHOS