• 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 <cctype>
16 #include <filesystem>
17 #include "phonenumbers/phonenumber.h"
18 #include "phonenumbers/shortnumberinfo.h"
19 #include "phonenumbers/phonenumberutil.h"
20 #include "i18n_hilog.h"
21 #include "libxml/globals.h"
22 #include "libxml/tree.h"
23 #include "libxml/xmlstring.h"
24 #include "matched_number_info.h"
25 #include "phone_number_rule.h"
26 #include "utils.h"
27 
28 namespace OHOS {
29 namespace Global {
30 namespace I18n {
31 using i18n::phonenumbers::PhoneNumber;
32 using i18n::phonenumbers::PhoneNumberUtil;
33 using i18n::phonenumbers::ShortNumberInfo;
34 
35 const std::string PhoneNumberRule::XML_COMMON_PATH = "/system/usr/ohos_locale_config/phonenumber/";
36 const std::string PhoneNumberRule::XML_COMMON_FILE = "common.xml";
37 
PhoneNumberRule(std::string & country)38 PhoneNumberRule::PhoneNumberRule(std::string& country)
39 {
40     xmlPath = XML_COMMON_PATH + country + ".xml";
41     isFixed = true;
42     try {
43         isFixed = std::filesystem::exists(xmlPath);
44     } catch (const std::filesystem::filesystem_error &except) {
45         HILOG_ERROR_I18N("FileExist failed because filesystem_error, error message: %{public}s.",
46             except.code().message().c_str());
47         isFixed = false;
48     } catch (const std::__h::__fs::filesystem::filesystem_error &except) {
49         HILOG_ERROR_I18N("FileExist failed because filesystem_error, error message: %{public}s.",
50             except.code().message().c_str());
51         isFixed = false;
52     } catch (const std::bad_alloc &except) {
53         HILOG_ERROR_I18N("FileExist failed because bad_alloc, error message: %{public}s.", except.what());
54         isFixed = false;
55     }
56     this->commonExit = false;
57     this->country = country;
58 }
59 
~PhoneNumberRule()60 PhoneNumberRule::~PhoneNumberRule()
61 {
62     for (auto it = negativeRules.begin(); it != negativeRules.end(); ++it) {
63         if (*it != nullptr) {
64             delete *it;
65         }
66     }
67     for (auto it = positiveRules.begin(); it != positiveRules.end(); ++it) {
68         if (*it != nullptr) {
69             delete *it;
70         }
71     }
72     for (auto it = borderRules.begin(); it != borderRules.end(); ++it) {
73         if (*it != nullptr) {
74             delete *it;
75         }
76     }
77     for (auto it = codesRules.begin(); it != codesRules.end(); ++it) {
78         if (*it != nullptr) {
79             delete *it;
80         }
81     }
82     for (auto it = findRules.begin(); it != findRules.end(); ++it) {
83         if (*it != nullptr) {
84             delete *it;
85         }
86     }
87 }
88 
Init()89 void PhoneNumberRule::Init()
90 {
91     if (isFixed) {
92         InitRule(xmlPath);
93     }
94     InitRule(XML_COMMON_PATH + XML_COMMON_FILE);
95 }
96 
97 // Load the rules of the corresponding country
InitRule(const std::string & xmlPath)98 void PhoneNumberRule::InitRule(const std::string& xmlPath)
99 {
100     std::string validXmlPath = GetAbsoluteFilePath(xmlPath);
101     if (validXmlPath.empty()) {
102         HILOG_ERROR_I18N("PhoneNumberRule::InitRule: invalid xmlPath: %{public}s.", xmlPath.c_str());
103         return;
104     }
105     xmlKeepBlanksDefault(0);
106     xmlDocPtr doc = xmlParseFile(validXmlPath.c_str());
107     if (doc == nullptr) {
108         return;
109     }
110     xmlNodePtr root = xmlDocGetRootElement(doc);
111     if (root == nullptr) {
112         xmlFreeDoc(doc);
113         return;
114     }
115     xmlNodePtr cur = root->xmlChildrenNode;
116     while (cur != nullptr) {
117         std::string category = reinterpret_cast<const char*>(cur->name);
118         ParseXmlNode(cur, category);
119         cur = cur->next;
120     }
121     xmlFreeDoc(doc);
122 }
123 
ParseXmlNode(xmlNodePtr cur,std::string & category)124 void PhoneNumberRule::ParseXmlNode(xmlNodePtr cur, std::string& category)
125 {
126     xmlNodePtr rule = cur->xmlChildrenNode;
127     while (rule != nullptr && !xmlStrcmp(rule->name, reinterpret_cast<const xmlChar*>("rule"))) {
128         xmlNodePtr value = rule->xmlChildrenNode;
129         std::string insensitive = XmlNodePtrToString(value);
130         if (category == "common_exit") {
131             commonExit = (insensitive == "True");
132             break;
133         }
134         if (value == nullptr) {
135             break;
136         }
137         value = value->next;
138         std::string type = XmlNodePtrToString(value);
139         if (value == nullptr) {
140             break;
141         }
142         value = value->next;
143         std::string valid = XmlNodePtrToString(value);
144         if (value == nullptr) {
145             break;
146         }
147         value = value->next;
148         std::string handle = XmlNodePtrToString(value);
149         if (IsXmlNodeValueEmpty(insensitive, type, valid, handle)) {
150             break;
151         }
152         icu::UnicodeString content = "";
153         while (value->next != nullptr && !xmlStrcmp(value->next->name,
154             reinterpret_cast<const xmlChar*>("content"))) {
155             value = value->next;
156             xmlChar* contentPtr = xmlNodeGetContent(value);
157             if (contentPtr == nullptr) {
158                 continue;
159             }
160             icu::UnicodeString tempContent = reinterpret_cast<char*>(contentPtr);
161             content += tempContent;
162             xmlFree(contentPtr);
163         }
164         SetRules(category, content, valid, handle, insensitive, type);
165         rule = rule->next;
166     }
167 }
168 
IsXmlNodeValueEmpty(const std::string & insensitive,const std::string & type,const std::string & valid,const std::string & handle)169 bool PhoneNumberRule::IsXmlNodeValueEmpty(const std::string& insensitive, const std::string& type,
170     const std::string& valid, const std::string& handle)
171 {
172     if (insensitive.empty() || type.empty() ||
173         valid.empty() || handle.empty()) {
174         return true;
175     }
176     return false;
177 }
178 
XmlNodePtrToString(xmlNodePtr valuePtr)179 std::string PhoneNumberRule::XmlNodePtrToString(xmlNodePtr valuePtr)
180 {
181     if (valuePtr == nullptr) {
182         return "";
183     }
184     xmlChar* charPtr = xmlNodeGetContent(valuePtr);
185     if (charPtr == nullptr) {
186         return "";
187     }
188     std::string result = reinterpret_cast<char*>(charPtr);
189     xmlFree(charPtr);
190     return result;
191 }
192 
SetRules(std::string & category,icu::UnicodeString & content,std::string & valid,std::string & handle,std::string & insensitive,std::string & type)193 void PhoneNumberRule::SetRules(std::string& category, icu::UnicodeString& content, std::string& valid,
194     std::string& handle, std::string& insensitive, std::string& type)
195 {
196     if (category == "negative" || (category == "common" && commonExit)) {
197         negativeRules.push_back(new NegativeRule(content, insensitive));
198     } else if (category == "positive") {
199         positiveRules.push_back(new PositiveRule(content, handle, insensitive));
200     } else if (category == "border") {
201         borderRules.push_back(new BorderRule(content, insensitive, type));
202     } else if (category == "codes") {
203         codesRules.push_back(new CodeRule(valid));
204     } else if (category == "find_number") {
205         findRules.push_back(new FindRule(content, insensitive));
206     }
207 }
208 
GetBorderRules()209 std::vector<BorderRule*> PhoneNumberRule::GetBorderRules()
210 {
211     return borderRules;
212 }
213 
GetCodesRules()214 std::vector<CodeRule*> PhoneNumberRule::GetCodesRules()
215 {
216     return codesRules;
217 }
218 
GetPositiveRules()219 std::vector<PositiveRule*> PhoneNumberRule::GetPositiveRules()
220 {
221     return positiveRules;
222 }
223 
GetNegativeRules()224 std::vector<NegativeRule*> PhoneNumberRule::GetNegativeRules()
225 {
226     return negativeRules;
227 }
228 
GetFindRules()229 std::vector<FindRule*> PhoneNumberRule::GetFindRules()
230 {
231     return findRules;
232 }
233 } // namespace I18n
234 } // namespace Global
235 } // namespace OHOS