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
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 auto strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"name"));
118 if (strVal != nullptr) {
119 conf->name = std::string(strVal);
120 }
121
122 strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"value"));
123 if (strVal != nullptr) {
124 conf->value = std::string(strVal);
125 }
126
127 strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"package"));
128 if (strVal != nullptr) {
129 conf->package = std::string(strVal);
130 }
131
132 strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"defaultValue"));
133 if (strVal != nullptr) {
134 conf->defaultValue = std::string(strVal);
135 }
136
137 strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"defaultSysSet"));
138 if (strVal != nullptr) {
139 conf->defaultSysSet = std::string(strVal);
140 }
141
142 strVal = reinterpret_cast<char*>(xmlGetProp(node, BAD_CAST"preserve_in_restore"));
143 if (strVal != nullptr) {
144 conf->preserveInRestore = (std::string(strVal) == "true" ? true : false);
145 }
146
147 dualFwkConfs_.push_back(std::move(conf));
148
149 return E_SUCCESS;
150 }
151
ConfTraval(std::function<void (std::unique_ptr<DualFwkConfRow> &)> func)152 void DualFwkConfParser::ConfTraval(std::function<void (std::unique_ptr<DualFwkConfRow> &)> func)
153 {
154 RINGTONE_INFO_LOG("dualfwk confs num: %{public}zu", dualFwkConfs_.size());
155 for (size_t i = 0; i < dualFwkConfs_.size(); i++) {
156 func(dualFwkConfs_[i]);
157 }
158 }
159 } // namespace Media
160 } // namespace OHOS
161