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