• 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     bool isValid = true;
211     icu::UnicodeString number = possibleNumber->raw_string().c_str();
212     // Processes the ;ext= extention number format
213     int32_t ind = number.trim().indexOf(";ext=");
214     if (ind != -1) {
215         number = number.trim().tempSubString(0, ind);
216     }
217     if (number[0] == '(' || number[0] == '[') {
218         StartWithBrackets(number);
219     }
220     isValid = NumberValid(number);
221     if (isValid) {
222         return possibleNumber;
223     } else {
224         return nullptr;
225     }
226 }
227 
IsValidRawstr(PhoneNumberMatch * possibleNumber,icu::UnicodeString & message)228 PhoneNumberMatch* CodeRule::IsValidRawstr(PhoneNumberMatch* possibleNumber, icu::UnicodeString& message)
229 {
230     if (possibleNumber == nullptr) {
231         return nullptr;
232     }
233     bool isValid = true;
234     icu::UnicodeString number = possibleNumber->raw_string().c_str();
235     // Processes the ;ext= extention number format
236     int32_t ind = number.trim().indexOf(";ext=");
237     if (ind != -1) {
238         number = number.trim().tempSubString(0, ind);
239     }
240     if (number[0] == '(' || number[0] == '[') {
241         number = number.tempSubString(1);
242     }
243     // 8 is the number of digits in the phone number.
244     if (number[0] != '0' && CountDigits(number) == 8) {
245         isValid = false;
246     }
247     // 4 is the number of digits in the phone number.
248     if (CountDigits(number) <= 4) {
249         isValid = false;
250     }
251     if (isValid) {
252         return possibleNumber;
253     } else {
254         return nullptr;
255     }
256 }
257 
258 // Handle phone number starting with '(' or '['
StartWithBrackets(icu::UnicodeString & number)259 void CodeRule::StartWithBrackets(icu::UnicodeString& number)
260 {
261     icu::UnicodeString right = "";
262     if (number[0] == '(') {
263         right = ')';
264     }
265     if (number[0] == '[') {
266         right = ']';
267     }
268     int neind = number.indexOf(right);
269     if (neind != -1) {
270         icu::UnicodeString phoneStr = number.tempSubString(0, neind);
271         int phoneLength = CountDigits(phoneStr);
272         icu::UnicodeString extraStr = number.tempSubString(neind);
273         int extra = CountDigits(extraStr);
274         // 4 is the number of numbers in parentheses, 1 and 2 are the number of numbers outside parentheses.
275         bool flag = (phoneLength > 4) && (extra == 1 || extra == 2);
276         number = flag ? number.tempSubString(1, neind - 1) : number.tempSubString(1);
277     } else {
278         number = number.tempSubString(1);
279     }
280 }
281 
Handle(PhoneNumberMatch * phoneNumberMatch,icu::UnicodeString & message)282 PhoneNumberMatch* CodeRule::Handle(PhoneNumberMatch* phoneNumberMatch, icu::UnicodeString& message)
283 {
284     if (phoneNumberMatch == nullptr) {
285         return nullptr;
286     }
287     return IsValid(phoneNumberMatch, message);
288 }
289 } // namespace I18n
290 } // namespace Global
291 } // namespace OHOS