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