53b2ba624bc86beb5c56a5d8d14b1ed9db92c5e2
[framework/web/wrt-installer.git] / src / pkg-manager / backendlib.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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  *
18  *
19  * @file       backendlib.cpp
20  * @author     Soyoung Kim (sy037.kim@samsung.com)
21  * @version    0.1
22  * @brief      This is implementation file for providing widget information
23  *             to package manager
24  */
25 #include "package-manager-plugin.h"
26 #include <package-manager.h>
27 #include <regex.h>
28 #include <dlog.h>
29 #include <dpl/wrt-dao-ro/global_config.h>
30 #include <vcore/VCore.h>
31 #include <dpl/wrt-dao-ro/WrtDatabase.h>
32 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
33 #include <dpl/wrt-dao-ro/feature_dao_read_only.h>
34 #include <dpl/wrt-dao-ro/widget_config.h>
35 #include <string>
36 #include <dpl/db/sql_connection.h>
37 #include <dpl/log/log.h>
38 #include <dpl/foreach.h>
39 #include <dpl/utils/folder_size.h>
40 #include <dpl/wrt-dao-ro/wrt_db_types.h>
41 #include <dpl/copy.h>
42 #include <dpl/abstract_waitable_input_adapter.h>
43 #include <dpl/abstract_waitable_output_adapter.h>
44 #include <dpl/zip_input.h>
45 #include <dpl/binary_queue.h>
46 #include <dpl/file_input.h>
47 #include <dpl/wrt-dao-ro/config_parser_data.h>
48 #include "root_parser.h"
49 #include "widget_parser.h"
50 #include "parser_runner.h"
51
52 using namespace WrtDB;
53
54 #undef TRUE
55 #undef FALSE
56 #define TRUE 0
57 #define FALSE -1
58 #define GET_DIRECTORY_SIZE_KB(x)    (x) / 1024
59
60 #ifdef __cplusplus
61 extern "C"
62 {
63 #endif
64
65 static void pkg_native_plugin_on_unload();
66 static int pkg_plugin_app_is_installed(const char *pkg_name);
67 static int pkg_plugin_get_installed_apps_list(const char *category,
68                                               const char *option,
69                                               package_manager_pkg_info_t **list,
70                                               int *count);
71 static int pkg_plugin_get_app_detail_info(
72     const char *pkg_name,
73     package_manager_pkg_detail_info_t *
74     pkg_detail_info);
75 static int pkg_plugin_get_app_detail_info_from_package(
76     const char *pkg_path,
77     package_manager_pkg_detail_info_t
78     *pkg_detail_info);
79
80 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path);
81
82 static void pkg_native_plugin_on_unload()
83 {
84     LogDebug("pkg_native_plugin_unload() is called");
85 }
86
87 static int pkg_plugin_app_is_installed(const char *pkg_name)
88 {
89     const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$";
90     LogDebug("pkg_plugin_app_is_installed() is called");
91
92     WrtDB::WrtDatabase::attachToThreadRO();
93
94     regex_t reg;
95     if (regcomp(&reg, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
96         LogDebug("Regcomp failed");
97     }
98
99     WrtDB::TizenAppId appid;
100
101     if ((regexec(&reg, pkg_name,
102                     static_cast<size_t>(0), NULL, 0) == 0))
103     {
104         WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name));
105         appid = WidgetDAOReadOnly::getTzAppId(pkgid);
106     } else {
107         appid = DPL::FromUTF8String(pkg_name);
108     }
109
110     bool result = WidgetDAOReadOnly::isWidgetInstalled(appid);
111     WrtDB::WrtDatabase::detachFromThread();
112
113     if (result) {
114         return TRUE;
115     } else {
116         return FALSE;
117     }
118 }
119
120 static int pkg_plugin_get_installed_apps_list(const char * /*category*/,
121                                               const char * /*option*/,
122                                               package_manager_pkg_info_t **list,
123                                               int *count)
124 {
125     LogDebug("pkg_plugin_get_installed_apps_list() is called");
126
127     package_manager_pkg_info_t *pkg_list = NULL;
128     package_manager_pkg_info_t *pkg_last = NULL;
129
130     WrtDB::WrtDatabase::attachToThreadRO();
131     TizenAppIdList tizenAppidList = WidgetDAOReadOnly::getTizenAppidList();
132     *count = 0;
133
134     FOREACH(iterator, tizenAppidList) {
135         package_manager_pkg_info_t *pkg_info =
136             static_cast<package_manager_pkg_info_t*>
137             (malloc(sizeof(package_manager_pkg_info_t)));
138
139         if (NULL == pkg_list) {
140             pkg_list = pkg_info;
141             pkg_last = pkg_info;
142         } else {
143             pkg_last->next = pkg_info;
144         }
145
146         TizenAppId tzAppid = *iterator;
147         WidgetDAOReadOnly widget(tzAppid);
148         strncpy(pkg_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
149         snprintf(pkg_info->pkg_name, PKG_NAME_STRING_LEN_MAX, "%s",
150                  DPL::ToUTF8String(tzAppid).c_str());
151
152         DPL::Optional<DPL::String> version = widget.getVersion();
153         if (!version.IsNull()) {
154             strncpy(pkg_info->version,
155                     DPL::ToUTF8String(*version).c_str(),
156                     PKG_VERSION_STRING_LEN_MAX - 1);
157         }
158
159         (*count)++;
160         pkg_last = pkg_info;
161     }
162     *list = pkg_list;
163     WrtDB::WrtDatabase::detachFromThread();
164
165     return TRUE;
166 }
167
168 static int pkg_plugin_get_app_detail_info(
169     const char *pkg_name,
170     package_manager_pkg_detail_info_t *
171     pkg_detail_info)
172 {
173     LogDebug("pkg_plugin_get_app_detail_info() is called");
174
175     WrtDB::WrtDatabase::attachToThreadRO();
176     int handle = WidgetDAOReadOnly::getHandle(
177             DPL::FromUTF8String(pkg_name));
178     WidgetDAOReadOnly widget(handle);
179
180     DPL::Optional<DPL::String> version = widget.getVersion();
181     DPL::Optional<DPL::String> id = widget.getGUID();
182     DPL::Optional<DPL::String> locale = widget.getDefaultlocale();
183
184     if (!version.IsNull()) {
185         strncpy(pkg_detail_info->version,
186                 DPL::ToUTF8String(*version).c_str(),
187                 PKG_VERSION_STRING_LEN_MAX - 1);
188     }
189     snprintf(pkg_detail_info->optional_id, PKG_NAME_STRING_LEN_MAX, "%d",
190              handle);
191     WidgetLocalizedInfo localizedInfo;
192
193     if (locale.IsNull()) {
194         LogError("is NULL");
195         DPL::String languageTag(L"");
196         localizedInfo = widget.getLocalizedInfo(languageTag);
197     } else {
198         localizedInfo = widget.getLocalizedInfo(*locale);
199     }
200     DPL::Optional<DPL::String> desc(localizedInfo.description);
201
202     if (!desc.IsNull()) {
203         strncpy(pkg_detail_info->pkg_description,
204                 DPL::ToUTF8String(*desc).c_str(),
205                 PKG_VALUE_STRING_LEN_MAX - 1);
206     }
207     strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
208     strncpy(pkg_detail_info->pkg_name, pkg_name, PKG_NAME_STRING_LEN_MAX - 1);
209
210     /* set installed time */
211     pkg_detail_info->installed_time = widget.getInstallTime();
212
213     /* set Widget size */
214     DPL::String pkgName = DPL::FromUTF8String(pkg_name);
215     std::string installPath = WidgetConfig::GetWidgetBasePath(pkgName);
216     std::string persistentPath =
217         WidgetConfig::GetWidgetPersistentStoragePath(pkgName);
218     std::string tempPath =
219         WidgetConfig::GetWidgetTemporaryStoragePath(pkgName);
220     installPath += "/";
221     tempPath += "/";
222     persistentPath += "/";
223
224     size_t installedSize = Utils::getFolderSize(installPath);
225     size_t persistentSize = Utils::getFolderSize(persistentPath);
226     size_t appSize = installedSize - persistentSize;
227     size_t dataSize = persistentSize + Utils::getFolderSize(tempPath);
228
229     pkg_detail_info->installed_size = GET_DIRECTORY_SIZE_KB(installedSize);
230     pkg_detail_info->app_size = GET_DIRECTORY_SIZE_KB(appSize);
231     pkg_detail_info->data_size = GET_DIRECTORY_SIZE_KB(dataSize);
232
233     WrtDB::WrtDatabase::detachFromThread();
234     return TRUE;
235 }
236
237 int getConfigParserData(const std::string &widgetPath, ConfigParserData& configInfo)
238 {
239     const char* CONFIG_XML = "config.xml";
240     const char* WITH_OSP_XML = "res/wgt/config.xml";
241
242     Try {
243         ParserRunner parser;
244
245         std::unique_ptr<DPL::ZipInput> zipFile(
246                 new DPL::ZipInput(widgetPath));
247
248         std::unique_ptr<DPL::ZipInput::File> configFile;
249
250         // Open config.xml file
251         Try {
252             configFile.reset(zipFile->OpenFile(CONFIG_XML));
253         }
254         Catch(DPL::ZipInput::Exception::OpenFileFailed)
255         {
256             configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
257         }
258
259         // Extract config
260         DPL::BinaryQueue buffer;
261         DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
262         DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
263         DPL::Copy(&inputAdapter, &outputAdapter);
264         parser.Parse(&buffer,
265                 ElementParserPtr(
266                     new RootParser<WidgetParser>(configInfo,
267                         DPL::
268                         FromUTF32String(
269                             L"widget"))));
270     }
271     Catch(DPL::ZipInput::Exception::OpenFailed)
272     {
273         LogError("Failed to open widget package");
274         return FALSE;
275     }
276     Catch(DPL::ZipInput::Exception::OpenFileFailed)
277     {
278         LogError("Failed to open config.xml file");
279         return FALSE;
280     }
281     Catch(DPL::CopyFailed)
282     {
283         LogError("Failed to extract config.xml file");
284         return FALSE;
285     }
286     Catch(DPL::FileInput::Exception::OpenFailed)
287     {
288         LogError("Failed to open config.xml file");
289         return FALSE;
290     }
291     Catch(ElementParser::Exception::ParseError)
292     {
293         LogError("Failed to parse config.xml file");
294         return FALSE;
295     }
296     Catch(DPL::ZipInput::Exception::SeekFileFailed)
297     {
298         LogError("Failed to seek widget archive - corrupted package?");
299         return FALSE;
300     }
301
302     return TRUE;
303 }
304
305 char* getIconInfo(const std::string widgetPath,
306         const std::string icon_name, int &icon_size)
307 {
308     Try {
309         std::unique_ptr<DPL::ZipInput> zipFile(
310                 new DPL::ZipInput(widgetPath));
311
312         std::unique_ptr<DPL::ZipInput::File> iconFile;
313
314         iconFile.reset(zipFile->OpenFile(icon_name));
315
316         DPL::BinaryQueue buffer;
317         DPL::AbstractWaitableInputAdapter inputAdapter(iconFile.get());
318         DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
319         DPL::Copy(&inputAdapter, &outputAdapter);
320         icon_size = buffer.Size();
321         char *getBuffer = (char*) calloc(1, (sizeof(char) * icon_size) + 1);
322         buffer.Flatten(getBuffer, buffer.Size());
323         return getBuffer;
324     }
325     Catch(DPL::ZipInput::Exception::OpenFailed)
326     {
327         LogError("Failed to open widget package");
328         return NULL;
329     }
330     Catch(DPL::ZipInput::Exception::OpenFileFailed)
331     {
332         LogError("Failed to open icon file");
333         return NULL;
334     }
335 }
336
337 int getWidgetDetailInfoFromPackage(const char* pkgPath,
338         package_manager_pkg_detail_info_t* pkg_detail_info)
339 {
340     const std::string widget_path(pkgPath);
341     ConfigParserData configInfo;
342
343     if (FALSE == getConfigParserData(widget_path, configInfo)) {
344         return FALSE;
345     }
346
347     strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
348     if (!configInfo.tizenPkgId.IsNull()) {
349         strncpy(pkg_detail_info->pkgid,
350                 DPL::ToUTF8String(*configInfo.tizenPkgId).c_str(), PKG_TYPE_STRING_LEN_MAX);
351     }
352     if (!configInfo.version.IsNull()) {
353         strncpy(pkg_detail_info->version,
354                 DPL::ToUTF8String(*configInfo.version).c_str(),
355                 PKG_VERSION_STRING_LEN_MAX);
356     }
357
358     DPL::Optional<DPL::String> name;
359     DPL::Optional<DPL::String> desc;
360     DPL::OptionalString defaultLocale = configInfo.defaultlocale;
361
362     FOREACH(localizedData, configInfo.localizedDataSet)
363     {
364         Locale i = localizedData->first;
365         if (!!defaultLocale) {
366             if (defaultLocale == i) {
367                 name = localizedData->second.name;
368                 desc = localizedData->second.description;
369                 break;
370             }
371         } else {
372             name = localizedData->second.name;
373             desc = localizedData->second.description;
374             break;
375         }
376     }
377
378     if( !name.IsNull()) {
379         strncpy(pkg_detail_info->pkg_name, DPL::ToUTF8String(*name).c_str(), PKG_NAME_STRING_LEN_MAX);
380     }
381
382     if (!desc.IsNull()) {
383         strncpy(pkg_detail_info->pkg_description,
384                 DPL::ToUTF8String(*desc).c_str(),
385                 PKG_VALUE_STRING_LEN_MAX - 1);
386     }
387
388     if (!configInfo.tizenMinVersionRequired.IsNull()) {
389         strncpy(pkg_detail_info->min_platform_version,
390                 DPL::ToUTF8String(*configInfo.tizenMinVersionRequired).c_str(),
391                 PKG_VERSION_STRING_LEN_MAX);
392     }
393
394     if (!configInfo.authorName.IsNull()) {
395         strncpy(pkg_detail_info->author,
396                 DPL::ToUTF8String(*configInfo.authorName).c_str(),
397                 PKG_VALUE_STRING_LEN_MAX);
398     }
399
400     std::string icon_name;
401
402     FOREACH(i, configInfo.iconsList) {
403         LogDebug("icon name: " << i->src);
404         icon_name = DPL::ToUTF8String(i->src);
405         break;
406     }
407     pkg_detail_info->icon_buf = getIconInfo(widget_path, icon_name,
408             pkg_detail_info->icon_size);
409     LogDebug("icon size : " << pkg_detail_info->icon_size);
410
411     GList *privilege_list = NULL;
412     FOREACH(it, configInfo.featuresList) {
413         LogDebug("privilege : " << it->name);
414         int length = DPL::ToUTF8String(it->name).length();
415         char *privilege = (char*) calloc(1, (sizeof(char) * length) + 1);
416         snprintf(privilege, length + 1, "%s",
417                 DPL::ToUTF8String(it->name).c_str());
418         privilege_list = g_list_append(privilege_list, privilege);
419     }
420     pkg_detail_info->privilege_list = privilege_list;
421
422     return TRUE;
423 }
424
425 static int pkg_plugin_get_app_detail_info_from_package(
426     const char * pkg_path,
427     package_manager_pkg_detail_info_t * pkg_detail_info)
428 {
429     LogDebug("pkg_plugin_get_app_detail_info_from_package() is called");
430     return getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info);
431 }
432
433 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path)
434 {
435     LogDebug("pkgmgr_client_check_pkginfo_from_file() is called");
436     package_manager_pkg_detail_info_t pkg_detail_info;
437     int ret = getWidgetDetailInfoFromPackage(pkg_path, &pkg_detail_info);
438     if (FALSE == ret) {
439         LogError("Failed to get package detail info ");
440         return NULL;
441     }
442     return &pkg_detail_info;
443 }
444
445 __attribute__ ((visibility("default")))
446 int pkg_plugin_on_load(pkg_plugin_set *set)
447 {
448     DPL::Log::LogSystemSingleton::Instance().SetTag("WGT-BACKLIB");
449     if (NULL == set) {
450         return FALSE;
451     }
452     memset(set, 0x00, sizeof(pkg_plugin_set));
453
454     set->plugin_on_unload = pkg_native_plugin_on_unload;
455     set->pkg_is_installed = pkg_plugin_app_is_installed;
456     set->get_installed_pkg_list = pkg_plugin_get_installed_apps_list;
457     set->get_pkg_detail_info = pkg_plugin_get_app_detail_info;
458     set->get_pkg_detail_info_from_package =
459         pkg_plugin_get_app_detail_info_from_package;
460
461     return TRUE;
462 }
463
464 #ifdef __cplusplus
465 }
466 #endif