Release version 0.18.5
[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(std::string id) {
33   return "/opt/share/loaders/" + id + ".loader";
34 }
35
36 int LaunchpadParser::WriteToFile(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    /usr/lib/" + lib + "\n";
58       }
59     }
60     out_file.close();
61   }
62   return 0;
63 }
64
65 bool LaunchpadParser::IsValidId(std::string loader_id, std::string pkgid) {
66   std::string needle("../");
67   size_t found = loader_id.find(needle);
68   if (found != std::string::npos) {
69     _E("Invalid loader_id(%s)", loader_id.c_str());
70     return false;
71   }
72
73   std::ifstream in_file(GetFilePath(loader_id).c_str());
74   if (!in_file.good())
75     return true;
76   std::string key, val;
77   in_file >> key;
78   while (in_file >> key >> val) {
79     if (key == "OWNER") {
80       LOGI("key (%s), val (%s)", key.c_str(), val.c_str());
81       if (val == pkgid)
82         return true;
83     }
84   }
85   return false;
86 }
87
88 int LaunchpadParser::Install(xmlDocPtr doc, std::string pkgid) {
89   pkgmgr_privilege_level level;
90   pkgmgr_installer_info_get_privilege_level(&level);
91   if (level != PM_PRIVILEGE_PLATFORM) {
92     LOGE("Privilege level(%d) is not platform", static_cast<int>(level));
93     return -1;
94   }
95
96   xmlNode* root = xmlDocGetRootElement(doc);
97   for (xmlNode* node = root->children; node; node = node->next) {
98     if (!node->name)
99       continue;
100
101     std::string name = std::string(reinterpret_cast<const char*>(node->name));
102     if (name != "provides-appdefined-loader")
103       continue;
104
105     xmlChar* val = xmlGetProp(node, reinterpret_cast<const xmlChar*>("id"));
106     std::shared_ptr<LoaderInfo> info =
107         std::make_shared<LoaderInfo>(std::string(reinterpret_cast<char*>(val)));
108     if (!IsValidId(info->GetId(), pkgid))
109       return -1;
110
111     xmlChar* ttl = xmlGetProp(node,
112         reinterpret_cast<const xmlChar*>("time-to-live"));
113     if (ttl)
114       info->SetTimeToLive(std::stoi(std::string(reinterpret_cast<char*>(ttl))));
115
116     for (xmlNode* iter = node->children; iter; iter = iter->next) {
117       if (!iter->name)
118         continue;
119       std::string child_name =
120           std::string(reinterpret_cast<const char*>(iter->name));
121       if (child_name == "preload-library") {
122         xmlChar* libname = xmlGetProp(iter,
123             reinterpret_cast<const xmlChar*>("name"));
124         if (!libname)
125           continue;
126         info->AddPreloadLib(std::string(reinterpret_cast<char*>(libname)));
127       }
128     }
129     loader_list_.push_back(info);
130   }
131   WriteToFile(pkgid);
132
133   return 0;
134 }
135
136 int LaunchpadParser::Upgrade(xmlDocPtr doc, std::string pkgid) {
137   if (UnInstall(doc, pkgid) != 0)
138     return -1;
139
140   return Install(doc, pkgid);
141 }
142
143 int LaunchpadParser::UnInstall(xmlDocPtr doc, std::string pkgid) {
144   xmlNode* root = xmlDocGetRootElement(doc);
145   for (xmlNode* node = root->children; node; node = node->next) {
146     if (!node->name)
147       continue;
148
149     std::string name = std::string(reinterpret_cast<const char*>(node->name));
150     if (name != "provides-appdefined-loader")
151       continue;
152
153     xmlChar* val = xmlGetProp(node, reinterpret_cast<const xmlChar*>("id"));
154     if (!val)
155       return -1;
156
157     std::string id = std::string(reinterpret_cast<char*>(val));
158     if (!IsValidId(id, pkgid))
159       return -1;
160     remove(GetFilePath(id).c_str());
161   }
162   return 0;
163 }
164
165 }   // namspace launchpad_parser_plugin