%files
%defattr(-,root,root)
+%{_datarootdir}/app-installers/plugins_list.txt
%manifest app-installers.manifest
%{_libdir}/libapp-installers.so*
%attr(6750,root,users) %{_bindir}/pkgdir-tool
step/step_register_security.cc
step/step_rollback_deinstallation_security.cc
step/step_rollback_installation_security.cc
+ step/step_run_parser_plugins.cc
step/step_unregister_app.cc
step/step_update_app.cc
step/step_update_security.cc
utils/dynamic_lib_handle.cc
utils/file_util.cc
utils/subprocess.cc
+ utils/plugin_xml_parser.cc
+ utils/plugin_list_parser.cc
+ utils/plugin_manager.cc
)
# Target - definition
ADD_LIBRARY(${TARGET_LIBNAME_COMMON} SHARED ${SRCS})
# Install
INSTALL(TARGETS ${TARGET_LIBNAME_COMMON} DESTINATION ${LIB_INSTALL_DIR})
+
+# Plugins
+SET(PLUGINS_LIST_FILE_NAME plugins_list.txt)
+SET(PLUGINS_LIST_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGINS_LIST_FILE_NAME})
+
+SET(PLUGINS_LIST_INSTALL_PATH ${SHAREDIR}/${TARGET_LIBNAME_COMMON})
+SET(PLUGINS_LIST_INSTALL_FILE_PATH ${PLUGINS_LIST_INSTALL_PATH}/${PLUGINS_LIST_FILE_NAME})
+
+ADD_DEFINITIONS("-DPLUGINS_LIST_INSTALL_FILE_PATH=\"${PLUGINS_LIST_INSTALL_FILE_PATH}\"")
+CONFIGURE_FILE(${PLUGINS_LIST_FILE_NAME}.in ${PLUGINS_LIST_FILE_NAME} @ONLY)
+INSTALL(FILES ${PLUGINS_LIST_FILE_PATH} DESTINATION ${PLUGINS_LIST_INSTALL_PATH}/)
+
# Export devel package
CONFIGURE_FILE(app-installers.pc.in app-installers.pc @ONLY)
INSTALL(FILES app-installers.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
--- /dev/null
+flag="0x00000001";type="tag";name="shortcut-list";path="/usr/etc/package-manager/parserlib/libshortcut-list.so"
+flag="0x00000002";type="tag";name="account";path="/usr/etc/package-manager/parserlib/libaccount.so"
+flag="0x00000004";type="tag";name="notifications";path="/usr/etc/package-manager/parserlib/libnotifications.so"
+flag="0x00000008";type="tag";name="privileges";path="/usr/etc/package-manager/parserlib/libprivileges.so"
+flag="0x00000010";type="tag";name="ime";path="/usr/etc/package-manager/parserlib/libime.so"
+flag="0x00000020";type="category";name="http://tizen.org/category/downloadable_font";path="/usr/etc/package-manager/parserlib/category/libdownloadable_font.so"
+flag="0x00000040";type="metadata";name="http://developer.samsung.com/tizen/metadata/sticker";path="/usr/etc/package-manager/parserlib/metadata/libsticker.so"
+flag="0x00000080";type="metadata";name="http://developer.samsung.com/tizen/metadata/ttsengine";path="/usr/etc/package-manager/parserlib/metadata/libttsengine.so"
+flag="0x00000100";type="metadata";name="http://developer.samsung.com/tizen/metadata/downloadable_filters";path="/usr/etc/package-manager/parserlib/metadata/libdownloadable_filters.so"
+flag="0x00000200";type="metadata";name="http://developer.samsung.com/tizen/metadata/dictionary";path="/usr/etc/package-manager/parserlib/metadata/libdictionary.so"
+flag="0x00000400";type="category";name="http://tizen.org/category/antivirus";path="/usr/etc/package-manager/parserlib/category/libantivirus.so"
+flag="0x00000800";type="metadata";name="http://developer.samsung.com/tizen/metadata/profile";path="/usr/etc/package-manager/parserlib/metadata/libtheme.so"
+flag="0x00001000";type="category";name="http://tizen.org/category/tts";path="/usr/etc/package-manager/parserlib/category/libsamsung_tts.so"
+flag="0x00002000";type="tag";name="livebox";path="/usr/etc/package-manager/parserlib/liblivebox.so"
+flag="0x00004000";type="tag";name="watch-application";path="/usr/etc/package-manager/parserlib/libwatch-application.so"
+flag="0x00008000";type="tag";name="widget-application";path="/usr/etc/package-manager/parserlib/libwidget-application.so"
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "common/step/step_run_parser_plugins.h"
+
+namespace common_installer {
+namespace pkgmgr {
+
+StepRunParserPlugin::StepRunParserPlugin(InstallerContext* context,
+ ActionType action_type)
+ : Step(context), action_type_(action_type) {}
+
+Step::Status StepRunParserPlugin::ProcessingPlugins(
+ const boost::filesystem::path& xml_path) {
+ // PLUGINS_LIST_FILE_PATH path generated from cmake
+ const std::string listPath(PLUGINS_LIST_INSTALL_FILE_PATH);
+
+ // init plugin_manager
+ plugin_manager_.reset(new PluginManager(xml_path.string(), listPath));
+
+ if (!plugin_manager_->GenerateUnknownTagList()) {
+ LOG(ERROR) << "Error during generate unknown list, no exist file, path, "
+ "invalid data format etc, chceck log";
+ return Status::ERROR;
+ }
+
+ std::vector<std::shared_ptr<PluginInfo>> plugins =
+ plugin_manager_->UnknownTagList();
+
+ for (const std::shared_ptr<PluginInfo>& plugin : plugins) {
+ if (!plugin_manager_->Launch(plugin->path(), action_type_,
+ context_->pkgid.get())) {
+ LOG(ERROR) << "Error during launch tag name: " << plugin->name()
+ << " path: " << plugin->path();
+ return Status::ERROR;
+ }
+ // add plugin to array for undo process
+ if (action_type_ == ActionType::Install) {
+ installed_plugins_.push_back(plugin);
+ }
+ }
+
+ LOG(INFO) << "Successfully processing plugins";
+ return Status::OK;
+}
+
+Step::Status StepRunParserPlugin::process() {
+ return ProcessingPlugins(context_->xml_path.get());
+}
+
+Step::Status StepRunParserPlugin::undo() {
+ if (action_type_ == ActionType::Install) {
+ if (installed_plugins_.empty()) {
+ // no installed plugins
+ return Status::OK;
+ }
+
+ for (const std::shared_ptr<PluginInfo>& plugin : installed_plugins_) {
+ if (!plugin_manager_->Launch(plugin->path(), ActionType::Uninstall,
+ context_->pkgid.get())) {
+ LOG(ERROR) << "Error during uninstall tag name: " << plugin->name()
+ << " path: " << plugin->path();
+ }
+ }
+ } else if (action_type_ == ActionType::Upgrade) {
+ return ProcessingPlugins(context_->backup_xml_path.get());
+ } else if (action_type_ == ActionType::Uninstall) {
+ return ProcessingPlugins(context_->xml_path.get());
+ }
+ return Status::OK;
+}
+
+} // namespace pkgmgr
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_STEP_RUN_PARSER_PLUGINS_H_
+#define COMMON_STEP_STEP_RUN_PARSER_PLUGINS_H_
+
+#include <string>
+#include <vector>
+
+#include "common/utils/plugin_manager.h"
+#include "manifest_parser/utils/logging.h"
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace pkgmgr {
+
+class StepRunParserPlugin : public Step {
+ public:
+ explicit StepRunParserPlugin(InstallerContext* context,
+ ActionType action_type);
+
+ Step::Status process() override;
+ Step::Status clean() { return Status::OK; }
+ Step::Status undo() override;
+ Step::Status precheck() { return Status::OK; }
+
+ SCOPE_LOG_TAG(RunParserPlugin)
+
+ private:
+ Step::Status ProcessingPlugins(const boost::filesystem::path& xml_path);
+ ActionType action_type_;
+ std::vector<std::shared_ptr<PluginInfo>> installed_plugins_;
+ std::unique_ptr<PluginManager> plugin_manager_;
+};
+
+} // namespace pkgmgr
+} // namespace common_installer
+
+#endif // COMMON_STEP_STEP_RUN_PARSER_PLUGINS_H_
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+#include "common/utils/plugin_list_parser.h"
+
+namespace common_installer {
+
+PluginInfo::PluginInfo(int flag, const std::string& type,
+ const std::string& name,
+ const boost::filesystem::path& path)
+ : flag_(flag),
+ type_(std::move(type)),
+ name_(std::move(name)),
+ path_(std::move(path)) {}
+
+int PluginInfo::flag() const { return flag_; }
+
+const std::string& PluginInfo::type() const { return type_; }
+
+const std::string& PluginInfo::name() const { return name_; }
+
+const boost::filesystem::path& PluginInfo::path() const { return path_; }
+
+// class PluginsListParser
+bool PluginsListParser::ValidType(const std::string& type) {
+ if (type.empty()) {
+ LOG(ERROR) << "Type is empty (valid function)";
+ return false;
+ }
+ std::regex re_valid(R"((tag|metadata|category))");
+ return std::regex_search(type, re_valid);
+}
+
+bool PluginsListParser::ValidFlag(const std::string& flag) {
+ if (flag.empty()) {
+ LOG(ERROR) << "Flag is empty (valid function)";
+ return false;
+ }
+
+ std::regex re_valid(R"(0x[01248]+)");
+ return std::regex_match(flag, re_valid);
+}
+
+bool PluginsListParser::ValidName(const std::string& name) {
+ if (name.empty()) {
+ LOG(ERROR) << "Name is empty (valid function)";
+ return false;
+ }
+
+ return true;
+}
+
+bool PluginsListParser::ValidPath(const std::string& path) {
+ if (path.empty()) {
+ LOG(ERROR) << "Path is empty (valid function)";
+ return false;
+ }
+
+ std::smatch match;
+ std::regex re_extension(R"((\.so[^/]+)?$)");
+
+ if (!std::regex_search(path, match, re_extension)) {
+ return false;
+ }
+
+ // if no matched group
+ if (match.size() != 2) {
+ LOG(ERROR) << "Path not included extension lib file";
+ return false;
+ }
+
+ return true;
+}
+
+std::string PluginsListParser::ExtractRaw(const std::string& data,
+ const std::regex& re_extract) {
+ std::smatch match;
+ std::regex_search(data, match, re_extract);
+
+ // 2 mean matched group
+ if (match.size() != 2) {
+ LOG(ERROR) << "Could not find data during extracting parameter";
+ return {};
+ }
+ return match[1];
+}
+
+std::string PluginsListParser::ExtractFlag(const std::string& flag) {
+ std::regex re_extract(R"(flag\s*\=\s*\"(.*)\")");
+ return ExtractRaw(flag, re_extract);
+}
+
+std::string PluginsListParser::ExtractName(const std::string& type) {
+ std::regex re_extract(R"(name\s*\=\s*\"(.*)\")");
+ return ExtractRaw(type, re_extract);
+}
+
+std::string PluginsListParser::ExtractType(const std::string& type) {
+ std::regex re_extract(R"(type\s*\=\s*\"(.*)\")");
+ return ExtractRaw(type, re_extract);
+}
+
+std::string PluginsListParser::ExtractPath(const std::string& path) {
+ std::regex re_extract(R"(path\s*\=\s*\"(.*)\")");
+ return ExtractRaw(path, re_extract);
+}
+
+bool PluginsListParser::Parse() {
+ std::vector<std::string> lines;
+
+ if (!ReadLinesFromFile(&lines)) {
+ LOG(ERROR) << "No read lines from file";
+ return false;
+ }
+
+ if (!ParsePluginsRawData(lines)) {
+ LOG(ERROR) << "No parse data from lines";
+ return false;
+ }
+
+ return true;
+}
+
+const std::vector<std::shared_ptr<PluginInfo>>&
+PluginsListParser::PluginInfoList() {
+ return plugin_info_list_;
+}
+
+bool PluginsListParser::ReadLinesFromFile(std::vector<std::string>* lines) {
+ std::ifstream plugins_file;
+
+ plugins_file.open(path_);
+
+ if (!plugins_file.is_open()) {
+ LOG(ERROR) << "File " << path_ << " no open";
+ return false;
+ }
+
+ LOG(INFO) << "Plugin list path: " << path_;
+
+ std::string line;
+ while (plugins_file >> line) {
+ lines->push_back(line);
+ }
+
+ plugins_file.close();
+
+ if (lines->empty()) {
+ LOG(ERROR) << "No data in file " << path_;
+ return false;
+ }
+
+ return true;
+}
+
+bool PluginsListParser::ParsePluginsRawData(
+ const std::vector<std::string>& lines) {
+ plugin_info_list_.clear();
+
+ std::vector<int> flag_container;
+
+ for (const std::string& line : lines) {
+ std::vector<std::string> parts;
+ if (!SplitPluginLine(line, &parts)) {
+ LOG(ERROR) << "Invalid split plugin line";
+ return false;
+ }
+
+ std::string flag = ExtractFlag(parts.at(Flag));
+ std::string type = ExtractType(parts.at(Type));
+ std::string name = ExtractName(parts.at(Name));
+ std::string path = ExtractPath(parts.at(Path));
+
+ if (!ValidFlag(flag)) {
+ LOG(ERROR) << "Invalid flag: " << flag;
+ return false;
+ }
+
+ const int kConvertStringBase = 16;
+ int _flag = std::strtoul(flag.c_str(), nullptr, kConvertStringBase);
+
+ // flag should be unique
+ if (std::find(flag_container.begin(), flag_container.end(), _flag) !=
+ flag_container.end()) {
+ LOG(ERROR) << "Flag isn't unique, flag: " << _flag;
+ return false;
+ } else {
+ flag_container.push_back(_flag);
+ }
+
+ if (!ValidType(type)) {
+ LOG(ERROR) << "Invalid type: " << type;
+ return false;
+ }
+
+ if (!ValidName(name)) {
+ LOG(ERROR) << "Invalid name: " << name;
+ return false;
+ }
+
+ if (!ValidPath(path)) {
+ LOG(ERROR) << "Invalid path: " << path;
+ return false;
+ }
+
+ boost::filesystem::path _path = boost::filesystem::path(path);
+
+ plugin_info_list_.push_back(
+ std::make_shared<PluginInfo>(_flag, type, name, _path));
+ }
+
+ return true;
+}
+
+bool PluginsListParser::SplitPluginLine(const std::string& line,
+ std::vector<std::string>* parts) {
+ static const char kPartsInLine = 4;
+
+ std::vector<std::string> _parts;
+ boost::algorithm::split(_parts, line, boost::algorithm::is_any_of(";"));
+
+ if (_parts.size() != kPartsInLine) {
+ LOG(ERROR) << "Invalid number of parts";
+ return false;
+ }
+
+ parts->assign(_parts.begin(), _parts.end());
+
+ return true;
+}
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_PLUGIN_LIST_PARSER_H_
+#define COMMON_UTILS_PLUGIN_LIST_PARSER_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlschemas.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <regex>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "manifest_parser/utils/logging.h"
+
+namespace common_installer {
+
+/** this class include information about plugin */
+class PluginInfo {
+ public:
+ PluginInfo(int flag, const std::string& type, const std::string& name,
+ const boost::filesystem::path& path);
+ int flag() const;
+ const std::string& type() const;
+ const std::string& name() const;
+ const boost::filesystem::path& path() const;
+
+ private:
+ int flag_;
+ std::string type_;
+ std::string name_;
+ boost::filesystem::path path_;
+};
+
+/** this class parse plugin file */
+class PluginsListParser {
+ public:
+ explicit PluginsListParser(const std::string& path) : path_(path) {}
+
+ bool Parse();
+ const std::vector<std::shared_ptr<PluginInfo>>& PluginInfoList();
+
+ private:
+ enum Column { Flag, Type, Name, Path };
+
+ PluginsListParser() {}
+ const std::string path_;
+ std::vector<std::shared_ptr<PluginInfo>> plugin_info_list_;
+
+ bool ReadLinesFromFile(std::vector<std::string>* lines);
+ bool ParsePluginsRawData(const std::vector<std::string>& lines);
+ bool SplitPluginLine(const std::string& line,
+ std::vector<std::string>* parts);
+
+ std::string ExtractRaw(const std::string& data, const std::regex& re_extract);
+ std::string ExtractFlag(const std::string& flag);
+ std::string ExtractType(const std::string& type);
+ std::string ExtractName(const std::string& name);
+ std::string ExtractPath(const std::string& path);
+ bool ValidFlag(const std::string& flag);
+ bool ValidType(const std::string& type);
+ bool ValidName(const std::string& name);
+ bool ValidPath(const std::string& path);
+};
+
+} // namespace common_installer
+#endif // COMMON_UTILS_PLUGIN_LIST_PARSER_H_
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/filesystem.hpp>
+
+#include <string>
+#include <vector>
+
+#include "common/utils/plugin_list_parser.h"
+#include "common/utils/plugin_xml_parser.h"
+#include "common/utils/plugin_manager.h"
+
+namespace common_installer {
+
+bool PluginManager::GenerateUnknownTagList() {
+ tags_.clear();
+
+ if (!xml_parser_.Parse()) {
+ LOG(ERROR) << "Parse xml function error";
+ return false;
+ }
+
+ std::vector<std::string> xmlTags = xml_parser_.tags_list();
+
+ if (!list_parser_.Parse()) {
+ LOG(ERROR) << "Parse list function error";
+ return false;
+ }
+
+ const std::vector<std::shared_ptr<PluginInfo>> pluginInfoList =
+ list_parser_.PluginInfoList();
+
+ for (std::shared_ptr<PluginInfo> pluginInfo : pluginInfoList) {
+ // find only tags
+ if (pluginInfo->type() == "tag") {
+ // check if a file exist
+ if (boost::filesystem::exists(pluginInfo->path())) {
+ for (const std::string& xmlTag : xmlTags) {
+ // if system tags included in xml tags
+ if (pluginInfo->name() == xmlTag) {
+ tags_.push_back(pluginInfo);
+ LOG(DEBUG) << "Tag: " << pluginInfo->name()
+ << " path: " << pluginInfo->path() << "has been added";
+ break;
+ }
+ }
+ } else {
+ LOG(WARNING) << "Tag: " << pluginInfo->name()
+ << " path: " << pluginInfo->path()
+ << " exist in plugin list but no exist in system.";
+ }
+ }
+ }
+
+ if (tags_.empty()) {
+ LOG(INFO) << "No tags to processing";
+ }
+
+ return true;
+}
+
+const std::vector<std::shared_ptr<PluginInfo>>&
+PluginManager::UnknownTagList() {
+ return tags_;
+}
+
+bool PluginManager::Launch(const boost::filesystem::path& plugin_path,
+ ActionType action_type, const std::string& pkg_Id) {
+ // TODO(l.wartalowic) add implementation
+ LOG(INFO) << "Launching plugin path:" << plugin_path << " pkgId: " << pkg_Id;
+ (void)plugin_path;
+ (void)action_type;
+ (void)pkg_Id;
+ return true;
+}
+
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_PLUGIN_MANAGER_H_
+#define COMMON_UTILS_PLUGIN_MANAGER_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <string>
+#include <vector>
+
+#include "common/utils/plugin_xml_parser.h"
+#include "common/utils/plugin_list_parser.h"
+
+namespace common_installer {
+
+enum class ActionType { Install, Upgrade, Uninstall };
+
+/** this class manages XML and plugin lists */
+class PluginManager {
+ public:
+ PluginManager(const std::string& xml_path, const std::string& list_path)
+ : xml_parser_(xml_path), list_parser_(list_path) {}
+
+ bool GenerateUnknownTagList();
+ const std::vector<std::shared_ptr<PluginInfo>>& UnknownTagList();
+ bool Launch(const boost::filesystem::path& pluginPath, ActionType actionType,
+ const std::string& pkgId);
+
+ private:
+ std::vector<std::shared_ptr<PluginInfo>> tags_;
+ PluginsXmlParser xml_parser_;
+ PluginsListParser list_parser_;
+};
+} // namespace common_installer
+
+#endif // COMMON_UTILS_PLUGIN_MANAGER_H_
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "manifest_parser/utils/logging.h"
+#include "common/utils/plugin_xml_parser.h"
+
+namespace common_installer {
+
+bool PluginsXmlParser::Parse() {
+ if (path_.empty()) {
+ return false;
+ }
+
+ WrapperXMLReader obj_reader;
+
+ xmlTextReaderPtr reader = obj_reader.Create(path_.c_str());
+
+ if (!reader) {
+ return false;
+ }
+
+ LOG(INFO) << "Xml path: " << path_;
+
+ tags_.clear();
+
+ int depth = xmlTextReaderDepth(reader);
+
+ // use set to remove duplicate
+ std::set<std::string> tags;
+
+ while ((NextChildElement(reader, depth))) {
+ const xmlChar* node = xmlTextReaderConstName(reader);
+
+ if (!node) {
+ return false;
+ }
+
+ tags.insert(std::string(reinterpret_cast<const char*>(node)));
+ }
+
+ tags_.assign(tags.begin(), tags.end());
+
+ // get here, after end of a "reading" file
+ doc_ptr_ = xmlTextReaderCurrentDoc(reader);
+
+ if (!doc_ptr_) {
+ return false;
+ }
+
+ return true;
+}
+
+const std::vector<std::string>& PluginsXmlParser::tags_list() { return tags_; }
+
+xmlDocPtr PluginsXmlParser::doc_ptr() { return doc_ptr_; }
+
+int PluginsXmlParser::NextChildElement(xmlTextReaderPtr reader, int depth) {
+ int ret = xmlTextReaderRead(reader);
+ int cur = xmlTextReaderDepth(reader);
+
+ while (ret == 1) {
+ switch (xmlTextReaderNodeType(reader)) {
+ case XML_READER_TYPE_ELEMENT:
+ if (cur == depth + 1) return 1;
+ break;
+ default:
+
+ if (cur <= depth) return 0;
+ break;
+ }
+
+ ret = xmlTextReaderRead(reader);
+ cur = xmlTextReaderDepth(reader);
+ }
+
+ return ret;
+}
+
+PluginsXmlParser::~PluginsXmlParser() {
+ if (doc_ptr_) {
+ xmlFreeDoc(doc_ptr_);
+ }
+}
+
+} // namespace common_installer
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_PLUGIN_XML_PARSER_H_
+#define COMMON_UTILS_PLUGIN_XML_PARSER_H_
+
+#include <libxml2/libxml/xmlreader.h>
+
+#include <string>
+#include <vector>
+#include <set>
+
+namespace common_installer {
+
+/** this class parse xml file*/
+class PluginsXmlParser {
+ public:
+ explicit PluginsXmlParser(const std::string& path)
+ : path_(path), doc_ptr_(nullptr) {}
+ ~PluginsXmlParser();
+ bool Parse();
+ const std::vector<std::string>& tags_list();
+ xmlDocPtr doc_ptr();
+
+ private:
+ const std::string path_;
+ xmlDocPtr doc_ptr_;
+ std::vector<std::string> tags_;
+ int NextChildElement(xmlTextReaderPtr reader, int depth);
+
+ class WrapperXMLReader {
+ public:
+ WrapperXMLReader() : reader_(nullptr) {}
+
+ xmlTextReaderPtr Create(const std::string& path) {
+ reader_ = xmlReaderForFile(path.c_str(), nullptr, 0);
+ return reader_;
+ }
+ virtual ~WrapperXMLReader() {
+ if (reader_) {
+ xmlFreeTextReader(reader_);
+ }
+ }
+
+ private:
+ xmlTextReaderPtr reader_;
+ };
+};
+} // namespace common_installer
+#endif // COMMON_UTILS_PLUGIN_XML_PARSER_H_