Fix crash issue when getting the locale was failed
[platform/core/appfw/wgt-backend.git] / src / lib / wgt_archive_info.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 "lib/wgt_archive_info.h"
6
7 #include <package-manager-plugin.h>
8 #include <pkgmgr-info.h>
9 #include <vconf.h>
10
11 #include <wgt_manifest_handlers/widget_config_parser.h>
12 #include <wgt_manifest_handlers/application_icons_handler.h>
13 #include <wgt_manifest_handlers/application_manifest_constants.h>
14 #include <wgt_manifest_handlers/permissions_handler.h>
15 #include <wgt_manifest_handlers/tizen_application_handler.h>
16 #include <wgt_manifest_handlers/widget_handler.h>
17
18 #include <common/utils/file_util.h>
19
20 #include <cstdio>
21 #include <cstdlib>
22 #include <fstream>
23 #include <string>
24 #include <vector>
25
26 namespace bf = boost::filesystem;
27 namespace ci = common_installer;
28
29 namespace {
30
31 const char kVconfLanguageKey[] = VCONFKEY_LANGSET;
32 const char kConfigFileName[] = "config.xml";
33 const char kHybridConfigFileName[] = "res/wgt/config.xml";
34
35 bool ExtractPackageArchive(const char* file_path, const char* file,
36     const bf::path& tmp_dir) {
37   if (!ci::ExtractToTmpDir(file_path, tmp_dir, file)) {
38     LOG(ERROR) << "Failed to extract";
39     return false;
40   }
41   return true;
42 }
43
44 bool GetPackageInfo(const wgt::parse::WidgetConfigParser& parser,
45     package_manager_pkg_detail_info_t* info) {
46   auto widget_info =
47       std::static_pointer_cast<const wgt::parse::WidgetInfo>(
48           parser.GetManifestData(wgt::parse::WidgetInfo::Key()));
49   auto app_info =
50       std::static_pointer_cast<const wgt::parse::TizenApplicationInfo>(
51           parser.GetManifestData(wgt::parse::TizenApplicationInfo::Key()));
52   if (!widget_info || !app_info) {
53     LOG(ERROR) << "WidgetInfo / TizenApplicationInfo not found";
54     return false;
55   }
56
57   snprintf(info->pkg_type, sizeof(info->pkg_type), "wgt");
58   snprintf(info->version, sizeof(info->version), "%s",
59       widget_info->version().c_str());
60   snprintf(info->author, sizeof(info->version), "%s",
61       widget_info->author().c_str());
62
63   snprintf(info->pkg_name, sizeof(info->pkg_name), "%s",
64       app_info->package().c_str());
65   snprintf(info->pkgid, sizeof(info->pkgid), "%s", app_info->package().c_str());
66   snprintf(info->api_version, sizeof(info->api_version), "%s",
67       app_info->required_version().c_str());
68
69   return true;
70 }
71
72 bool GetPrivilegesInfo(const wgt::parse::WidgetConfigParser& parser,
73     package_manager_pkg_detail_info_t* info) {
74   auto privileges_info =
75       std::static_pointer_cast<const wgt::parse::PermissionsInfo>(
76           parser.GetManifestData(wgt::parse::PermissionsInfo::Key()));
77   if (!privileges_info)
78     return false;
79
80   const auto& privileges = privileges_info->GetAPIPermissions();
81   for (auto& priv : privileges) {
82     info->privilege_list = g_list_append(info->privilege_list,
83         strdup(priv.c_str()));
84   }
85
86   return true;
87 }
88
89 bool GetLabelInfo(const wgt::parse::WidgetConfigParser& parser,
90     const char* locale, package_manager_pkg_detail_info_t* info) {
91   auto widget_info =
92       std::static_pointer_cast<const wgt::parse::WidgetInfo>(
93           parser.GetManifestData(wgt::parse::WidgetInfo::Key()));
94   if (!widget_info)
95     return false;
96
97   std::string name;
98   const auto& labels = widget_info->name_set();
99   if (labels.find(locale) != labels.end()) {
100     name = labels.find(locale)->second;
101     snprintf(info->label, sizeof(info->label), "%s", name.c_str());
102     return true;
103   } else if (labels.find("") != labels.end()) {
104     name = labels.find("")->second;
105     snprintf(info->label, sizeof(info->label), "%s", name.c_str());
106     return true;
107   }
108
109   return false;
110 }
111
112 bool GetDescriptionInfo(const wgt::parse::WidgetConfigParser& parser,
113     const char* locale, package_manager_pkg_detail_info_t* info) {
114   auto widget_info =
115       std::static_pointer_cast<const wgt::parse::WidgetInfo>(
116           parser.GetManifestData(wgt::parse::WidgetInfo::Key()));
117   if (!widget_info)
118     return false;
119
120   std::string desc;
121   const auto& descriptions = widget_info->description_set();
122   if (descriptions.find(locale) != descriptions.end()) {
123     desc = descriptions.find(locale)->second;
124     snprintf(info->pkg_description, sizeof(info->pkg_description), "%s",
125         desc.c_str());
126     return true;
127   } else if (descriptions.find("") != descriptions.end()) {
128     desc = descriptions.find("")->second;
129     snprintf(info->pkg_description, sizeof(info->pkg_description), "%s",
130         desc.c_str());
131     return true;
132   }
133
134   return false;
135 }
136
137 bool ReadIcon(const bf::path& icon, const bf::path& tmp_dir,
138     package_manager_pkg_detail_info_t* info) {
139   bf::path icon_path = tmp_dir / icon;
140
141   LOG(INFO) << "Icon file path: " << icon_path;
142
143   std::ifstream ifs(icon_path.c_str(),
144       std::ifstream::in | std::ifstream::binary);
145   ifs.seekg(0, ifs.end);
146   int len = ifs.tellg();
147   ifs.seekg(0, ifs.beg);
148
149   if (len <= 0)
150     return false;
151
152   char* buf = static_cast<char*>(malloc(sizeof(char) * len));
153
154   LOG(INFO) << "Reading icon file, " << len << " bytes";
155   ifs.read(buf, len);
156
157   info->icon_buf = buf;
158   info->icon_size = len;
159
160   return true;
161 }
162
163 std::string GetIconInfo(const wgt::parse::WidgetConfigParser& parser) {
164   auto icons_info =
165       std::static_pointer_cast<const wgt::parse::ApplicationIconsInfo>(
166           parser.GetManifestData(wgt::parse::ApplicationIconsInfo::Key()));
167   if (!icons_info)
168     return {};
169
170   return std::string(icons_info->icons().front().path());
171 }
172
173 }  // namespace
174
175 bool WgtArchiveInfo::GetArchiveInfo(const char* file_path,
176     package_manager_pkg_detail_info_t* info) {
177   bf::path tmp_dir = ci::GenerateTmpDir("/tmp");
178   if (!ci::CreateDir(tmp_dir))
179     return false;
180   LOG(DEBUG) << "Unpack at temporary dir: " << tmp_dir;
181   bool is_hybrid = false;
182   if (!ExtractPackageArchive(file_path, kHybridConfigFileName, tmp_dir))
183     return false;
184   if (bf::exists(tmp_dir / kHybridConfigFileName)) {
185     is_hybrid = true;
186   } else {
187     if (!ExtractPackageArchive(file_path, kConfigFileName, tmp_dir))
188       return false;
189   }
190
191   wgt::parse::WidgetConfigParser parser;
192   bf::path manifest_path;
193   if (is_hybrid)
194     manifest_path = tmp_dir / kHybridConfigFileName;
195   else
196     manifest_path = tmp_dir / kConfigFileName;
197   if (!parser.ParseManifest(manifest_path)) {
198     LOG(ERROR) << "Failed to parse";
199     bf::remove_all(tmp_dir);
200     return false;
201   }
202
203   if (!GetPackageInfo(parser, info)) {
204     LOG(ERROR) << "Failed to get package info";
205     bf::remove_all(tmp_dir);
206     return false;
207   }
208   if (!GetPrivilegesInfo(parser, info))
209     LOG(WARNING) << "Failed to get privileges info";
210   std::string icon = GetIconInfo(parser);
211   if (!icon.empty()) {
212     std::string icon_path;
213     if (is_hybrid)
214       icon_path = "res/wgt/" + icon;
215     else
216       icon_path = icon;
217     if (!ExtractPackageArchive(file_path, icon_path.c_str(), tmp_dir)) {
218       bf::remove_all(tmp_dir);
219       return false;
220     }
221     if (!ReadIcon(icon_path, tmp_dir, info)) {
222       LOG(WARNING) << "Failed to get icon info";
223       bf::remove_all(tmp_dir);
224       return false;
225     }
226   }
227
228   char* locale = vconf_get_str(kVconfLanguageKey);
229   if (!locale)
230     locale = strdup("");
231   if (!GetLabelInfo(parser, locale, info))
232     LOG(WARNING) << "Failed to get label info";
233   if (!GetDescriptionInfo(parser, locale, info))
234     LOG(WARNING) << "Failed to get description info";
235
236   free(locale);
237   bf::remove_all(tmp_dir);
238
239   return true;
240 }