Fix static analysis issues
[platform/core/appfw/launchpad.git] / src / launchpad-parser / launchpad_parser_plugin.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <pkgmgr_installer_info.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <fstream>
23 #include <string>
24
25 #include "launchpad-parser/launchpad_parser_plugin.hh"
26 #include "launchpad-parser/log_private.hh"
27
28 #define LOADERS_DIRECTORY_PATH "/opt/share/loaders/"
29
30 namespace launchpad_parser_plugin {
31
32 std::string LaunchpadParser::GetFilePath(const std::string& id) {
33   return "/opt/share/loaders/" + id + ".loader";
34 }
35
36 int LaunchpadParser::WriteToFile(const std::string& pkgid) {
37   if (access(LOADERS_DIRECTORY_PATH, F_OK) != 0)
38     mkdir(LOADERS_DIRECTORY_PATH, 0644);
39
40   LOGI("write to file (%zu)", loader_list_.size());
41   for (auto& i : loader_list_) {
42     std::ofstream out_file;
43     LOGI("write ID (%s)", i->GetId().c_str());
44     out_file.open(GetFilePath(i->GetId()));
45     out_file << "[LOADER]\n";
46     out_file << "NAME " + i->GetId() + "\n";
47     out_file << "EXE  /usr/bin/launchpad-loader \n";
48     out_file << "APP_TYPE  capp|c++app \n";
49     out_file << "DETECTION_METHOD  TIMEOUT|VISIBILITY \n";
50     out_file << "TIMEOUT    5000 \n";
51     out_file << "TTL    " + std::to_string(i->GetTimeToLive()) + "\n";
52     out_file << "OWNER    " + pkgid + "\n";
53     out_file << "EXTRA    loader_type  common-loader \n";
54     if (i->GetPreloadLib().size() > 0) {
55       out_file << "EXTRA_ARRAY    preload \n";
56       for (auto& lib : i->GetPreloadLib()) {
57         out_file << "EXTRA_ARRAY_VAL    " LIBDIR "/" + lib + "\n";
58       }
59     }
60     out_file.close();
61   }
62   return 0;
63 }
64
65 bool LaunchpadParser::IsValidId(const std::string& loader_id,
66     const std::string& pkgid) {
67   std::string needle("../");
68   size_t found = loader_id.find(needle);
69   if (found != std::string::npos) {
70     _E("Invalid loader_id(%s)", loader_id.c_str());
71     return false;
72   }
73
74   std::ifstream in_file(GetFilePath(loader_id).c_str());
75   if (!in_file.good())
76     return true;
77   std::string key, val;
78   in_file >> key;
79   while (in_file >> key >> val) {
80     if (key == "OWNER") {
81       LOGI("key (%s), val (%s)", key.c_str(), val.c_str());
82       if (val == pkgid)
83         return true;
84     }
85   }
86   return false;
87 }
88
89 int LaunchpadParser::Install(xmlDocPtr doc, const std::string& pkgid) {
90   pkgmgr_privilege_level level;
91   pkgmgr_installer_info_get_privilege_level(&level);
92   if (level != PM_PRIVILEGE_PLATFORM) {
93     LOGE("Privilege level(%d) is not platform", static_cast<int>(level));
94     return -1;
95   }
96
97   xmlNode* root = xmlDocGetRootElement(doc);
98   if (root == nullptr)
99     return -1;
100
101   for (xmlNode* node = root->children; node; node = node->next) {
102     if (!node->name)
103       continue;
104
105     std::string name = std::string(reinterpret_cast<const char*>(node->name));
106     if (name != "provides-appdefined-loader")
107       continue;
108
109     xmlChar* val = xmlGetProp(node, reinterpret_cast<const xmlChar*>("id"));
110     if (val == nullptr)
111       continue;
112
113     std::shared_ptr<LoaderInfo> info =
114         std::make_shared<LoaderInfo>(std::string(reinterpret_cast<char*>(val)));
115     xmlFree(val);
116     if (!IsValidId(info->GetId(), pkgid))
117       return -1;
118
119     xmlChar* ttl = xmlGetProp(node,
120         reinterpret_cast<const xmlChar*>("time-to-live"));
121     if (ttl) {
122       info->SetTimeToLive(std::stoi(std::string(reinterpret_cast<char*>(ttl))));
123       xmlFree(ttl);
124     }
125
126     for (xmlNode* iter = node->children; iter; iter = iter->next) {
127       if (!iter->name)
128         continue;
129       std::string child_name =
130           std::string(reinterpret_cast<const char*>(iter->name));
131       if (child_name == "preload-library") {
132         xmlChar* libname = xmlGetProp(iter,
133             reinterpret_cast<const xmlChar*>("name"));
134         if (!libname)
135           continue;
136         info->AddPreloadLib(std::string(reinterpret_cast<char*>(libname)));
137         xmlFree(libname);
138       }
139     }
140     loader_list_.push_back(info);
141   }
142   WriteToFile(pkgid);
143
144   return 0;
145 }
146
147 int LaunchpadParser::Upgrade(xmlDocPtr doc, const std::string& pkgid) {
148   if (UnInstall(doc, pkgid) != 0)
149     return -1;
150
151   return Install(doc, pkgid);
152 }
153
154 int LaunchpadParser::UnInstall(xmlDocPtr doc, const std::string& pkgid) {
155   xmlNode* root = xmlDocGetRootElement(doc);
156   if (root == nullptr)
157     return -1;
158
159   for (xmlNode* node = root->children; node; node = node->next) {
160     if (!node->name)
161       continue;
162
163     std::string name = std::string(reinterpret_cast<const char*>(node->name));
164     if (name != "provides-appdefined-loader")
165       continue;
166
167     xmlChar* val = xmlGetProp(node, reinterpret_cast<const xmlChar*>("id"));
168     if (!val)
169       return -1;
170
171     std::string id = std::string(reinterpret_cast<char*>(val));
172     xmlFree(val);
173     if (!IsValidId(id, pkgid))
174       return -1;
175     remove(GetFilePath(id).c_str());
176   }
177   return 0;
178 }
179
180 }   // namspace launchpad_parser_plugin