1 /*
2 * Copyright (C) 2024 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
16 #include <dualfwk_conf_parser.h>
17
18 #include <charconv>
19 #include <functional>
20 #include <string>
21 #include <vector>
22 #include <unordered_map>
23
24 #include <libxml/tree.h>
25 #include <libxml/parser.h>
26
27 #include "ringtone_errno.h"
28 #include "ringtone_log.h"
29 #include "ringtone_type.h"
30 #include "ringtone_utils.h"
31
32 namespace OHOS {
33 namespace Media {
DualFwkConfParser(const std::string & path)34 DualFwkConfParser::DualFwkConfParser(const std::string &path)
35 : version_(0), path_(path)
36 {
37 }
38
StringConverter(const std::string & str,int & result)39 bool DualFwkConfParser::StringConverter(const std::string &str, int &result)
40 {
41 auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
42 return ec == std::errc{} && ptr == str.data() + str.size();
43 }
44
Parse()45 int32_t DualFwkConfParser::Parse()
46 {
47 std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
48 xmlReadFile(path_.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
49 if (docPtr == nullptr) {
50 RINGTONE_ERR_LOG("failed to read xml file");
51 return E_ERR;
52 }
53
54 auto rootNode = xmlDocGetRootElement(docPtr.get());
55 if (rootNode == nullptr) {
56 RINGTONE_ERR_LOG("failed to read root node");
57 return E_ERR;
58 }
59
60 if (!xmlStrcmp(rootNode->name, BAD_CAST"settings")) {
61 xmlChar* xmlVersion = xmlGetProp(rootNode, BAD_CAST"version");
62 if (xmlVersion == nullptr) {
63 RINGTONE_ERR_LOG("xml version is null");
64 return E_ERR;
65 }
66 try {
67 version_ = std::stoi((const char *)xmlVersion);
68 RINGTONE_INFO_LOG("xml verison=%{public}d", version_);
69 } catch (const std::invalid_argument& e) {
70 RINGTONE_INFO_LOG("invalid argument: %{public}s", e.what());
71 } catch (const std::out_of_range& e) {
72 RINGTONE_INFO_LOG("out of range: %{public}s", e.what());
73 }
74
75 if (xmlVersion != nullptr) {
76 int32_t value = 0;
77 if (RingtoneUtils::IsNumber((const char *)xmlVersion) &&
78 StringConverter((const char *)xmlVersion, value)) {
79 version_ = value;
80 RINGTONE_INFO_LOG("xml verison=%{public}d", version_);
81 xmlFree(xmlVersion);
82 }
83 } else {
84 RINGTONE_INFO_LOG("xml version is null");
85 }
86 } else {
87 RINGTONE_ERR_LOG("root node name is not matched");
88 return E_ERR;
89 }
90
91 for (auto node = rootNode->children; node != nullptr; node = node->next) {
92 if (!xmlStrcmp(node->name, BAD_CAST"setting")) {
93 ParseConf(node);
94 } else {
95 RINGTONE_INFO_LOG("bad node name: %{public}s", node->name);
96 }
97 }
98
99 return E_SUCCESS;
100 }
101
ParseConf(xmlNodePtr node)102 int32_t DualFwkConfParser::ParseConf(xmlNodePtr node)
103 {
104 auto conf = std::make_unique<DualFwkConfRow>();
105 xmlChar* xmlAttrVal = xmlGetProp(node, BAD_CAST"id");
106 if (xmlAttrVal) {
107 try {
108 int num = std::stoi((const char *)xmlAttrVal);
109 conf->id = num;
110 } catch (const std::invalid_argument& e) {
111 conf->id = -1;
112 RINGTONE_INFO_LOG("invalid argument: %{public}s", e.what());
113 } catch (const std::out_of_range& e) {
114 conf->id = -1;
115 RINGTONE_INFO_LOG("out of range: %{public}s", e.what());
116 }
117 xmlFree(xmlAttrVal);
118 }
119 auto strName = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"name"));
120 if (strName != nullptr) {
121 conf->name = std::string(strName);
122 xmlFree(strName);
123 }
124
125 auto strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"value"));
126 if (strVal != nullptr) {
127 conf->value = std::string(strVal);
128 xmlFree(strVal);
129 }
130
131 auto strPackage = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"package"));
132 if (strPackage != nullptr) {
133 conf->package = std::string(strPackage);
134 xmlFree(strPackage);
135 }
136
137 auto strDefaultVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"defaultValue"));
138 if (strDefaultVal != nullptr) {
139 conf->defaultValue = std::string(strDefaultVal);
140 xmlFree(strDefaultVal);
141 }
142
143 auto strDefaultSysSet = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"defaultSysSet"));
144 if (strDefaultSysSet != nullptr) {
145 conf->defaultSysSet = std::string(strDefaultSysSet);
146 xmlFree(strDefaultSysSet);
147 }
148
149 auto strPreserve = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"preserve_in_restore"));
150 if (strPreserve != nullptr) {
151 conf->preserveInRestore = (std::string(strPreserve) == "true" ? true : false);
152 xmlFree(strPreserve);
153 }
154
155 dualFwkConfs_.push_back(std::move(conf));
156
157 return E_SUCCESS;
158 }
159
ConfTraval(std::function<void (std::unique_ptr<DualFwkConfRow> &)> func)160 void DualFwkConfParser::ConfTraval(std::function<void (std::unique_ptr<DualFwkConfRow> &)> func)
161 {
162 RINGTONE_INFO_LOG("dualfwk confs num: %{public}zu", dualFwkConfs_.size());
163 for (size_t i = 0; i < dualFwkConfs_.size(); i++) {
164 func(dualFwkConfs_[i]);
165 }
166 }
167 } // namespace Media
168 } // namespace OHOS
169