Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / plugins / plugin_list_parser.cc
1 // Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/plugins/plugin_list_parser.h"
6
7 #include <manifest_parser/utils/string_util.h>
8
9 #include <filesystem>
10
11 namespace fs = std::filesystem;
12
13 namespace common_installer {
14
15 PluginInfo::PluginInfo(std::string type,
16                        std::string name,
17                        std::filesystem::path path,
18                        bool vitalness)
19     : type_(std::move(type)),
20       name_(std::move(name)),
21       path_(std::move(path)),
22       vitalness_(vitalness) {}
23
24 const std::string& PluginInfo::type() const { return type_; }
25
26 const std::string& PluginInfo::name() const { return name_; }
27
28 const std::filesystem::path& PluginInfo::path() const { return path_; }
29
30 bool PluginInfo::vitalness() const {
31   return vitalness_;
32 }
33
34 // class PluginsListParser
35 bool PluginsListParser::ValidType(const std::string& type) {
36   if (type.empty()) {
37     LOG(ERROR) << "Type is empty (valid function)";
38     return false;
39   }
40   std::regex re_valid(R"((tag|metadata|category))");
41   return std::regex_search(type, re_valid);
42 }
43
44 bool PluginsListParser::ValidName(const std::string& name) {
45   if (name.empty()) {
46     LOG(ERROR) << "Name is empty (valid function)";
47     return false;
48   }
49
50   return true;
51 }
52
53 bool PluginsListParser::ValidPath(const std::string& path) {
54   if (path.empty()) {
55     LOG(ERROR) << "Path is empty (valid function)";
56     return false;
57   }
58
59   std::smatch match;
60   std::regex re_extension(R"((\.so[^/]+)?$)");
61
62   if (!std::regex_search(path, match, re_extension)) {
63     return false;
64   }
65
66   // if no matched group
67   if (match.size() != 2) {
68     LOG(ERROR) << "Path not included extension lib file";
69     return false;
70   }
71
72   return true;
73 }
74
75 std::string PluginsListParser::ExtractRaw(const std::string& data,
76                                           const std::regex& re_extract) {
77   std::smatch match;
78
79   // 2 mean matched group
80   if (!std::regex_search(data, match, re_extract) || match.size() != 2) {
81     LOG(ERROR) << "Could not find data during extracting parameter";
82     return {};
83   }
84   return match[1];
85 }
86
87 std::string PluginsListParser::ExtractName(const std::string& type) {
88   std::regex re_extract(R"(name\s*\=\s*\"(.*)\")");
89   return ExtractRaw(type, re_extract);
90 }
91
92 std::string PluginsListParser::ExtractType(const std::string& type) {
93   std::regex re_extract(R"(type\s*\=\s*\"(.*)\")");
94   return ExtractRaw(type, re_extract);
95 }
96
97 std::string PluginsListParser::ExtractPath(const std::string& path) {
98   std::regex re_extract(R"(path\s*\=\s*\"(.*)\")");
99   return ExtractRaw(path, re_extract);
100 }
101
102 std::string PluginsListParser::ExtractVitalness(
103     const std::string& vitalness) {
104   std::regex re_extract(R"(vitalness\s*\=\s*\"(.*)\")");
105   return ExtractRaw(vitalness, re_extract);
106 }
107
108 bool PluginsListParser::Parse() {
109   std::vector<std::string> lines;
110
111   if (!ReadLinesFromFile(&lines)) {
112     LOG(ERROR) << "No read lines from file";
113     return false;
114   }
115
116   if (!ParsePluginsRawData(lines)) {
117     LOG(ERROR) << "No parse data from lines";
118     return false;
119   }
120
121   return true;
122 }
123
124 const PluginsListParser::PluginList& PluginsListParser::PluginInfoList() const {
125   return plugin_info_list_;
126 }
127
128 bool PluginsListParser::ReadLinesFromFile(std::vector<std::string>* lines) {
129   for (fs::directory_iterator file(path_); file != fs::directory_iterator();
130       ++file) {
131     std::error_code error;
132     bool is_file = fs::is_regular_file(file->path(), error);
133     if (!is_file || error)
134       continue;
135
136     std::ifstream plugins_file;
137     plugins_file.open(file->path().string());
138     if (!plugins_file.is_open()) {
139       LOG(ERROR) << "File " << file->path() << " not opened";
140       continue;
141     }
142
143     LOG(INFO) << "Plugin list path: " << file->path();
144
145     std::string line;
146     while (plugins_file >> line)
147       lines->push_back(line);
148
149     plugins_file.close();
150   }
151
152   if (lines->empty()) {
153     LOG(ERROR) << "No data in files from " << path_;
154     return false;
155   }
156
157   return true;
158 }
159
160 bool PluginsListParser::ParsePluginsRawData(
161     const std::vector<std::string>& lines) {
162   plugin_info_list_.clear();
163
164   for (const std::string& line : lines) {
165     std::vector<std::string> parts;
166     if (!SplitPluginLine(line, &parts)) {
167       LOG(ERROR) << "Invalid split plugin line";
168       return false;
169     }
170
171     std::string type = ExtractType(parts.at(Type));
172     std::string name = ExtractName(parts.at(Name));
173     std::string path = ExtractPath(parts.at(Path));
174     std::string vitalness = "false";
175     if (parts.size() == 4)
176       vitalness = ExtractVitalness(parts.at(Vitalness));
177     if (!ValidName(name)) {
178       LOG(ERROR) << "Invalid name: " << name;
179       return false;
180     }
181
182     if (!ValidType(type)) {
183       LOG(ERROR) << "Invalid type: " << type;
184       return false;
185     }
186
187     if (!ValidPath(path)) {
188       LOG(ERROR) << "Invalid path: " << path;
189       return false;
190     }
191
192     plugin_info_list_.push_back(std::make_shared<PluginInfo>(std::move(type),
193         std::move(name), std::filesystem::path(std::move(path)),
194         (vitalness.compare("true") == 0 ? true : false)));
195   }
196
197   return true;
198 }
199
200 bool PluginsListParser::SplitPluginLine(const std::string& line,
201                                         std::vector<std::string>* parts) {
202   static const char kPartsInLine = 3;
203
204   std::vector<std::string> _parts;
205   parser::utils::Split(_parts, line, ';');
206
207   if (_parts.size() != kPartsInLine && _parts.size() != kPartsInLine + 1) {
208     LOG(ERROR) << "Invalid number of parts";
209     return false;
210   }
211
212   parts->assign(_parts.begin(), _parts.end());
213
214   return true;
215 }
216 }  // namespace common_installer