2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file backendlib.cpp
20 * @author Soyoung Kim (sy037.kim@samsung.com)
22 * @brief This is implementation file for providing widget information
25 #include "package-manager-plugin.h"
26 #include <package-manager.h>
28 #include <dpl/wrt-dao-ro/global_config.h>
29 #include <vcore/VCore.h>
30 #include <dpl/wrt-dao-ro/WrtDatabase.h>
31 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
32 #include <dpl/wrt-dao-ro/feature_dao_read_only.h>
33 #include <dpl/wrt-dao-ro/widget_config.h>
35 #include <dpl/db/sql_connection.h>
36 #include <dpl/foreach.h>
37 #include <dpl/utils/folder_size.h>
38 #include <dpl/wrt-dao-ro/wrt_db_types.h>
40 #include <dpl/abstract_waitable_input_adapter.h>
41 #include <dpl/abstract_waitable_output_adapter.h>
42 #include <dpl/zip_input.h>
43 #include <dpl/binary_queue.h>
44 #include <dpl/file_input.h>
45 #include <dpl/wrt-dao-ro/config_parser_data.h>
46 #include <dpl/localization/LanguageTagsProvider.h>
47 #include <dpl/optional_typedefs.h>
48 #include "root_parser.h"
49 #include "widget_parser.h"
50 #include "parser_runner.h"
51 #include <dpl/log/log.h>
52 #include <dpl/log/secure_log.h>
54 using namespace WrtDB;
60 #define GET_DIRECTORY_SIZE_KB(x) (x) / 1024
67 static void pkg_native_plugin_on_unload();
68 static int pkg_plugin_app_is_installed(const char *pkg_name);
69 static int pkg_plugin_get_installed_apps_list(const char *category,
71 package_manager_pkg_info_t **list,
73 static int pkg_plugin_get_app_detail_info(
75 package_manager_pkg_detail_info_t *
77 static int pkg_plugin_get_app_detail_info_from_package(
79 package_manager_pkg_detail_info_t
82 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path);
84 static void pkg_native_plugin_on_unload()
86 _D("pkg_native_plugin_unload() is called");
89 // regexec() function does not work properly in specific locale (ex, Estonian)
90 // So, change locale temporally before call regcomp and regexec
94 currentLocale = setlocale(LC_ALL , NULL);
95 if (NULL == setlocale(LC_ALL, "C")) {
96 _W("Failed to change locale to \"C\"");
101 if (NULL == setlocale(LC_ALL, currentLocale.c_str())) {
102 _W("Failed to set previous locale");
107 std::string currentLocale;
110 static int pkg_plugin_app_is_installed(const char *pkg_name)
112 const char* REG_PKGID_PATTERN = "^[a-zA-Z0-9]{10}$";
113 _D("pkg_plugin_app_is_installed() is called");
115 WrtDB::WrtDatabase::attachToThreadRO();
120 if (regcomp(®, REG_PKGID_PATTERN, REG_NOSUB | REG_EXTENDED) != 0) {
121 _D("Regcomp failed");
124 if (!(regexec(®, pkg_name,
125 static_cast<size_t>(0), NULL, 0) == 0))
127 _E("Invalid argument : %s", pkg_name);
133 WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name));
134 WrtDB::TizenAppId appid = WidgetDAOReadOnly::getTizenAppId(pkgid);
135 _D("appid : %ls", appid.c_str());
136 } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
137 WrtDB::WrtDatabase::detachFromThread();
140 WrtDB::WrtDatabase::detachFromThread();
144 static int pkg_plugin_get_installed_apps_list(const char * /*category*/,
145 const char * /*option*/,
146 package_manager_pkg_info_t **list,
149 _D("pkg_plugin_get_installed_apps_list() is called");
151 package_manager_pkg_info_t *pkg_list = NULL;
152 package_manager_pkg_info_t *pkg_last = NULL;
154 WrtDB::WrtDatabase::attachToThreadRO();
155 TizenAppIdList tizenAppIdList = WidgetDAOReadOnly::getTizenAppIdList();
158 FOREACH(iterator, tizenAppIdList) {
159 package_manager_pkg_info_t *pkg_info =
160 static_cast<package_manager_pkg_info_t*>
161 (malloc(sizeof(package_manager_pkg_info_t)));
163 if (pkg_info == NULL) {
167 if (NULL == pkg_list) {
171 pkg_last->next = pkg_info;
174 TizenAppId tzAppid = *iterator;
175 WidgetDAOReadOnly widget(tzAppid);
176 strncpy(pkg_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
177 snprintf(pkg_info->pkg_name, PKG_NAME_STRING_LEN_MAX, "%s",
178 DPL::ToUTF8String(tzAppid).c_str());
180 DPL::OptionalString version = widget.getVersion();
182 strncpy(pkg_info->version,
183 DPL::ToUTF8String(*version).c_str(),
184 PKG_VERSION_STRING_LEN_MAX - 1);
191 WrtDB::WrtDatabase::detachFromThread();
196 static int pkg_plugin_get_app_detail_info(
197 const char *pkg_name,
198 package_manager_pkg_detail_info_t *
201 _D("pkg_plugin_get_app_detail_info() is called");
203 WrtDB::WrtDatabase::attachToThreadRO();
205 WrtDB::TizenAppId appid;
207 WrtDB::TizenPkgId pkgid(DPL::FromUTF8String(pkg_name));
208 appid = WidgetDAOReadOnly::getTizenAppId(pkgid);
209 _D("appid : %ls", appid.c_str());
210 } Catch(WidgetDAOReadOnly::Exception::WidgetNotExist) {
211 WrtDB::WrtDatabase::detachFromThread();
215 WidgetDAOReadOnly widget(appid);
217 DPL::OptionalString version = widget.getVersion();
218 DPL::OptionalString id = widget.getGUID();
219 DPL::OptionalString locale = widget.getDefaultlocale();
222 strncpy(pkg_detail_info->version,
223 DPL::ToUTF8String(*version).c_str(),
224 PKG_VERSION_STRING_LEN_MAX - 1);
226 snprintf(pkg_detail_info->pkgid, PKG_NAME_STRING_LEN_MAX, "%s",
228 snprintf(pkg_detail_info->optional_id, PKG_NAME_STRING_LEN_MAX, "%s",
229 DPL::ToUTF8String(appid).c_str());
230 WidgetLocalizedInfo localizedInfo;
233 _D("locale is NULL");
234 DPL::String languageTag(L"");
235 localizedInfo = widget.getLocalizedInfo(languageTag);
237 localizedInfo = widget.getLocalizedInfo(*locale);
239 DPL::OptionalString desc(localizedInfo.description);
242 strncpy(pkg_detail_info->pkg_description,
243 DPL::ToUTF8String(*desc).c_str(),
244 PKG_VALUE_STRING_LEN_MAX - 1);
246 strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
247 strncpy(pkg_detail_info->pkg_name, pkg_name, PKG_NAME_STRING_LEN_MAX - 1);
249 std::string min_version = DPL::ToUTF8String((*widget.getMinimumWacVersion()));
251 strncpy(pkg_detail_info->min_platform_version, min_version.c_str(),
252 PKG_VERSION_STRING_LEN_MAX - 1);
254 /* set installed time */
255 pkg_detail_info->installed_time = widget.getInstallTime();
257 /* set Widget size */
258 DPL::String pkgName = DPL::FromUTF8String(pkg_name);
259 std::string installPath = WidgetConfig::GetWidgetBasePath(pkgName);
260 std::string persistentPath =
261 WidgetConfig::GetWidgetPersistentStoragePath(pkgName);
262 std::string tempPath =
263 WidgetConfig::GetWidgetTemporaryStoragePath(pkgName);
266 persistentPath += "/";
268 size_t installedSize = Utils::getFolderSize(installPath);
269 size_t persistentSize = Utils::getFolderSize(persistentPath);
270 size_t appSize = installedSize - persistentSize;
271 size_t dataSize = persistentSize + Utils::getFolderSize(tempPath);
273 pkg_detail_info->installed_size = GET_DIRECTORY_SIZE_KB(installedSize);
274 pkg_detail_info->app_size = GET_DIRECTORY_SIZE_KB(appSize);
275 pkg_detail_info->data_size = GET_DIRECTORY_SIZE_KB(dataSize);
277 WrtDB::WrtDatabase::detachFromThread();
281 int getConfigParserData(const std::string &widgetPath, ConfigParserData& configInfo)
283 const char* CONFIG_XML = "config.xml";
284 const char* WITH_OSP_XML = "res/wgt/config.xml";
289 std::unique_ptr<DPL::ZipInput> zipFile(
290 new DPL::ZipInput(widgetPath));
292 std::unique_ptr<DPL::ZipInput::File> configFile;
294 // Open config.xml file
296 configFile.reset(zipFile->OpenFile(CONFIG_XML));
298 Catch(DPL::ZipInput::Exception::OpenFileFailed)
300 configFile.reset(zipFile->OpenFile(WITH_OSP_XML));
304 DPL::BinaryQueue buffer;
305 DPL::AbstractWaitableInputAdapter inputAdapter(configFile.get());
306 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
307 DPL::Copy(&inputAdapter, &outputAdapter);
308 parser.Parse(&buffer,
310 new RootParser<WidgetParser>(configInfo,
315 Catch(DPL::ZipInput::Exception::OpenFailed)
317 _E("Failed to open widget package");
320 Catch(DPL::ZipInput::Exception::OpenFileFailed)
322 _E("Failed to open config.xml file");
325 Catch(DPL::CopyFailed)
327 _E("Failed to extract config.xml file");
330 Catch(DPL::FileInput::Exception::OpenFailed)
332 _E("Failed to open config.xml file");
335 Catch(ElementParser::Exception::ParseError)
337 _E("Failed to parse config.xml file");
340 Catch(DPL::ZipInput::Exception::SeekFileFailed)
342 _E("Failed to seek widget archive - corrupted package?");
349 char* getIconInfo(const std::string &widgetPath,
350 const std::string &icon_name, int &icon_size)
353 std::unique_ptr<DPL::ZipInput> zipFile(
354 new DPL::ZipInput(widgetPath));
356 std::unique_ptr<DPL::ZipInput::File> iconFile;
359 iconFile.reset(zipFile->OpenFile(icon_name));
361 Catch(DPL::ZipInput::Exception::OpenFileFailed)
363 _D("This web app is hybrid web app");
364 std::string hybrid_icon = "res/wgt/" + icon_name;
365 iconFile.reset(zipFile->OpenFile(hybrid_icon));
368 DPL::BinaryQueue buffer;
369 DPL::AbstractWaitableInputAdapter inputAdapter(iconFile.get());
370 DPL::AbstractWaitableOutputAdapter outputAdapter(&buffer);
371 DPL::Copy(&inputAdapter, &outputAdapter);
372 icon_size = buffer.Size();
373 char *getBuffer = (char*) calloc(1, (sizeof(char) * icon_size) + 1);
374 buffer.Flatten(getBuffer, buffer.Size());
377 Catch(DPL::ZipInput::Exception::OpenFailed)
379 _D("Failed to open widget package");
382 Catch(DPL::ZipInput::Exception::OpenFileFailed)
384 _D("Not found icon file %s", icon_name.c_str());
389 char* getIconForLocale(const std::string& bp, const std::string& tag,
390 const std::string& icon, int & size)
392 std::string iconPath;
394 iconPath += std::string("locales/") + tag;
396 if (!iconPath.empty()) {
401 return getIconInfo(bp, iconPath, size);
404 char* getIcon(const std::string & basepath, const WrtDB::ConfigParserData & config, int & size)
406 const std::list<std::string> defaultIcons{ "icon.svg", "icon.ico", "icon.png", "icon.gif", "icon.jpg" };
407 LanguageTags tagsList =
408 LanguageTagsProviderSingleton::Instance().getLanguageTags();
410 char * result = NULL;
412 //for each locale tag - searching for icon presence and returning raw data
413 //first found is best as locale tags are ordered
414 FOREACH(tag, tagsList)
416 FOREACH(icon, config.iconsList)
418 std::string src = DPL::ToUTF8String(icon->src);
419 result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), src, size);
424 FOREACH(i, defaultIcons)
426 result = getIconForLocale(basepath, DPL::ToUTF8String(*tag), *i, size);
435 int getWidgetDetailInfoFromPackage(const char* pkgPath,
436 package_manager_pkg_detail_info_t* pkg_detail_info)
438 const std::string widget_path(pkgPath);
439 ConfigParserData configInfo;
441 if (FALSE == getConfigParserData(widget_path, configInfo)) {
445 strncpy(pkg_detail_info->pkg_type, "wgt", PKG_TYPE_STRING_LEN_MAX);
446 if (!!configInfo.tizenPkgId) {
447 strncpy(pkg_detail_info->pkgid,
448 DPL::ToUTF8String(*configInfo.tizenPkgId).c_str(), PKG_TYPE_STRING_LEN_MAX - 1);
450 if (!!configInfo.tizenAppId) {
451 strncpy(pkg_detail_info->pkg_name,
452 DPL::ToUTF8String(*configInfo.tizenAppId).c_str(),
453 PKG_NAME_STRING_LEN_MAX - 1);
455 if (!!configInfo.version) {
456 strncpy(pkg_detail_info->version,
457 DPL::ToUTF8String(*configInfo.version).c_str(),
458 PKG_VERSION_STRING_LEN_MAX - 1);
461 DPL::OptionalString name;
462 DPL::OptionalString desc;
464 LanguageTags tags = LanguageTagsProviderSingleton::Instance().getLanguageTags();
466 auto toLowerCase = [](const DPL::String & r)
469 std::transform(r.begin(), r.end(), std::inserter(result, result.begin()), ::tolower);
473 if (!!configInfo.defaultlocale)
475 Locale & dl = *configInfo.defaultlocale;
476 configInfo.defaultlocale = toLowerCase(dl);
479 bool isNameFound = false;
480 bool isDescFound = false;
483 *tag = toLowerCase(*tag);
484 FOREACH(localizedData, configInfo.localizedDataSet)
486 Locale i = localizedData->first;
489 if (!!configInfo.defaultlocale && *configInfo.defaultlocale == i)
492 name = localizedData->second.name;
494 desc = localizedData->second.description;
500 name = localizedData->second.name;
506 desc = localizedData->second.description;
512 if (isNameFound && isDescFound) break;
516 strncpy(pkg_detail_info->label, DPL::ToUTF8String(*name).c_str(),
517 PKG_LABEL_STRING_LEN_MAX - 1);
521 strncpy(pkg_detail_info->pkg_description,
522 DPL::ToUTF8String(*desc).c_str(),
523 PKG_VALUE_STRING_LEN_MAX - 1);
526 if (!!configInfo.tizenMinVersionRequired) {
527 strncpy(pkg_detail_info->min_platform_version,
528 DPL::ToUTF8String(*configInfo.tizenMinVersionRequired).c_str(),
529 PKG_VERSION_STRING_LEN_MAX - 1);
532 if (!!configInfo.authorName) {
533 strncpy(pkg_detail_info->author,
534 DPL::ToUTF8String(*configInfo.authorName).c_str(),
535 PKG_VALUE_STRING_LEN_MAX - 1);
539 pkg_detail_info->privilege_list = NULL;
540 FOREACH(it, configInfo.featuresList) {
541 std::string featureInfo = DPL::ToUTF8String(it->name);
542 _D("privilege : %s", featureInfo.c_str());
543 int length = featureInfo.size();
544 char *privilege = (char*) calloc(1, (sizeof(char) * (length + 1)));
545 if (privilege == NULL) {
548 snprintf(privilege, length + 1, "%s", featureInfo.c_str());
549 pkg_detail_info->privilege_list =
550 g_list_append(pkg_detail_info->privilege_list, privilege);
553 char* icon_buf = getIcon(widget_path, configInfo, pkg_detail_info->icon_size);
556 _D("icon size : %d", pkg_detail_info->icon_size);
557 pkg_detail_info->icon_buf = icon_buf;
560 pkg_detail_info->icon_size = 0;
561 pkg_detail_info->icon_buf = NULL;
567 static int pkg_plugin_get_app_detail_info_from_package(
568 const char * pkg_path,
569 package_manager_pkg_detail_info_t * pkg_detail_info)
571 _D("pkg_plugin_get_app_detail_info_from_package() is called");
572 return getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info);
575 pkgmgr_info *pkgmgr_client_check_pkginfo_from_file(const char *pkg_path)
577 _D("pkgmgr_client_check_pkginfo_from_file() is called");
578 package_manager_pkg_detail_info_t *pkg_detail_info;
579 pkg_detail_info = (package_manager_pkg_detail_info_t*)malloc(
580 sizeof(package_manager_pkg_detail_info_t));
581 if (pkg_detail_info == NULL) {
582 _E("Failed to get memory alloc");
585 int ret = getWidgetDetailInfoFromPackage(pkg_path, pkg_detail_info);
587 _E("Failed to get package detail info ");
588 free(pkg_detail_info);
591 return reinterpret_cast<pkgmgr_info*>(pkg_detail_info);
594 __attribute__ ((visibility("default")))
595 int pkg_plugin_on_load(pkg_plugin_set *set)
600 memset(set, 0x00, sizeof(pkg_plugin_set));
602 set->plugin_on_unload = pkg_native_plugin_on_unload;
603 set->pkg_is_installed = pkg_plugin_app_is_installed;
604 set->get_installed_pkg_list = pkg_plugin_get_installed_apps_list;
605 set->get_pkg_detail_info = pkg_plugin_get_app_detail_info;
606 set->get_pkg_detail_info_from_package =
607 pkg_plugin_get_app_detail_info_from_package;