Update wrt-installer_0.0.54
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_widget_config.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  * @file    task_widget_config.cpp
18  * @author  Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task widget config
21  */
22
23 #include <sstream>
24 #include <string>
25 #include <sys/stat.h>
26 #include <dirent.h>
27
28 #include <dpl/errno_string.h>
29 #include <dpl/foreach.h>
30 #include <dpl/localization/w3c_file_localization.h>
31 #include <dpl/singleton_impl.h>
32 #include <dpl/utils/file_utils.h>
33 #include <dpl/utils/mime_type_utils.h>
34 #include <dpl/utils/wrt_global_settings.h>
35 #include <dpl/utils/wrt_utility.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37 #include <dpl/wrt-dao-rw/feature_dao.h>
38
39 #include <libiriwrapper.h>
40 #include <parser_runner.h>
41 #include <root_parser.h>
42
43 #include <widget_install/job_widget_install.h>
44 #include <widget_install/task_widget_config.h>
45 #include <widget_install/widget_install_context.h>
46 #include <widget_install/widget_install_errors.h>
47 #include <widget_parser.h>
48 #include <wrt_error.h>
49
50
51 namespace { // anonymous
52 const WidgetHandle WIDGET_HANDLE_START_VALUE = 1000;
53 const DPL::String BR = DPL::FromUTF8String("<br>");
54 const std::string WIDGET_NOT_COMPATIBLE = "This widget is "
55         "not compatible with WRT.<br><br>";
56 const std::string QUESTION = "Do you want to install it anyway?";
57
58 const char *const DEFAULT_LANGUAGE = "default";
59 const size_t MAX_WIDGET_PATH_SIZE = 1024;
60
61 const char *const WRT_WIDGET_CONFIG_FILE_NAME = "config.xml";
62 }
63
64
65 namespace Jobs {
66 namespace WidgetInstall {
67 void InstallerTaskWidgetPopupData::PopupData::addWidgetInfo(
68         const DPL::String &info)
69 {
70     widgetInfo = info;
71 }
72
73 TaskWidgetConfig::TaskWidgetConfig(InstallerContext& installContext) :
74     DPL::TaskDecl<TaskWidgetConfig>(this),
75     m_installContext(installContext),
76     WidgetInstallPopup(installContext)
77 {
78     AddStep(&TaskWidgetConfig::StepProcessConfigurationFile);
79     AddStep(&TaskWidgetConfig::ReadLocaleFolders);
80     AddStep(&TaskWidgetConfig::ProcessLocalizedStartFiles);
81     AddStep(&TaskWidgetConfig::ProcessLocalizedIcons);
82     AddStep(&TaskWidgetConfig::StepVerifyFeatures);
83
84     if (!GlobalSettings::TestModeEnabled() && !m_installContext.m_quiet) {
85         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterVerifyFeatures);
86         AddStep(&TaskWidgetConfig::StepShowWidgetInfo);
87         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallation);
88         AddStep(&TaskWidgetConfig::StepCheckMinVersionInfo);
89         AddStep(&TaskWidgetConfig::StepCancelWidgetInstallationAfterMinVersion);
90         AddStep(&TaskWidgetConfig::StepDeletePopupWin);
91     }
92 }
93
94 void TaskWidgetConfig::StepProcessConfigurationFile()
95 {
96     Try
97     {
98         std::string path = m_installContext.locations->getConfigurationDir();
99         LogInfo("path: " << path);
100
101         processFile(path, m_installContext.widgetConfig);
102     }
103     Catch(Exception::ConfigParseFailed)
104     {
105         LogError("Parsing failed.");
106         ReThrow(Exceptions::WidgetConfigFileInvalid);
107     }
108     Try
109     {
110         // To get widget type for distribute WAC, TIZEN WebApp
111         setApplicationType();
112     }
113     Catch(Exception::ConfigParseFailed)
114     {
115         LogError("Config.xml has more than one namespace");
116         ReThrow(Exceptions::WidgetConfigFileInvalid);
117     }
118
119     m_installContext.job->UpdateProgress(
120         InstallerContext::INSTALL_WIDGET_CONFIG1,
121         "Parse elements of configuration file and save them");
122 }
123
124 void TaskWidgetConfig::ReadLocaleFolders()
125 {
126     LogDebug("Reading locale");
127     //Adding default locale
128     m_localeFolders.insert(L"");
129
130     std::string localePath = m_installContext.locations->getConfigurationDir() + "/locales";
131     DIR* localeDir = opendir(localePath.c_str());
132     if (!localeDir) {
133         LogDebug("No /locales directory in the widget package.");
134         return;
135     }
136
137     struct dirent* dirent;
138     struct stat statStruct;
139     do {
140         errno = 0;
141         if ((dirent = readdir(localeDir))) {
142             DPL::String dirName = DPL::FromUTF8String(dirent->d_name);
143             std::string absoluteDirName = localePath + "/";
144             absoluteDirName += dirent->d_name;
145
146             if (stat(absoluteDirName.c_str(), &statStruct) != 0) {
147                 LogError("stat() failed with " << DPL::GetErrnoString());
148                 continue;
149             }
150
151             if (S_ISDIR(statStruct.st_mode)) {
152                 //Yes, we ignore current, parent & hidden directories
153                 if (dirName[0] != L'.') {
154                     LogDebug("Adding locale directory \"" << dirName << "\"");
155                     m_localeFolders.insert(dirName);
156                 }
157             }
158         }
159     }
160     while (dirent);
161
162     if (errno != 0) {
163         LogError("readdir() failed with " << DPL::GetErrnoString());
164     }
165
166     if (closedir(localeDir)) {
167         LogError("closedir() failed with " << DPL::GetErrnoString());
168     }
169 }
170
171 void TaskWidgetConfig::ProcessLocalizedStartFiles()
172 {
173     typedef DPL::String S;
174     ProcessStartFile(
175         m_installContext.widgetConfig.configInfo.startFile,
176         m_installContext.widgetConfig.configInfo.
177             startFileContentType,
178         m_installContext.widgetConfig.configInfo.startFileEncoding,
179         true);
180     ProcessStartFile(S(L"index.htm"), S(L"text/html"));
181     ProcessStartFile(S(L"index.html"), S(L"text/html"));
182     ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml"));
183     ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml"));
184     ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml"));
185     // TODO: (l.wrzosek) we need better check if in current locales widget is valid.
186     FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) {
187         if (it->propertiesForLocales.size() > 0) {
188             return;
189         }
190     }
191     ThrowMsg(Exceptions::WidgetConfigFileInvalid,
192              L"The Widget has no valid start file");
193 }
194
195 void TaskWidgetConfig::ProcessStartFile(const DPL::OptionalString& path,
196         const DPL::OptionalString& type,
197         const DPL::OptionalString& encoding,
198         bool typeForcedInConfig)
199 {
200     using namespace WrtDB;
201
202     if (!!path) {
203         WidgetRegisterInfo::LocalizedStartFile startFileData;
204         startFileData.path = *path;
205
206         FOREACH(i, m_localeFolders) {
207             DPL::String pathPrefix = *i;
208             if (!pathPrefix.empty()) {
209                 pathPrefix = L"locales/" + pathPrefix + L"/";
210             }
211
212             DPL::String relativePath = pathPrefix + *path;
213             DPL::String absolutePath = DPL::FromUTF8String(
214                     m_installContext.locations->getConfigurationDir()) + L"/" + relativePath;
215
216             // get property data from packaged app
217             if (FileUtils::FileExists(absolutePath)) {
218                 WidgetRegisterInfo::StartFileProperties startFileProperties;
219                 if (!!type) {
220                     startFileProperties.type = *type;
221                 } else {
222                     startFileProperties.type =
223                         MimeTypeUtils::identifyFileMimeType(absolutePath);
224                 }
225
226                 //proceed only if MIME type is supported
227                 if (MimeTypeUtils::isMimeTypeSupportedForStartFile(
228                         startFileProperties.type))
229                 {
230                     if (!!encoding) {
231                         startFileProperties.encoding = *encoding;
232                     } else {
233                         MimeTypeUtils::MimeAttributes attributes =
234                             MimeTypeUtils::getMimeAttributes(
235                             startFileProperties.type);
236                         if (attributes.count(L"charset") > 0) {
237                             startFileProperties.encoding =
238                                 attributes[L"charset"];
239                         } else {
240                             startFileProperties.encoding = L"UTF-8";
241                         }
242                     }
243
244                     startFileData.propertiesForLocales[*i] =
245                         startFileProperties;
246                 } else {
247                     //9.1.16.5.content.8
248                     //(there seems to be no similar requirement in .6,
249                     //so let's throw only when mime type is
250                     // provided explcitly in config.xml)
251                     if (typeForcedInConfig) {
252                         ThrowMsg(Exceptions::WidgetConfigFileInvalid,
253                                  "Unsupported MIME type for start file.");
254                     }
255                 }
256             } else {
257                 // set property data for hosted start url
258                 // Hosted start url only support TIZEN WebApp
259                 if (m_installContext.widgetConfig.type ==
260                         APP_TYPE_TIZENWEBAPP)
261                 {
262                     const char *startPath =
263                         DPL::ToUTF8String(startFileData.path).c_str();
264                     if (strstr(startPath, "http") == startPath) {
265                         WidgetRegisterInfo::StartFileProperties
266                             startFileProperties;
267                         if (!!type) {
268                             startFileProperties.type = *type;
269                         }
270                         if (!!encoding) {
271                             startFileProperties.encoding = *encoding;
272                         }
273                         startFileData.propertiesForLocales[*i] =
274                             startFileProperties;
275                     }
276                 }
277             }
278         }
279
280         m_installContext.widgetConfig.localizationData.startFiles.push_back(
281             startFileData);
282     }
283 }
284
285 void TaskWidgetConfig::ProcessLocalizedIcons()
286 {
287     using namespace WrtDB;
288     ProcessIcon(ConfigParserData::Icon(L"icon.svg"));
289     ProcessIcon(ConfigParserData::Icon(L"icon.ico"));
290     ProcessIcon(ConfigParserData::Icon(L"icon.png"));
291     ProcessIcon(ConfigParserData::Icon(L"icon.gif"));
292     ProcessIcon(ConfigParserData::Icon(L"icon.jpg"));
293
294     FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList)
295     {
296         ProcessIcon(*i);
297     }
298 }
299
300 void TaskWidgetConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon)
301 {
302     LogInfo("enter");
303     bool isAnyIconValid = false;
304     //In case a default filename is passed as custom filename in config.xml, we
305     //need to keep a set of already processed filenames to avoid icon duplication
306     //in database.
307
308     using namespace WrtDB;
309
310     if (m_processedIconSet.count(icon.src) > 0) {
311         return;
312     }
313     m_processedIconSet.insert(icon.src);
314
315     LocaleSet localesAvailableForIcon;
316
317     FOREACH(i, m_localeFolders)
318     {
319         DPL::String pathPrefix = *i;
320         if (!pathPrefix.empty()) {
321             pathPrefix = L"locales/" + pathPrefix + L"/";
322         }
323
324         DPL::String relativePath = pathPrefix + icon.src;
325         DPL::String absolutePath = DPL::FromUTF8String(
326                 m_installContext.locations->getConfigurationDir()) + L"/" + relativePath;
327
328         if (FileUtils::FileExists(absolutePath)) {
329             DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath);
330
331             if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) {
332                 isAnyIconValid = true;
333                 localesAvailableForIcon.insert(*i);
334                 LogInfo("Icon absolutePath :" << absolutePath <<
335                         ", assigned locale :" << *i << ", type: " << type);
336             }
337         }
338     }
339
340     if(isAnyIconValid)
341     {
342         WidgetRegisterInfo::LocalizedIcon localizedIcon(icon,
343                                                         localesAvailableForIcon);
344         m_installContext.widgetConfig.localizationData.icons.push_back(
345             localizedIcon);
346     }
347 }
348
349 void TaskWidgetConfig::StepCancelWidgetInstallationAfterVerifyFeatures()
350 {
351     LogDebug("StepCancelWidgetInstallationAfterVerifyFeatures");
352     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
353         m_installCancel = WRT_POPUP_BUTTON;
354         destroyPopup();
355         ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Widget not allowed");
356     }
357 }
358
359 void TaskWidgetConfig::StepCancelWidgetInstallation()
360 {
361     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
362         m_installCancel = WRT_POPUP_BUTTON;
363         destroyPopup();
364         ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
365     }
366 }
367
368 void TaskWidgetConfig::StepCancelWidgetInstallationAfterMinVersion()
369 {
370     if (InfoPopupButton::WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
371         m_installCancel = WRT_POPUP_BUTTON;
372         destroyPopup();
373         ThrowMsg(Exceptions::NotAllowed, "WRT version incompatible.");
374     }
375 }
376
377 void TaskWidgetConfig::createInstallPopup(PopupType type, const std::string &label)
378 {
379     m_installContext.job->Pause();
380     if (m_popup)
381         destroyPopup();
382
383     bool ret = createPopup();
384     if (ret)
385     {
386         loadPopup( type, label);
387         showPopup();
388     }
389 }
390
391 void TaskWidgetConfig::StepDeletePopupWin()
392 {
393     destroyPopup();
394 }
395
396 void TaskWidgetConfig::StepShowWidgetInfo()
397 {
398     if (!m_popupData.widgetInfo.empty()) {
399             std::string label = DPL::ToUTF8String(m_popupData.widgetInfo);
400             createInstallPopup(PopupType::WIDGET_FEATURE_INFO, label);
401         m_installContext.job->UpdateProgress(
402             InstallerContext::INSTALL_WIDGET_CONFIG2,
403             "Show Widget Info Finished");
404     }
405 }
406
407 void TaskWidgetConfig::StepCheckMinVersionInfo()
408 {
409     if (!isMinVersionCompatible(
410                 m_installContext.widgetConfig.type.appType,
411                 m_installContext.widgetConfig.minVersion)) {
412         std::string label = WIDGET_NOT_COMPATIBLE + QUESTION;
413         createInstallPopup(PopupType::WIDGET_MIN_VERSION, label);
414     }
415
416     m_installContext.job->UpdateProgress(
417             InstallerContext::INSTALL_WIDGET_CONFIG2,
418             "Check MinVersion Finished");
419 }
420
421 void TaskWidgetConfig::StepVerifyFeatures()
422 {
423     using namespace WrtDB;
424     ConfigParserData &data = m_installContext.widgetConfig.configInfo;
425     ConfigParserData::FeaturesList list = data.featuresList;
426     ConfigParserData::FeaturesList newList;
427
428     //in case of tests, this variable is unused
429     std::string featureInfo;
430     FOREACH(it, list)
431     {
432         // check feature vender for permission
433         // WAC, TIZEN WebApp cannot use other feature
434
435         if (!isFeatureAllowed(m_installContext.widgetConfig.type.appType,
436                               it->name))
437         {
438             LogInfo("This application type not allowed to use this feature");
439             ThrowMsg(
440                 Exceptions::WidgetConfigFileInvalid,
441                 "This app type [" <<
442                 m_installContext.widgetConfig.type.getApptypeToString() <<
443                 "] cannot be allowed to use [" <<
444                 DPL::ToUTF8String(it->name) + "] feature");
445         }
446         if (!WrtDB::FeatureDAOReadOnly::isFeatureInstalled(
447                 DPL::ToUTF8String(it->name))) {
448             LogWarning("Feature not found. Checking if required :[" <<
449                        DPL::ToUTF8String(it->name) << "]");
450
451             if (it->required) {
452                 /**
453                  * WL-3210 The WRT MUST inform the user if a widget cannot be
454                  * installed because one or more required features are not
455                  * supported.
456                  */
457                 std::ostringstream os;
458                 os << "Widget cannot be installed, required feature is missing:["
459                     << DPL::ToUTF8String(it->name) << "]";
460                 if (!GlobalSettings::TestModeEnabled() && !isTizenWebApp()) {
461                     std::string label = os.str();
462                     createInstallPopup(PopupType::WIDGET_WRONG_FEATURE_INFO, label);
463                 }
464                 ThrowMsg(Exceptions::WidgetConfigFileInvalid, os.str());
465             }
466         } else {
467             newList.insert(*it);
468             featureInfo += DPL::ToUTF8String(it->name);
469             featureInfo += DPL::ToUTF8String(BR);
470         }
471     }
472     data.featuresList = newList;
473     if (!featureInfo.empty()) {
474         m_popupData.addWidgetInfo(DPL::FromUTF8String(featureInfo));
475     }
476
477     m_installContext.job->UpdateProgress(
478         InstallerContext::INSTALL_WIDGET_CONFIG2,
479         "Widget Config step2 Finished");
480 }
481
482 void TaskWidgetConfig::setApplicationType()
483 {
484     using namespace WrtDB;
485     WidgetRegisterInfo* widgetInfo = &(m_installContext.widgetConfig);
486     ConfigParserData* configInfo = &(widgetInfo->configInfo);
487
488     FOREACH(iterator, configInfo->nameSpaces) {
489         LogInfo("namespace = [" << *iterator << "]");
490         AppType currentAppType = APP_TYPE_UNKNOWN;
491
492         if (*iterator == ConfigurationNamespace::W3CWidgetNamespaceName) {
493             continue;
494         } else if (
495             *iterator ==
496             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement ||
497             *iterator ==
498             ConfigurationNamespace::WacWidgetNamespaceName)
499         {
500             currentAppType = APP_TYPE_WAC20;
501         } else if (*iterator == ConfigurationNamespace::TizenWebAppNamespaceName) {
502             currentAppType = APP_TYPE_TIZENWEBAPP;
503         }
504
505         if (widgetInfo->type == APP_TYPE_UNKNOWN) {
506             widgetInfo->type = currentAppType;
507         } else if (widgetInfo->type == currentAppType) {
508             continue;
509         } else {
510             ThrowMsg(Exceptions::WidgetConfigFileInvalid,
511                      "Config.xml has more than one namespace");
512         }
513     }
514
515     // If there is no define, type set to WAC 2.0
516     if (widgetInfo->type == APP_TYPE_UNKNOWN) {
517         widgetInfo->type = APP_TYPE_WAC20;
518     }
519
520     LogInfo("type = [" << widgetInfo->type.getApptypeToString() << "]");
521 }
522
523 bool TaskWidgetConfig::isFeatureAllowed(WrtDB::AppType appType,
524                                         DPL::String featureName)
525 {
526     using namespace WrtDB;
527     LogInfo("AppType = [" <<
528             WidgetType(appType).getApptypeToString() << "]");
529     LogInfo("FetureName = [" << featureName << "]");
530
531     AppType featureType = APP_TYPE_UNKNOWN;
532     const char* feature = DPL::ToUTF8String(featureName).c_str();
533     // check prefix of  feature name
534     if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) {
535         // Tizen WebApp feature
536         featureType = APP_TYPE_TIZENWEBAPP;
537     } else if (strstr(feature, PluginsPrefix::WACPluginsPrefix) == feature) {
538         // WAC 2.0 feature
539         featureType = APP_TYPE_WAC20;
540     } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) {
541         // W3C standard feature
542         // Both WAC and TIZEN WebApp are possible to use W3C plugins
543         return true;
544     } else {
545         // unknown feature
546         // unknown feature will be checked next step
547         return true;
548     }
549
550     if (appType == featureType) {
551         return true;
552     }
553     return false;
554 }
555
556 bool TaskWidgetConfig::parseVersionString(const std::string &version,
557         long &majorVersion, long &minorVersion, long &microVersion) const
558 {
559     std::istringstream inputString(version);
560     inputString >> majorVersion;
561     if (inputString.bad() || inputString.fail()) {
562         LogWarning("Invalid minVersion format.");
563         return false;
564     }
565     inputString.get(); // skip period
566     inputString >> minorVersion;
567     if (inputString.bad() || inputString.fail()) {
568         LogWarning("Invalid minVersion format");
569         return false;
570     } else {
571         inputString.get(); // skip period
572         if (inputString.bad() || inputString.fail()) {
573             inputString >> microVersion;
574         }
575     }
576     return true;
577 }
578
579 bool TaskWidgetConfig::isMinVersionCompatible(WrtDB::AppType appType,
580         const DPL::OptionalString &widgetVersion) const
581 {
582     if (widgetVersion.IsNull() || (*widgetVersion).empty())
583     {
584         LogWarning("minVersion attribute is empty. WRT assumes platform "
585                 "supports this widget.");
586         return true;
587     }
588
589     //Parse widget version
590     long majorWidget = 0, minorWidget = 0, microWidget = 0;
591     if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget,
592             minorWidget, microWidget)) {
593         LogWarning("Invalid format of widget version string.");
594         return true;
595     }
596
597     //Parse supported version
598     long majorSupported = 0, minorSupported = 0, microSupported = 0;
599     std::string version;
600     if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
601         version = WrtDB::GlobalConfig::GetTizenVersion();
602     } else if (appType == WrtDB::AppType::APP_TYPE_WAC20) {
603         version = WrtDB::GlobalConfig::GetWACVersion();
604     } else {
605         LogWarning("Invaild AppType");
606         return false;
607     }
608
609     if (!parseVersionString(version,
610                 majorSupported, minorSupported, microSupported)) {
611         LogWarning("Invalid format of WAC version string.");
612         return true;
613     }
614
615     if (majorWidget > majorSupported ||
616             minorWidget > minorSupported ||
617             microWidget > microSupported) {
618         LogInfo("Platform doesn't support this widget.");
619         return false;
620     }
621     return true;
622 }
623
624 bool TaskWidgetConfig::isTizenWebApp() const
625 {
626     bool ret = FALSE;
627     if (m_installContext.widgetConfig.type.appType
628             == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
629         ret = TRUE;
630
631     return ret;
632 }
633
634 bool TaskWidgetConfig::parseConfigurationFileBrowser(WrtDB::ConfigParserData& configInfo,
635                                     const std::string& _currentPath, int* pErrCode)
636 {
637     ParserRunner parser;
638     Try
639     {
640         parser.Parse(_currentPath, ElementParserPtr(new
641                                                   RootParser<
642                                                       WidgetParser>(
643                                                       configInfo,
644                                                       DPL::FromUTF32String(
645                                                           L"widget"))));
646     }
647     Catch(ElementParser::Exception::Base)
648     {
649         LogDebug("Invalid widget configuration file!");
650         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
651         return false;
652     }
653     return true;
654 }
655
656 bool TaskWidgetConfig::parseConfigurationFileWidget(WrtDB::ConfigParserData& configInfo,
657                                     const std::string& _currentPath, int* pErrCode)
658 {
659     ParserRunner parser;
660
661     //TODO: rewrite this madness
662     char cfgAbsPath[MAX_WIDGET_PATH_SIZE + 1] = { 0 };
663     DIR* dir = NULL;
664     struct dirent* ptr = NULL;
665
666     dir = opendir(_currentPath.c_str());
667     if (dir == NULL) {
668         *pErrCode = WRT_ERR_UNKNOWN;
669         return false;
670     }
671     bool has_config_xml = false;
672     errno = 0;
673     while ((ptr = readdir(dir)) != NULL) { //Find configuration file, based on its name
674         if (ptr->d_type == DT_REG) {
675             if (!strcmp(ptr->d_name, WRT_WIDGET_CONFIG_FILE_NAME)) {
676                 _WrtUtilSetAbsolutePath(cfgAbsPath,
677                                         _currentPath.c_str(), ptr->d_name);
678                 //Parse widget configuration file
679                 LogDebug("Found config: " << cfgAbsPath);
680
681                 Try
682                 {
683                     parser.Parse(cfgAbsPath, ElementParserPtr(new
684                                                               RootParser<
685                                                                   WidgetParser>(
686                                                                   configInfo,
687                                                                   DPL
688                                                                       ::
689                                                                       FromUTF32String(
690                                                                       L"widget"))));
691                 }
692                 Catch(ElementParser::Exception::Base)
693                 {
694                     LogDebug("Invalid widget configuration file!");
695                     //                    _rethrown_exception.Dump();
696                     *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
697                     closedir(dir);
698                     return false;
699                 }
700
701                 has_config_xml = true;
702                 break;
703             }
704         }
705     }
706     closedir(dir);
707
708     //We must have config.xml so leaveing if we doesn't
709     if (!has_config_xml) {
710         LogDebug("Invalid archive");
711         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
712         return false;
713     }
714     return true;
715 }
716
717 bool TaskWidgetConfig::locateAndParseConfigurationFile(
718         const std::string& _currentPath,
719         WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
720         const std::string& baseFolder,
721         int* pErrCode)
722 {
723     using namespace WrtDB;
724
725     if (!pErrCode) {
726         return false;
727     }
728
729     ConfigParserData& configInfo = pWidgetConfigInfo.configInfo;
730
731     // check if this installation from browser, or not.
732     size_t pos = _currentPath.rfind("/");
733     std::ostringstream infoPath;
734     infoPath << _currentPath.substr(pos+1);
735
736     std::string language = "";
737
738     if (infoPath.str() != WRT_WIDGET_CONFIG_FILE_NAME) {
739         if (_currentPath.empty() || baseFolder.empty()) {
740             *pErrCode = WRT_ERR_INVALID_ARG;
741             return false;
742         }
743         // in case of general installation using wgt archive
744         if(!parseConfigurationFileWidget(configInfo, _currentPath, pErrCode))
745         {
746             return false;
747         }
748     } else {
749         // in case of browser installation
750         if(!parseConfigurationFileBrowser(configInfo, _currentPath, pErrCode))
751         {
752             return false;
753         }
754     }
755
756     char *tmp_language;
757     if (!_WrtUtilStringToLower(baseFolder.c_str(), &tmp_language)) {
758         *pErrCode = WRT_ERR_UNKNOWN;
759         return false;
760     }
761
762     if (!tmp_language) {
763         *pErrCode = WRT_ERR_UNKNOWN;
764         return false;
765     }
766     language = tmp_language;
767     free(tmp_language);
768
769     if(!fillWidgetConfig(pWidgetConfigInfo, configInfo))
770     {
771         *pErrCode = WRT_WM_ERR_INVALID_ARCHIVE;
772         return false;
773     }
774     return true;
775 }
776
777 bool TaskWidgetConfig::fillWidgetConfig(WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
778                                         WrtDB::ConfigParserData& configInfo)
779 {
780     if (!!configInfo.widget_id) {
781         if (!pWidgetConfigInfo.guid) {
782             pWidgetConfigInfo.guid = configInfo.widget_id;
783         } else {
784             if (pWidgetConfigInfo.guid != configInfo.widget_id) {
785                 LogDebug("Invalid archive");
786                 return false;
787             }
788         }
789     }
790     if (!!configInfo.tizenId) {
791         if (!pWidgetConfigInfo.pkgname) {
792             pWidgetConfigInfo.pkgname = configInfo.tizenId;
793         } else {
794             if (pWidgetConfigInfo.pkgname != configInfo.tizenId) {
795                 LogDebug("Invalid archive - Tizen ID not same error");
796                 return false;
797             }
798         }
799     }
800     if (!!configInfo.version) {
801         if (!pWidgetConfigInfo.version) {
802             pWidgetConfigInfo.version = configInfo.version;
803         } else {
804             if (pWidgetConfigInfo.version != configInfo.version) {
805                 LogDebug("Invalid archive");
806                 return false;
807             }
808         }
809     }
810     if (!!configInfo.minVersionRequired) {
811         pWidgetConfigInfo.minVersion = configInfo.minVersionRequired;
812     } else if (!!configInfo.tizenMinVersionRequired) {
813         pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired;
814     }
815     return true;
816 }
817
818 void TaskWidgetConfig::processFile(const std::string& path,
819         WrtDB::WidgetRegisterInfo &widgetConfiguration)
820 {
821     int pErrCode;
822
823     if (!locateAndParseConfigurationFile(path, widgetConfiguration,
824                                          DEFAULT_LANGUAGE, &pErrCode)) {
825         LogWarning("Widget archive: Failed while parsing config file");
826         ThrowMsg(Exception::ConfigParseFailed, path);
827     }
828 }
829
830 } //namespace WidgetInstall
831 } //namespace Jobs