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