Icon extension for package manager and manifest fix
[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 <map>
24 #include <sstream>
25 #include <string>
26 #include <sys/stat.h>
27 #include <dirent.h>
28
29 #include <dpl/errno_string.h>
30 #include <dpl/foreach.h>
31 #include <dpl/localization/w3c_file_localization.h>
32 #include <dpl/singleton_impl.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-ro/config_parser_data.h>
38 #include <dpl/wrt-dao-rw/feature_dao.h>
39
40 #include <libiriwrapper.h>
41 #include <parser_runner.h>
42 #include <root_parser.h>
43
44 #include <widget_install/job_widget_install.h>
45 #include <widget_install/task_widget_config.h>
46 #include <widget_install/widget_install_context.h>
47 #include <widget_install/widget_install_errors.h>
48 #include <widget_parser.h>
49 #include <web_provider_plugin_info.h>
50 #include <web_provider_livebox_info.h>
51 #include <manifest.h>
52
53 namespace { // anonymous
54 const DPL::String BR = DPL::FromUTF8String("<br>");
55 const std::string WIDGET_NOT_COMPATIBLE = "This widget is "
56                                           "not compatible with WRT.<br><br>";
57 const std::string QUESTION = "Do you want to install it anyway?";
58
59 const char *const DEFAULT_LANGUAGE = "default";
60
61 const char *const WRT_WIDGET_CONFIG_FILE_NAME = "config.xml";
62
63 const std::string WINDGET_INSTALL_NETWORK_ACCESS = "network access";
64
65 const char WRT_WIDGETS_XML_SCHEMA[] = "/usr/etc/wrt-installer/widgets.xsd";
66 }
67
68 namespace Jobs {
69 namespace WidgetInstall {
70
71 TaskWidgetConfig::TaskWidgetConfig(InstallerContext& installContext) :
72     DPL::TaskDecl<TaskWidgetConfig>(this),
73     m_installContext(installContext)
74 {
75     AddStep(&TaskWidgetConfig::StartStep);
76     AddStep(&TaskWidgetConfig::StepProcessConfigurationFile);
77     AddStep(&TaskWidgetConfig::ReadLocaleFolders);
78     AddStep(&TaskWidgetConfig::ProcessLocalizedStartFiles);
79     AddStep(&TaskWidgetConfig::ProcessBackgroundPageFile);
80     AddStep(&TaskWidgetConfig::ProcessLocalizedIcons);
81     AddStep(&TaskWidgetConfig::ProcessWidgetInstalledPath);
82     AddStep(&TaskWidgetConfig::ProcessAppControlInfo);
83     AddStep(&TaskWidgetConfig::ProcessSecurityModel);
84     AddStep(&TaskWidgetConfig::StepVerifyFeatures);
85     AddStep(&TaskWidgetConfig::StepCheckMinVersionInfo);
86     AddStep(&TaskWidgetConfig::EndStep);
87 }
88
89 void TaskWidgetConfig::StepProcessConfigurationFile()
90 {
91     Try
92     {
93         std::string path = m_installContext.locations->getConfigurationDir();
94         LogDebug("path: " << path);
95
96         processFile(path, m_installContext.widgetConfig);
97     }
98     Catch(Exception::ConfigParseFailed)
99     {
100         LogError("Parsing failed.");
101         ReThrow(Exceptions::WidgetConfigFileInvalid);
102     }
103
104     m_installContext.job->UpdateProgress(
105         InstallerContext::INSTALL_WIDGET_CONFIG1,
106         "Parse elements of configuration file and save them");
107 }
108
109 void TaskWidgetConfig::ReadLocaleFolders()
110 {
111     LogDebug("Reading locale");
112     //Adding default locale
113     m_localeFolders.insert(L"");
114
115     std::string localePath =
116         m_installContext.locations->getConfigurationDir() + "/locales";
117     DIR* localeDir = opendir(localePath.c_str());
118     if (!localeDir) {
119         LogDebug("No /locales directory in the widget package.");
120         return;
121     }
122
123     struct stat statStruct;
124     struct dirent dirent;
125     struct dirent *result;
126     int return_code;
127     errno = 0;
128     for (return_code = readdir_r(localeDir, &dirent, &result);
129             result != NULL && return_code == 0;
130             return_code = readdir_r(localeDir, &dirent, &result))
131     {
132         DPL::String dirName = DPL::FromUTF8String(dirent.d_name);
133         std::string absoluteDirName = localePath + "/";
134         absoluteDirName += dirent.d_name;
135
136         if (stat(absoluteDirName.c_str(), &statStruct) != 0) {
137             LogError("stat() failed with " << DPL::GetErrnoString());
138             continue;
139         }
140
141         if (S_ISDIR(statStruct.st_mode)) {
142             //Yes, we ignore current, parent & hidden directories
143             if (dirName[0] != L'.') {
144                 LogDebug("Adding locale directory \"" << dirName << "\"");
145                 m_localeFolders.insert(dirName);
146             }
147         }
148     }
149
150     if (return_code != 0 || errno != 0) {
151         LogError("readdir_r() failed with " << DPL::GetErrnoString());
152     }
153
154     if (-1 == TEMP_FAILURE_RETRY(closedir(localeDir))) {
155         LogError("Failed to close dir: " << localePath << " with error: "
156                                          << DPL::GetErrnoString());
157     }
158 }
159
160 void TaskWidgetConfig::ProcessLocalizedStartFiles()
161 {
162     typedef DPL::String S;
163     ProcessStartFile(
164         m_installContext.widgetConfig.configInfo.startFile,
165         m_installContext.widgetConfig.configInfo.
166             startFileContentType,
167         m_installContext.widgetConfig.configInfo.startFileEncoding,
168         true);
169     ProcessStartFile(S(L"index.htm"), S(L"text/html"));
170     ProcessStartFile(S(L"index.html"), S(L"text/html"));
171     ProcessStartFile(S(L"index.svg"), S(L"image/svg+xml"));
172     ProcessStartFile(S(L"index.xhtml"), S(L"application/xhtml+xml"));
173     ProcessStartFile(S(L"index.xht"), S(L"application/xhtml+xml"));
174     // TODO: we need better check if in current locales widget is valid
175     FOREACH(it, m_installContext.widgetConfig.localizationData.startFiles) {
176         if (it->propertiesForLocales.size() > 0) {
177             return;
178         }
179     }
180     ThrowMsg(Exceptions::InvalidStartFile,
181              "The Widget has no valid start file");
182 }
183
184 void TaskWidgetConfig::ProcessStartFile(const DPL::OptionalString& path,
185                                         const DPL::OptionalString& type,
186                                         const DPL::OptionalString& encoding,
187                                         bool typeForcedInConfig)
188 {
189     using namespace WrtDB;
190
191     if (!!path) {
192         WidgetRegisterInfo::LocalizedStartFile startFileData;
193         startFileData.path = *path;
194
195         FOREACH(i, m_localeFolders) {
196             DPL::String pathPrefix = *i;
197             if (!pathPrefix.empty()) {
198                 pathPrefix = L"locales/" + pathPrefix + L"/";
199             }
200
201             DPL::String relativePath = pathPrefix + *path;
202             DPL::String absolutePath = DPL::FromUTF8String(
203                     m_installContext.locations->getConfigurationDir()) + L"/" +
204                 relativePath;
205
206             // get property data from packaged app
207             if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
208                 WidgetRegisterInfo::StartFileProperties startFileProperties;
209                 if (!!type) {
210                     startFileProperties.type = *type;
211                 } else {
212                     startFileProperties.type =
213                         MimeTypeUtils::identifyFileMimeType(absolutePath);
214                 }
215
216                 //proceed only if MIME type is supported
217                 if (MimeTypeUtils::isMimeTypeSupportedForStartFile(
218                         startFileProperties.type))
219                 {
220                     if (!!encoding) {
221                         startFileProperties.encoding = *encoding;
222                     } else {
223                         MimeTypeUtils::MimeAttributes attributes =
224                             MimeTypeUtils::getMimeAttributes(
225                                 startFileProperties.type);
226                         if (attributes.count(L"charset") > 0) {
227                             startFileProperties.encoding =
228                                 attributes[L"charset"];
229                         } else {
230                             startFileProperties.encoding = L"UTF-8";
231                         }
232                     }
233
234                     startFileData.propertiesForLocales[*i] =
235                         startFileProperties;
236                 } else {
237                     //9.1.16.5.content.8
238                     //(there seems to be no similar requirement in .6,
239                     //so let's throw only when mime type is
240                     // provided explcitly in config.xml)
241                     if (typeForcedInConfig) {
242                         ThrowMsg(Exceptions::WidgetConfigFileInvalid,
243                                  "Unsupported MIME type for start file.");
244                     }
245                 }
246             } else {
247                 // set property data for hosted start url
248                 // Hosted start url only support TIZEN WebApp
249                 if (m_installContext.widgetConfig.webAppType ==
250                     APP_TYPE_TIZENWEBAPP)
251                 {
252                     std::string startPath = DPL::ToUTF8String(
253                             startFileData.path);
254
255                     if (strstr(startPath.c_str(),
256                                "http") == startPath.c_str())
257                     {
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     FOREACH(i, m_installContext.widgetConfig.configInfo.iconsList)
297     {
298         ProcessIcon(*i);
299     }
300     ProcessIcon(ConfigParserData::Icon(L"icon.svg"));
301     ProcessIcon(ConfigParserData::Icon(L"icon.ico"));
302     ProcessIcon(ConfigParserData::Icon(L"icon.png"));
303     ProcessIcon(ConfigParserData::Icon(L"icon.gif"));
304     ProcessIcon(ConfigParserData::Icon(L"icon.jpg"));
305 }
306
307 void TaskWidgetConfig::ProcessIcon(const WrtDB::ConfigParserData::Icon& icon)
308 {
309     LogDebug("enter");
310     bool isAnyIconValid = false;
311     //In case a default filename is passed as custom filename in config.xml, we
312     //need to keep a set of already processed filenames to avoid icon
313     // 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"/" +
335             relativePath;
336
337         if (WrtUtilFileExists(DPL::ToUTF8String(absolutePath))) {
338             DPL::String type = MimeTypeUtils::identifyFileMimeType(absolutePath);
339
340             if (MimeTypeUtils::isMimeTypeSupportedForIcon(type)) {
341                 isAnyIconValid = true;
342                 localesAvailableForIcon.insert(*i);
343                 LogDebug("Icon absolutePath :" << absolutePath <<
344                         ", assigned locale :" << *i << ", type: " << type);
345             }
346         }
347     }
348
349     if (isAnyIconValid) {
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(
362             m_installContext.locations->getPackageInstallationDir());
363 }
364
365 void TaskWidgetConfig::ProcessAppControlInfo()
366 {
367     LogDebug("ProcessAppControlInfo");
368     using namespace WrtDB;
369
370     // In case of dispostion is inline, set the seperate execute
371     int index = 1;
372     // 0 index is reserved by default execute
373     FOREACH(it, m_installContext.widgetConfig.configInfo.appControlList) {
374         if (it->m_disposition ==
375             ConfigParserData::AppControlInfo::Disposition::INLINE)
376         {
377             it->m_index = index++;
378         } else {
379             it->m_index = 0;
380         }
381     }
382 }
383
384 void TaskWidgetConfig::ProcessSecurityModel()
385 {
386     // 0104.  If the "required_version" specified in the Web Application's
387     // configuration is 2.2 or higher and if the Web Application's
388     // configuration is "CSP-compatible configuration", then the WRT MUST be
389     // set to "CSP-based security mode". Otherwise, the WRT MUST be set to
390     // "WARP-based security mode".
391     // 0105.  A Web Application configuration is "CSP-compatible configuration"
392     // if the configuration includes one or more of
393     // <tizen:content-security-policy> /
394     // <tizen:content-security-policy-report-only> /
395     // <tizen:allow-navigation> elements.
396
397     bool isSecurityModelV1 = false;
398     bool isSecurityModelV2 = false;
399     WrtDB::ConfigParserData &data = m_installContext.widgetConfig.configInfo;
400
401     if (!data.cspPolicy.IsNull() ||
402         !data.cspPolicyReportOnly.IsNull() ||
403         !data.allowNavigationInfoList.empty())
404     {
405         data.accessInfoSet.clear();
406     }
407
408     // WARP is V1
409     if (!data.accessInfoSet.empty()) {
410         isSecurityModelV1 = true;
411     }
412
413     // CSP & allow-navigation is V2
414     if (!data.cspPolicy.IsNull() ||
415         !data.cspPolicyReportOnly.IsNull() ||
416         !data.allowNavigationInfoList.empty())
417     {
418         isSecurityModelV2 = true;
419     }
420
421     if (isSecurityModelV1 && isSecurityModelV2) {
422         LogError("Security model is conflict");
423         ThrowMsg(Exceptions::NotAllowed, "Security model is conflict");
424     } else if (isSecurityModelV1) {
425         data.securityModelVersion =
426             WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1;
427     } else if (isSecurityModelV2) {
428         data.securityModelVersion =
429             WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V2;
430     } else {
431         data.securityModelVersion =
432             WrtDB::ConfigParserData::SecurityModelVersion::SECURITY_MODEL_V1;
433     }
434
435     m_installContext.job->UpdateProgress(
436         InstallerContext::INSTALL_WIDGET_CONFIG2,
437         "Finished process security model");
438 }
439
440 void TaskWidgetConfig::StepCheckMinVersionInfo()
441 {
442     if (!isMinVersionCompatible(
443             m_installContext.widgetConfig.webAppType.appType,
444             m_installContext.widgetConfig.minVersion))
445     {
446         LogError(
447             "Platform version lower than required -> cancelling installation");
448         ThrowMsg(Exceptions::NotAllowed,
449                  "Platform version does not meet requirements");
450     }
451
452     m_installContext.job->UpdateProgress(
453         InstallerContext::INSTALL_WIDGET_CONFIG2,
454         "Check MinVersion Finished");
455 }
456
457 void TaskWidgetConfig::StepVerifyFeatures()
458 {
459     using namespace WrtDB;
460     ConfigParserData &data = m_installContext.widgetConfig.configInfo;
461     ConfigParserData::FeaturesList list = data.featuresList;
462     ConfigParserData::FeaturesList newList;
463
464     //in case of tests, this variable is unused
465     std::string featureInfo;
466     FOREACH(it, list)
467     {
468         // check feature vender for permission
469         // WAC, TIZEN WebApp cannot use other feature
470
471         if (!isFeatureAllowed(m_installContext.widgetConfig.webAppType.appType,
472                               it->name))
473         {
474             LogDebug("This application type not allowed to use this feature");
475             ThrowMsg(
476                 Exceptions::WidgetConfigFileInvalid,
477                 "This app type [" <<
478                 m_installContext.widgetConfig.webAppType.getApptypeToString()
479                                   <<
480                 "] cannot be allowed to use [" <<
481                 DPL::ToUTF8String(it->name) + "] feature");
482         } else {
483             newList.insert(*it);
484             featureInfo += DPL::ToUTF8String(it->name);
485             featureInfo += DPL::ToUTF8String(BR);
486         }
487     }
488     if (!data.accessInfoSet.empty()) {
489         featureInfo += WINDGET_INSTALL_NETWORK_ACCESS;
490         featureInfo += DPL::ToUTF8String(BR);
491     }
492     data.featuresList = newList;
493
494     m_installContext.job->UpdateProgress(
495         InstallerContext::INSTALL_WIDGET_CONFIG2,
496         "Widget Config step2 Finished");
497 }
498
499 void TaskWidgetConfig::StepVerifyLivebox()
500 {
501     using namespace WrtDB;
502     ConfigParserData &data = m_installContext.widgetConfig.configInfo;
503     ConfigParserData::LiveboxList liveBoxList = data.m_livebox;
504
505     if (liveBoxList.size() <= 0) {
506         return;
507     }
508
509     FOREACH (it, liveBoxList) {
510         std::string boxType;
511
512         if ((**it).m_type.empty()) {
513             boxType = web_provider_livebox_get_default_type();
514         } else {
515             boxType = DPL::ToUTF8String((**it).m_type);
516         }
517
518         LogDebug("livebox type: " << boxType);
519
520         ConfigParserData::LiveboxInfo::BoxSizeList boxSizeList =
521             (**it).m_boxInfo.m_boxSize;
522         char** boxSize = static_cast<char**>(
523             malloc(sizeof(char*)* boxSizeList.size()));
524
525         int boxSizeCnt = 0;
526         FOREACH (m, boxSizeList) {
527             boxSize[boxSizeCnt++] = strdup(DPL::ToUTF8String((*m).m_size).c_str());
528         }
529
530         bool chkSize = web_provider_plugin_check_supported_size(
531             boxType.c_str(), boxSize, boxSizeCnt);
532
533         for(int i = 0; i < boxSizeCnt; i++) {
534             free(boxSize[i]);
535         }
536         free(boxSize);
537
538         if(!chkSize) {
539             LogError("Invalid boxSize");
540             ThrowMsg(Exceptions::WidgetConfigFileInvalid, "Invalid boxSize");
541         }
542     }
543 }
544
545 bool TaskWidgetConfig::isFeatureAllowed(WrtDB::AppType appType,
546                                         DPL::String featureName)
547 {
548     using namespace WrtDB;
549     LogDebug("AppType = [" <<
550             WidgetType(appType).getApptypeToString() << "]");
551     LogDebug("FetureName = [" << featureName << "]");
552
553     AppType featureType = APP_TYPE_UNKNOWN;
554     std::string featureStr = DPL::ToUTF8String(featureName);
555     const char* feature = featureStr.c_str();
556
557     // check prefix of  feature name
558     if (strstr(feature, PluginsPrefix::TIZENPluginsPrefix) == feature) {
559         // Tizen WebApp feature
560         featureType = APP_TYPE_TIZENWEBAPP;
561     } else if (strstr(feature, PluginsPrefix::W3CPluginsPrefix) == feature) {
562         // W3C standard feature
563         // Both WAC and TIZEN WebApp are possible to use W3C plugins
564         return true;
565     } else {
566         // unknown feature
567         // unknown feature will be checked next step
568         return true;
569     }
570
571     if (appType == featureType) {
572         return true;
573     }
574     return false;
575 }
576
577 bool TaskWidgetConfig::parseVersionString(const std::string &version,
578                                           long &majorVersion,
579                                           long &minorVersion,
580                                           long &microVersion) const
581 {
582     std::istringstream inputString(version);
583     inputString >> majorVersion;
584     if (inputString.bad() || inputString.fail()) {
585         LogWarning("Invalid minVersion format.");
586         return false;
587     }
588     inputString.get(); // skip period
589     inputString >> minorVersion;
590     if (inputString.bad() || inputString.fail()) {
591         LogWarning("Invalid minVersion format");
592         return false;
593     } else {
594         inputString.get(); // skip period
595         if (inputString.bad() || inputString.fail()) {
596             inputString >> microVersion;
597         }
598     }
599     return true;
600 }
601
602 bool TaskWidgetConfig::isMinVersionCompatible(
603     WrtDB::AppType appType,
604     const DPL::OptionalString &
605     widgetVersion) const
606 {
607     if (widgetVersion.IsNull() || (*widgetVersion).empty()) {
608         if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
609             return false;
610         } else {
611             LogWarning("minVersion attribute is empty. WRT assumes platform "
612                     "supports this widget.");
613             return true;
614         }
615     }
616
617     //Parse widget version
618     long majorWidget = 0, minorWidget = 0, microWidget = 0;
619     if (!parseVersionString(DPL::ToUTF8String(*widgetVersion), majorWidget,
620                             minorWidget, microWidget))
621     {
622         LogWarning("Invalid format of widget version string.");
623         return false;
624     }
625
626     //Parse supported version
627     long majorSupported = 0, minorSupported = 0, microSupported = 0;
628     std::string version;
629     if (appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) {
630         version = WrtDB::GlobalConfig::GetTizenVersion();
631     } else {
632         LogWarning("Invaild AppType");
633         return false;
634     }
635
636     if (!parseVersionString(version,
637                             majorSupported, minorSupported, microSupported))
638     {
639         LogWarning("Invalid format of platform version string.");
640         return true;
641     }
642
643     if (majorWidget > majorSupported ||
644         (majorWidget == majorSupported && minorWidget > minorSupported) ||
645         (majorWidget == majorSupported && minorWidget == minorSupported
646          && microWidget > microSupported))
647     {
648         LogDebug("Platform doesn't support this widget.");
649         return false;
650     }
651     return true;
652 }
653
654 bool TaskWidgetConfig::isTizenWebApp() const
655 {
656     bool ret = FALSE;
657     if (m_installContext.widgetConfig.webAppType.appType
658         == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
659     {
660         ret = TRUE;
661     }
662
663     return ret;
664 }
665
666 bool TaskWidgetConfig::parseConfigurationFileBrowser(
667     WrtDB::ConfigParserData& configInfo,
668     const std::string& _currentPath)
669 {
670     ParserRunner parser;
671     Try
672     {
673         parser.Parse(_currentPath, ElementParserPtr(new
674                                                     RootParser<
675                                                         WidgetParser>(
676                                                         configInfo,
677                                                         DPL::FromUTF32String(
678                                                             L"widget"))));
679     }
680     Catch(ElementParser::Exception::Base)
681     {
682         LogError("Invalid widget configuration file!");
683         return false;
684     }
685     return true;
686 }
687
688 bool TaskWidgetConfig::parseConfigurationFileWidget(
689     WrtDB::ConfigParserData& configInfo,
690     const std::string& _currentPath)
691 {
692     std::string configFilePath;
693     WrtUtilJoinPaths(configFilePath, _currentPath, WRT_WIDGET_CONFIG_FILE_NAME);
694     if (!WrtUtilFileExists(configFilePath))
695     {
696         LogError("Archive does not contain configuration file");
697         return false;
698     }
699
700     LogDebug("Configuration file: " << configFilePath);
701
702     Try
703     {
704         ParserRunner parser;
705 #ifdef SCHEMA_VALIDATION_ENABLED
706         if(!parser.Validate(configFilePath, WRT_WIDGETS_XML_SCHEMA))
707         {
708             LogError("Invalid configuration file - schema validation failed");
709             return false;
710         }
711 #endif
712         parser.Parse(configFilePath,
713                      ElementParserPtr(new RootParser<WidgetParser>(
714                                           configInfo,
715                                           DPL::FromUTF32String(L"widget"))));
716         return true;
717     }
718     Catch (ElementParser::Exception::Base)
719     {
720         LogError("Invalid configuration file!");
721         return false;
722     }
723 }
724
725 bool TaskWidgetConfig::locateAndParseConfigurationFile(
726     const std::string& _currentPath,
727     WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
728     const std::string& baseFolder)
729 {
730     using namespace WrtDB;
731
732     ConfigParserData& configInfo = pWidgetConfigInfo.configInfo;
733
734     // check if this installation from browser, or not.
735     size_t pos = _currentPath.rfind("/");
736     std::ostringstream infoPath;
737     infoPath << _currentPath.substr(pos + 1);
738
739     if (infoPath.str() != WRT_WIDGET_CONFIG_FILE_NAME) {
740         if (_currentPath.empty() || baseFolder.empty()) {
741             return false;
742         }
743         // in case of general installation using wgt archive
744         if (!parseConfigurationFileWidget(configInfo, _currentPath))
745         {
746             return false;
747         }
748     } else {
749         // in case of browser installation
750         if (!parseConfigurationFileBrowser(configInfo, _currentPath))
751         {
752             return false;
753         }
754     }
755
756     if (!fillWidgetConfig(pWidgetConfigInfo, configInfo)) {
757         return false;
758     }
759     return true;
760 }
761
762 bool TaskWidgetConfig::fillWidgetConfig(
763     WrtDB::WidgetRegisterInfo& pWidgetConfigInfo,
764     WrtDB::ConfigParserData& configInfo)
765 {
766     if (!!configInfo.widget_id) {
767         if (!pWidgetConfigInfo.guid) {
768             pWidgetConfigInfo.guid = configInfo.widget_id;
769         } else {
770             if (pWidgetConfigInfo.guid != configInfo.widget_id) {
771                 LogError("Invalid archive");
772                 return false;
773             }
774         }
775     }
776     if (!!configInfo.tizenAppId) {
777         if (DPL::ToUTF8String(pWidgetConfigInfo.tzAppid).compare(
778                 DPL::ToUTF8String(*configInfo.tizenAppId)) < 0)
779         {
780             LogError("Invalid archive - Tizen App ID not same error");
781             return false;
782         }
783     }
784     if (!!configInfo.tizenPkgId) {
785         if (pWidgetConfigInfo.tzPkgid != *configInfo.tizenPkgId) {
786             LogError("Invalid archive - Tizen Pkg ID not same error");
787             return false;
788         }
789     }
790     if (!!configInfo.version) {
791         if (!pWidgetConfigInfo.version) {
792             pWidgetConfigInfo.version = configInfo.version;
793         } else {
794             if (pWidgetConfigInfo.version != configInfo.version) {
795                 LogError("Invalid archive");
796                 return false;
797             }
798         }
799     }
800     if (!!configInfo.minVersionRequired) {
801         pWidgetConfigInfo.minVersion = configInfo.minVersionRequired;
802     } else if (!!configInfo.tizenMinVersionRequired) {
803         pWidgetConfigInfo.minVersion = configInfo.tizenMinVersionRequired;
804     }
805     return true;
806 }
807
808 void TaskWidgetConfig::processFile(
809     const std::string& path,
810     WrtDB::WidgetRegisterInfo &
811     widgetConfiguration)
812 {
813     if (!locateAndParseConfigurationFile(path, widgetConfiguration,
814                                          DEFAULT_LANGUAGE))
815     {
816         LogWarning("Widget archive: Failed while parsing config file");
817         ThrowMsg(Exception::ConfigParseFailed, path);
818     }
819 }
820
821 void TaskWidgetConfig::StartStep()
822 {
823     LogDebug("--------- <TaskWidgetConfig> : START ----------");
824 }
825
826 void TaskWidgetConfig::EndStep()
827 {
828     LogDebug("--------- <TaskWidgetConfig> : END ----------");
829 }
830 } //namespace WidgetInstall
831 } //namespace Jobs