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