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 "cpp/src/phonenumbers/phonenumber.h"
18 #include "cpp/src/phonenumbers/shortnumberinfo.h"
19 #include "cpp/src/phonenumbers/phonenumberutil.h"
20 #include "libxml/globals.h"
21 #include "libxml/tree.h"
22 #include "libxml/xmlstring.h"
23 #include "matched_number_info.h"
24 #include "phone_number_rule.h"
25 #include "utils.h"
26
27 namespace OHOS {
28 namespace Global {
29 namespace I18n {
30 using i18n::phonenumbers::PhoneNumber;
31 using i18n::phonenumbers::PhoneNumberUtil;
32 using i18n::phonenumbers::ShortNumberInfo;
33
34 std::string PhoneNumberRule::xmlCommonPath = "/system/usr/ohos_locale_config/phonenumber/common.xml";
35
PhoneNumberRule(std::string & country)36 PhoneNumberRule::PhoneNumberRule(std::string& country)
37 {
38 xmlPath = "/system/usr/ohos_locale_config/phonenumber/" + country + ".xml";
39 isFixed = true;
40 if (!std::filesystem::exists(xmlPath)) {
41 isFixed = false;
42 }
43 this->commonExit = false;
44 this->country = country;
45 }
46
~PhoneNumberRule()47 PhoneNumberRule::~PhoneNumberRule()
48 {
49 FreePointer(negativeRules);
50 FreePointer(positiveRules);
51 FreePointer(borderRules);
52 FreePointer(codesRules);
53 FreePointer(findRules);
54 }
55
FreePointer(std::vector<RegexRule * > & ruleList)56 void PhoneNumberRule::FreePointer(std::vector<RegexRule*> &ruleList)
57 {
58 std::vector<RegexRule*>::iterator iter;
59 for (iter = ruleList.begin(); iter != ruleList.end(); ++iter) {
60 if (*iter != nullptr) {
61 delete *iter;
62 }
63 *iter = nullptr;
64 }
65 ruleList.clear();
66 }
67
Init()68 void PhoneNumberRule::Init()
69 {
70 if (isFixed) {
71 InitRule(xmlPath);
72 }
73 InitRule(xmlCommonPath);
74 }
75
76 // Load the rules of the corresponding country
InitRule(std::string & xmlPath)77 void PhoneNumberRule::InitRule(std::string& xmlPath)
78 {
79 if (!CheckTzDataFilePath(xmlPath)) {
80 return;
81 }
82 xmlKeepBlanksDefault(0);
83 xmlDocPtr doc = xmlParseFile(xmlPath.c_str());
84 if (doc == nullptr) return;
85 xmlNodePtr root = xmlDocGetRootElement(doc);
86 xmlNodePtr cur = root->xmlChildrenNode;
87 while (cur != nullptr) {
88 std::string category = reinterpret_cast<const char*>(cur->name);
89 xmlNodePtr rule = cur->xmlChildrenNode;
90 while (rule != nullptr && !xmlStrcmp(rule->name, reinterpret_cast<const xmlChar*>("rule"))) {
91 xmlNodePtr value = rule->xmlChildrenNode;
92 std::string insensitive = reinterpret_cast<char*>(xmlNodeGetContent(value));
93 value = value->next;
94 if (category == "common_exit") {
95 commonExit = (insensitive == "True");
96 break;
97 }
98 std::string type = reinterpret_cast<char*>(xmlNodeGetContent(value));
99 value = value->next;
100 std::string valid = reinterpret_cast<char*>(xmlNodeGetContent(value));
101 value = value->next;
102 std::string handle = reinterpret_cast<char*>(xmlNodeGetContent(value));
103 icu::UnicodeString content = "";
104 while (value->next != nullptr && !xmlStrcmp(value->next->name,
105 reinterpret_cast<const xmlChar*>("content"))) {
106 value = value->next;
107 xmlChar* contentPtr = xmlNodeGetContent(value);
108 icu::UnicodeString tempContent = reinterpret_cast<char*>(contentPtr);
109 content += tempContent;
110 xmlFree(contentPtr);
111 }
112 SetRules(category, content, valid, handle, insensitive, type);
113 rule = rule->next;
114 }
115 cur = cur->next;
116 }
117 xmlFreeDoc(doc);
118 }
119
SetRules(std::string & category,icu::UnicodeString & content,std::string & valid,std::string & handle,std::string & insensitive,std::string & type)120 void PhoneNumberRule::SetRules(std::string& category, icu::UnicodeString& content, std::string& valid,
121 std::string& handle, std::string& insensitive, std::string& type)
122 {
123 if (category == "negative" || (category == "common" && commonExit)) {
124 negativeRules.push_back(new RegexRule(content, valid, handle, insensitive, type));
125 } else if (category == "positive") {
126 positiveRules.push_back(new RegexRule(content, valid, handle, insensitive, type));
127 } else if (category == "border") {
128 borderRules.push_back(new RegexRule(content, valid, handle, insensitive, type));
129 } else if (category == "codes") {
130 codesRules.push_back(new RegexRule(content, valid, handle, insensitive, type));
131 } else if (category == "find_number") {
132 findRules.push_back(new RegexRule(content, valid, handle, insensitive, type));
133 }
134 }
135
GetBorderRules()136 std::vector<RegexRule*> PhoneNumberRule::GetBorderRules()
137 {
138 return borderRules;
139 }
140
GetCodesRules()141 std::vector<RegexRule*> PhoneNumberRule::GetCodesRules()
142 {
143 return codesRules;
144 }
145
GetPositiveRules()146 std::vector<RegexRule*> PhoneNumberRule::GetPositiveRules()
147 {
148 return positiveRules;
149 }
150
GetNegativeRules()151 std::vector<RegexRule*> PhoneNumberRule::GetNegativeRules()
152 {
153 return negativeRules;
154 }
155
GetFindRules()156 std::vector<RegexRule*> PhoneNumberRule::GetFindRules()
157 {
158 return findRules;
159 }
160 } // namespace I18n
161 } // namespace Global
162 } // namespace OHOS