Tizen 2.4.0 rev3 SDK Public Release
[framework/web/wrt-installer.git] / src / configuration_parser / widget_parser.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  * This file  have been implemented in compliance with  W3C WARP SPEC.
18  * but there are some patent issue between  W3C WARP SPEC and APPLE.
19  * so if you want to use this file, refer to the README file in root directory
20  */
21 /**
22  * @file        widget_parser.cpp
23  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
24  * @version     0.1
25  * @brief
26  */
27
28 #include <widget_parser.h>
29 #include "ignoring_parser.h"
30 #include "deny_all_parser.h"
31 #include <dpl/wrt-dao-ro/config_parser_data.h>
32 #include "libiriwrapper.h"
33 #include "wrt-commons/i18n-dao-ro/i18n_dao_read_only.h"
34 #include <dpl/utils/warp_iri.h>
35 #include <dpl/utils/mime_type_utils.h>
36 #include <language_subtag_rst_tree.h>
37 #include <algorithm>
38 #include <cerrno>
39 #include <climits>
40 #include <cmath>
41 #include <cstdlib>
42 #include <cstdio>
43 #include <functional>
44 #include <locale>
45 #include <memory>
46 #include <string>
47 #include <stdlib.h>
48 #include <boost/optional.hpp>
49
50 #include <dpl/log/log.h>
51 #include <dpl/foreach.h>
52 #include <dpl/platform.h>
53 #include <dpl/utils/warp_iri.h>
54 #include <dpl/utils/mime_type_utils.h>
55 #include <dpl/wrt-dao-ro/config_parser_data.h>
56 #include <iri.h>
57 #include <pcrecpp.h>
58
59 #include <deny_all_parser.h>
60 #include <ignoring_parser.h>
61 #include <dpl/log/secure_log.h>
62 #include <language_subtag_rst_tree.h>
63 #include <libiriwrapper.h>
64 #include <uuid/uuid.h>
65
66 using namespace WrtDB;
67
68 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
69 namespace {
70 const unsigned int MAX_ATTR_ELEMENT_LENGTH = 2048;
71 const unsigned int MAX_NAME_KEY_LENGTH = 80;
72 const unsigned int MAX_NAME_KEY_VALUE_LENGTH = 8192;
73 } // namespace anonymous
74 #endif // ELEMENT_ATTR_MAX_LENGTH
75
76 namespace{
77 const unsigned int MAX_APPLICATION_ID_LENGTH = 63;
78 }
79
80 namespace Unicode {
81 static const DPL::String UTF_LRE = L"\x0202a";
82 static const DPL::String UTF_LRO = L"\x0202d";
83 static const DPL::String UTF_RLE = L"\x0202b";
84 static const DPL::String UTF_RLO = L"\x0202e";
85 static const DPL::String UTF_PDF = L"\x0202c";
86
87 Direction ParseDirAttribute(const XmlAttribute& attribute)
88 {
89     Assert(L"dir" == attribute.name);
90     if (L"ltr" == attribute.value) {
91         return LRE;
92     } else if (L"rtl" == attribute.value) {
93         return RLE;
94     } else if (L"lro" == attribute.value) {
95         return LRO;
96     } else if (L"rlo" == attribute.value) {
97         return RLO;
98     } else {
99         _W("dir attribute has wrong value: %ls ", attribute.value.c_str());
100         return EMPTY;
101     }
102 }
103
104 void UpdateTextWithDirectionMark(Direction direction,
105                                  DPL::String* text)
106 {
107     Assert(text);
108     switch (direction) {
109     case RLO:
110         *text = UTF_RLO + *text + UTF_PDF;
111         break;
112     case RLE:
113         *text = UTF_RLE + *text + UTF_PDF;
114         break;
115     case LRE:
116         *text = UTF_LRE + *text + UTF_PDF;
117         break;
118     case LRO:
119         *text = UTF_LRO + *text + UTF_PDF;
120         break;
121     case EMPTY:
122         break;
123     default:
124         Assert(false);
125         break;
126     }
127 }
128 } // namespace Unicode
129
130
131 class InnerElementsParser : public ElementParser
132 {
133   public:
134     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
135                                         const DPL::String& /*name*/)
136     {
137         return std::bind(&InnerElementsParser::Other, this);
138     }
139
140     virtual void Accept(const Element& /*element*/)
141     {}
142
143     virtual void Accept(const Text& text)
144     {
145         if (!m_text) {
146             m_text = text;
147         } else {
148             m_text->value += text.value;
149         }
150     }
151
152     virtual void Accept(const XmlAttribute& attribute)
153     {
154         if (attribute.name == L"dir") {
155             m_textDirection = Unicode::ParseDirAttribute(attribute);
156         }
157     }
158
159     virtual void Verify()
160     {
161         if (!!m_text) {
162             Unicode::UpdateTextWithDirectionMark(m_textDirection,
163                                                  &m_text->value);
164             m_parentParser->Accept(*m_text);
165         }
166     }
167
168     InnerElementsParser(ElementParserPtr parent) :
169         m_parentParser(parent),
170         m_textDirection(Unicode::EMPTY)
171     {}
172
173     ElementParserPtr Other()
174     {
175         return ElementParserPtr(new InnerElementsParser(
176                                     std::static_pointer_cast<ElementParser>(
177                                         shared_from_this())));
178     }
179
180   private:
181     boost::optional<Text> m_text;
182     ElementParserPtr m_parentParser;
183     Unicode::Direction m_textDirection;
184 };
185
186 class NameParser : public ElementParser
187 {
188   public:
189     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
190                                         const DPL::String& /*name*/)
191     {
192         return std::bind(&NameParser::Other, this);
193     }
194
195     virtual void Accept(const Element& element)
196     {
197         m_lang = element.lang;
198         m_name = L"";
199     }
200
201     virtual void Accept(const Text& text)
202     {
203         if (!m_name) {
204             m_name = text.value;
205         } else {
206             *m_name += text.value;
207         }
208     }
209
210     virtual void Accept(const XmlAttribute& attribute)
211     {
212         if (attribute.name == L"short") {
213             if (!m_shortName) {
214                 m_shortName = attribute.value;
215             }
216         } else if (attribute.name == L"dir") {
217             m_textDirection = Unicode::ParseDirAttribute(attribute);
218         }
219     }
220
221     virtual void Verify()
222     {
223         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
224         if (!data.name) {
225             if (!!m_name) {
226 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
227                 NormalizeString(m_name, MAX_ATTR_ELEMENT_LENGTH, true);
228 #else
229                 NormalizeString(m_name);
230 #endif
231                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
232             }
233             data.name = m_name;
234             if (!!m_shortName) {
235 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
236                 NormalizeString(m_shortName, MAX_ATTR_ELEMENT_LENGTH, true);
237 #else
238                 NormalizeString(m_shortName);
239 #endif
240                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
241                                                      &*m_shortName);
242                 data.shortName = m_shortName;
243             }
244         }
245     }
246
247     NameParser(Unicode::Direction direction,
248                ConfigParserData& data) :
249         m_data(data),
250         m_textDirection(direction)
251     {}
252
253     ElementParserPtr Other()
254     {
255         return ElementParserPtr(new InnerElementsParser(
256                                     std::static_pointer_cast<ElementParser>(
257                                         shared_from_this())));
258     }
259
260   private:
261     ConfigParserData& m_data;
262     DPL::OptionalString m_name;
263     DPL::OptionalString m_shortName;
264     DPL::OptionalString m_dir;
265     DPL::String m_lang;
266     Unicode::Direction m_textDirection;
267 };
268
269 class AccessParser : public ElementParser
270 {
271   public:
272     enum StandardType
273     {
274         STANDARD_TYPE_NONE,
275         STANDARD_TYPE_WARP
276     };
277
278     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
279                                         const DPL::String& /*name*/)
280     {
281         return std::bind(&AccessParser::Other, this);
282     }
283
284     virtual void Accept(const Element& element)
285     {
286         // for tizen web apps WARP should be used
287         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName ||
288             element.ns == ConfigurationNamespace::TizenWebAppNamespaceName)
289         {
290             m_standardType = STANDARD_TYPE_WARP;
291         }
292     }
293
294     virtual void Accept(const Text& /*text*/)
295     {}
296
297     void AcceptWac(const XmlAttribute& attribute)
298     {
299         if (attribute.name == L"origin") {
300             m_strIRIOrigin = attribute.value;
301         } else if (attribute.name == L"subdomains") {
302             DPL::String normalizedValue = attribute.value;
303 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
304             NormalizeString(normalizedValue, MAX_ATTR_ELEMENT_LENGTH, true);
305 #else
306             NormalizeString(normalizedValue);
307 #endif
308             if (normalizedValue == L"true") {
309                 m_bSubDomainAccess = true;
310             } else {
311                 m_bSubDomainAccess = false;
312             }
313         }
314     }
315
316     virtual void Accept(const XmlAttribute& attribute)
317     {
318         switch (m_standardType) {
319         case STANDARD_TYPE_WARP:
320             AcceptWac(attribute);
321             break;
322         default:
323             _E("Error in Access tag - unknown standard.");
324             break;
325         }
326     }
327
328     void VerifyWac()
329     {
330 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
331         NormalizeString(m_strIRIOrigin, MAX_ATTR_ELEMENT_LENGTH, true);
332 #else
333         NormalizeString(m_strIRIOrigin);
334 #endif
335
336         WarpIRI iri;
337         iri.set(m_strIRIOrigin, false);
338
339         if (!iri.isAccessDefinition()) {
340             _W("Access list element: %ls is not acceptable by WARP standard and will be ignored!",
341                 m_strIRIOrigin.c_str());
342             return;
343         }
344
345         if(m_strIRIOrigin == L"*") //wildcard match means yes for subdomains
346         {
347             m_bSubDomainAccess = true;
348         }
349
350         ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
351                                                 m_bSubDomainAccess);
352         //std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
353         m_data.accessInfoSet.insert(accessInfo);
354     }
355
356     virtual void Verify()
357     {
358         switch (m_standardType) {
359         case STANDARD_TYPE_WARP:
360             VerifyWac();
361             break;
362         default:
363             _E("Error in Access tag - unknown standard.");
364             break;
365         }
366     }
367
368     AccessParser(ConfigParserData& data) :
369         ElementParser(),
370         m_bSubDomainAccess(false),
371         m_standardType(STANDARD_TYPE_NONE),
372         m_network(false),
373         m_data(data)
374     {}
375
376     ElementParserPtr Other()
377     {
378         return ElementParserPtr(new InnerElementsParser(
379                                     ElementParserPtr(shared_from_this())));
380     }
381
382   private:
383     DPL::String m_strIRIOrigin;
384     bool m_bSubDomainAccess;
385     StandardType m_standardType;
386     bool m_network;
387     ConfigParserData& m_data;
388 };
389
390 class DescriptionParser : public ElementParser
391 {
392   public:
393     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
394                                         const DPL::String& /*name*/)
395     {
396         return std::bind(&DescriptionParser::Other, this);
397     }
398
399     virtual void Accept(const Element& element)
400     {
401         m_lang = element.lang;
402         m_description = L"";
403     }
404
405     ElementParserPtr Other()
406     {
407         return ElementParserPtr(new InnerElementsParser(
408                                     std::static_pointer_cast<ElementParser>(
409                                         shared_from_this())));
410     }
411
412     virtual void Accept(const Text& text)
413     {
414         if (!m_description) {
415             m_description = text.value;
416         } else {
417             *m_description += text.value;
418         }
419     }
420
421     virtual void Accept(const XmlAttribute& attribute)
422     {
423         if (attribute.name == L"dir") {
424             m_textDirection = Unicode::ParseDirAttribute(attribute);
425         }
426     }
427
428     virtual void Verify()
429     {
430         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
431         if (!data.description) {
432             if (!!m_description) {
433                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
434                                                      &*m_description);
435             }
436             data.description = m_description;
437         }
438     }
439
440     DescriptionParser(Unicode::Direction direction,
441                       ConfigParserData& data) :
442         m_data(data),
443         m_lang(),
444         m_description(),
445         m_textDirection(direction)
446     {}
447
448   private:
449     ConfigParserData& m_data;
450     DPL::String m_lang;
451     DPL::OptionalString m_description;
452     Unicode::Direction m_textDirection;
453 };
454
455 class AuthorParser : public ElementParser
456 {
457   public:
458     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
459                                         const DPL::String& /*name*/)
460     {
461         return std::bind(&AuthorParser::Other, this);
462     }
463
464     AuthorParser(Unicode::Direction direction,
465                  ConfigParserData& data) :
466         m_data(data),
467         m_textDirection(direction)
468     {}
469
470     virtual void Accept(const Element& /*element*/)
471     {
472         m_authorName = L"";
473     }
474
475     virtual void Accept(const Text& text)
476     {
477         *(m_authorName) += text.value;
478     }
479
480     virtual void Accept(const XmlAttribute& attribute)
481     {
482         if (attribute.name == L"href") {
483             //Validate href IRI and ignore it if invalid
484             //See also test: ta-argMozRiC-an
485             LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
486             if (iri.Validate()) {
487                 m_authorHref = attribute.value;
488             }
489         } else if (attribute.name == L"email") {
490             m_authorEmail = attribute.value;
491         } else if (attribute.name == L"dir") {
492             m_textDirection = Unicode::ParseDirAttribute(attribute);
493         }
494     }
495
496     virtual void Verify()
497     {
498         if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
499             if (!!m_authorName) {
500 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
501                 NormalizeString(m_authorName, MAX_ATTR_ELEMENT_LENGTH, true);
502 #else
503                 NormalizeString(m_authorName);
504 #endif
505                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
506                                                      &*m_authorName);
507                 m_data.authorName = m_authorName;
508             }
509             if (!!m_authorHref) {
510 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
511                 NormalizeString(m_authorHref, MAX_ATTR_ELEMENT_LENGTH, true);
512 #else
513                 NormalizeString(m_authorHref);
514 #endif
515                 m_data.authorHref = m_authorHref;
516             }
517             if (!!m_authorEmail) {
518 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
519                 NormalizeString(m_authorEmail, MAX_ATTR_ELEMENT_LENGTH, true);
520 #else
521                 NormalizeString(m_authorEmail);
522 #endif
523                 m_data.authorEmail = m_authorEmail;
524             }
525         }
526     }
527
528     ElementParserPtr Other()
529     {
530         return ElementParserPtr(new InnerElementsParser(
531                                     std::static_pointer_cast<ElementParser>(
532                                         shared_from_this())));
533     }
534
535   private:
536     ConfigParserData& m_data;
537     DPL::OptionalString m_authorEmail;
538     DPL::OptionalString m_authorHref;
539     DPL::OptionalString m_authorName;
540     Unicode::Direction m_textDirection;
541 };
542
543 class LicenseParser : public ElementParser
544 {
545   public:
546     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
547                                         const DPL::String& /*name*/)
548     {
549         return std::bind(&LicenseParser::Other, this);
550     }
551
552     LicenseParser(Unicode::Direction direction,
553                   ConfigParserData& data) :
554         m_data(data),
555         m_ignore(true),
556         m_textDirection(direction)
557     {}
558
559     virtual void Accept(const Element& element)
560     {
561         if (!m_license) {
562             m_lang = element.lang;
563             m_license = L"";
564             m_ignore = false;
565         }
566     }
567
568     virtual void Accept(const Text& text)
569     {
570         if (!m_ignore) {
571             *m_license += text.value;
572         }
573     }
574
575     virtual void Accept(const XmlAttribute& attribute)
576     {
577         if (!m_ignore) {
578             if (attribute.name == L"href" && !m_licenseHref) {
579                 m_licenseHref = attribute.value;
580             } else if (attribute.name == L"file" && !m_licenseFile) {
581                 m_licenseFile = attribute.value;
582             } else if (attribute.name == L"dir") {
583                 m_textDirection = Unicode::ParseDirAttribute(attribute);
584             }
585         }
586     }
587
588     virtual void Verify()
589     {
590         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
591         if (!data.license) {
592             if (!!m_license) {
593                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
594                                                      &*m_license);
595             }
596             data.license = m_license;
597             data.licenseHref = m_licenseHref;
598             data.licenseFile = m_licenseFile;
599         }
600     }
601
602     ElementParserPtr Other()
603     {
604         return ElementParserPtr(new InnerElementsParser(
605                                     ElementParserPtr(shared_from_this())));
606     }
607
608   private:
609     ConfigParserData& m_data;
610     DPL::String m_lang;
611     bool m_ignore;
612
613     DPL::OptionalString m_license;
614     DPL::OptionalString m_licenseFile;
615     DPL::OptionalString m_licenseHref;
616     Unicode::Direction m_textDirection;
617 };
618
619 class IconParser : public ElementParser
620 {
621     DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError)
622
623   public:
624     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
625                                         const DPL::String& /*name*/)
626     {
627         return &IgnoringParser::Create; //ignore unknown according to w3c
628     }
629
630     IconParser(ConfigParserData& data) : ElementParser(),
631         m_data(data), m_isSmall(false)
632     {}
633
634     IconParser(ConfigParserData& data, bool isSmall) : ElementParser(),
635         m_data(data), m_isSmall(isSmall)
636     {}
637
638     virtual void Accept(const Element& /*element*/)
639     {}
640
641     virtual void Accept(const XmlAttribute& attribute)
642     {
643         if (attribute.name == L"src") {
644             if (attribute.value.size() > 0) {
645                 m_src = attribute.value;
646             }
647         } else if (attribute.name == L"width") {
648             m_width = ParseSizeAttributeValue(attribute.value);
649         } else if (attribute.name == L"height") {
650             m_height = ParseSizeAttributeValue(attribute.value);
651         }
652     }
653
654     virtual void Accept(const Text& /*text*/)
655     {
656         ThrowMsg(Exception::ParseError, "Icon element must be empty");
657     }
658
659     virtual void Verify()
660     {
661         if (!m_src) {
662             _W("src attribute of icon element is mandatory - ignoring");
663             return;
664         }
665
666         Try
667         {
668             ConfigParserData::Icon icon(delocalizeSrcPath(*m_src));
669             icon.width = m_width;
670             icon.height = m_height;
671             icon.isSmall = m_isSmall;
672
673             ConfigParserData::IconsList::iterator it = std::find(
674                     m_data.iconsList.begin(), m_data.iconsList.end(), icon);
675             if (it == m_data.iconsList.end()) {
676                 m_data.iconsList.push_front(icon);
677             }
678         }
679         Catch(BadSrcError)
680         {
681             _W("src attribute is invalid: %ls", (*m_src).c_str());
682         }
683     }
684
685   private:
686     ConfigParserData& m_data;
687     DPL::OptionalString m_src;
688     DPL::OptionalInt m_width;
689     DPL::OptionalInt m_height;
690     bool m_isSmall;
691
692     static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
693     {
694         DPL::OptionalString normalizedValue = value;
695         if (!(*normalizedValue).empty()) {
696 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
697             NormalizeString(normalizedValue, MAX_ATTR_ELEMENT_LENGTH, true);
698 #else
699             NormalizeString(normalizedValue);
700 #endif
701             char* reterr = NULL;
702             errno = 0;
703             long int valueInt =
704                 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
705             if (errno != 0 ||
706                 std::string(reterr) == DPL::ToUTF8String(value) ||
707                 valueInt <= 0)
708             {
709                 return DPL::OptionalInt();
710             } else {
711                 return valueInt;
712             }
713         }
714         return DPL::OptionalInt();
715     }
716
717     /**
718      * @brief delocalizePath removes locales folder from relative path if
719      * neccessary
720      * @param source source string
721      *
722      * @throw BadSrcError if string is bad value of src attribute
723      *
724      * @return corrected string
725      */
726     static DPL::String delocalizeSrcPath(const DPL::String & source)
727     {
728         static const DPL::String localeFolder(L"locales/");
729         static const int index = localeFolder.size();
730
731         DPL::String result = source;
732
733         if (source.substr(0, index) == localeFolder) {
734             size_t pos = result.find_first_of('/', index);
735             if (pos != std::string::npos && pos + 1 < source.size()) {
736                 result = result.substr(pos + 1, source.size());
737             } else {
738                 Throw(BadSrcError);
739             }
740         }
741         return result;
742     }
743 };
744
745 class ContentParser : public ElementParser
746 {
747   public:
748     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
749                                         const DPL::String& /*name*/)
750     {
751         return &IgnoringParser::Create; //ignore unknown according to w3c
752     }
753
754     ContentParser(ConfigParserData& data) :
755         ElementParser(),
756         m_data(data)
757     {}
758
759     virtual void Accept(const Element& element)
760     {
761         m_namespace = element.ns;
762     }
763
764     virtual void Accept(const Text& /*text*/)
765     {}
766
767     virtual void Accept(const XmlAttribute& attribute)
768     {
769         DPL::String value = attribute.value;
770
771         if (attribute.name == L"src") {
772             m_src = value;
773 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
774             NormalizeString(m_src, MAX_ATTR_ELEMENT_LENGTH, true);
775 #else
776             NormalizeString(m_src);
777 #endif
778         } else if (attribute.name == L"type") {
779             m_type = value;
780             MimeTypeUtils::MimeAttributes mimeAttributes =
781                 MimeTypeUtils::getMimeAttributes(value);
782             if ((mimeAttributes.count(L"charset") > 0) && !m_encoding)
783             {
784                 m_encoding = mimeAttributes[L"charset"];
785             }
786         } else if (attribute.name == L"encoding") {
787             if (!value.empty()) {
788                 m_encoding = value;
789             }
790         }
791     }
792
793     virtual void Verify()
794     {
795         if(!!m_data.startFileEncountered)
796         {
797             if(m_data.startFileNamespace == m_namespace
798                 || m_namespace != ConfigurationNamespace::TizenWebAppNamespaceName)
799             {
800                 return;
801             }
802             //else continue -> if previous item was not in tizen namespace
803         }
804
805         m_data.startFileEncountered = true;
806         m_data.startFileNamespace = m_namespace;
807
808         if (m_namespace == ConfigurationNamespace::TizenWebAppNamespaceName &&
809                 (!m_src || m_src->empty())) {
810             ThrowMsg(Exception::ParseError, "content element must have correct src element");
811         }
812
813         if (!!m_src) {
814             m_data.startFile = m_src;
815             if (!!m_type) {
816 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
817                 NormalizeString(m_type, MAX_ATTR_ELEMENT_LENGTH, true);
818 #else
819                 NormalizeString(m_type);
820 #endif
821                 m_data.startFileContentType = m_type;
822             }
823             if (!!m_encoding) {
824 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
825                 NormalizeString(m_encoding, MAX_ATTR_ELEMENT_LENGTH, true);
826 #else
827                 NormalizeString(m_encoding);
828 #endif
829                 m_data.startFileEncoding = m_encoding;
830             } else {
831                 m_data.startFileEncoding = L"UTF-8";
832             }
833         }
834     }
835
836   private:
837     DPL::OptionalString m_src;
838     DPL::OptionalString m_type;
839     DPL::OptionalString m_encoding;
840     ConfigParserData& m_data;
841     DPL::String m_namespace;
842 };
843
844 class PreferenceParser : public ElementParser
845 {
846   public:
847     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
848                                         const DPL::String& /*name*/)
849     {
850         return &IgnoringParser::Create; //ignore unknown according to w3c
851     }
852
853     virtual void Accept(const XmlAttribute& attribute)
854     {
855         if (attribute.name == L"name") {
856             m_name = attribute.value;
857         } else if (attribute.name == L"value") {
858             m_value = attribute.value;
859         } else if (attribute.name == L"readonly") {
860             if (attribute.value == L"true") {
861                 m_required = true;
862             } else {
863                 m_required = false;
864             }
865         }
866     }
867
868     virtual void Accept(const Element& /*element*/)
869     {}
870
871     virtual void Accept(const Text& /*text*/)
872     {
873         ThrowMsg(Exception::ParseError, "param element must be empty");
874     }
875
876     virtual void Verify()
877     {
878         if (!m_name) {
879             _W("preference element must have name attribute");
880             return;
881         }
882 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
883         NormalizeString(m_name, MAX_NAME_KEY_LENGTH, true);
884         NormalizeString(m_value, MAX_NAME_KEY_VALUE_LENGTH, true);
885 #else
886         NormalizeString(m_name);
887         NormalizeString(m_value);
888 #endif
889         ConfigParserData::Preference preference(*m_name, m_required);
890         preference.value = m_value;
891         if (m_data.preferencesList.find(preference) ==
892             m_data.preferencesList.end())
893         {
894             m_data.preferencesList.insert(preference);
895         }
896     }
897
898     PreferenceParser(ConfigParserData& data) :
899         ElementParser(),
900         m_required(false),
901         m_data(data)
902     {}
903
904   private:
905     DPL::OptionalString m_name;
906     DPL::OptionalString m_value;
907     bool m_required;
908     ConfigParserData& m_data;
909 };
910
911 class SettingParser : public ElementParser
912 {
913   public:
914     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
915                                         const DPL::String& /*name*/)
916     {
917         return &IgnoringParser::Create; //ignore unknown according to w3c
918     }
919
920     virtual void Accept(const Text& /*text*/)
921     {}
922
923     virtual void Accept(const Element& /*element*/)
924     {}
925
926     virtual void Accept(const XmlAttribute& attribute)
927     {
928         m_setting.m_name = attribute.name;
929         m_setting.m_value = attribute.value;
930         m_data.settingsList.insert(m_setting);
931     }
932
933     virtual void Verify()
934     {
935         if(m_data.serviceAppInfoList.size() > 0) {
936             FOREACH(it, m_data.settingsList) {
937                 if (it->m_name == L"encryption" && it->m_value == L"enable") {
938                     ThrowMsg(Exception::ParseError, "Service application does not support application encryption");
939                 }
940             }
941         }
942     }
943
944     SettingParser(ConfigParserData& data) :
945         ElementParser(),
946         m_data(data),
947         m_setting(L"", L"")
948     {}
949
950   private:
951     ConfigParserData& m_data;
952     ConfigParserData::Setting m_setting;
953 };
954
955 class AppControlParser : public ElementParser
956 {
957   public:
958     struct SourceParser : public ElementParser
959     {
960       public:
961         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
962                                             const DPL::String& /*name*/)
963         {
964             return &IgnoringParser::Create; //ignore unknown according to w3c
965         }
966
967         virtual void Accept(const Text& /*text*/)
968         {}
969
970         virtual void Accept(const Element& /*element*/)
971         {}
972
973         virtual void Accept(const XmlAttribute& attribute)
974         {
975             if (attribute.name == L"name") {
976                 if (attribute.value.size() > 0) {
977                     m_value = attribute.value;
978                 }
979             } else if (attribute.name == L"reload") {
980                 m_reload = attribute.value;
981             }
982         }
983
984         virtual void Verify()
985         {
986             if (!m_value || *m_value == L"") {
987                 return;
988             }
989 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
990             NormalizeString(m_value, MAX_ATTR_ELEMENT_LENGTH, true);
991 #else
992             NormalizeString(m_value);
993 #endif
994             m_appControl.m_src = *m_value;
995
996             if (!!m_reload) {
997                 if (*m_reload == L"enable") {
998                     m_appControl.m_reload = L"true";
999                 } else if (*m_reload == L"disable") {
1000                     m_appControl.m_reload = L"false";
1001                 } else {
1002                     ThrowMsg(Exception::ParseError, "Wrong reload value. enable or disable");
1003                 }
1004             }
1005         }
1006
1007         SourceParser(ConfigParserData::AppControlInfo& appControl, ConfigParserData& data) :
1008             ElementParser(),
1009             m_properNamespace(false),
1010             m_appControl(appControl),
1011             m_data(data)
1012         {}
1013
1014       private:
1015         bool m_properNamespace;
1016         DPL::OptionalString m_reload;
1017         DPL::OptionalString m_value;
1018         ConfigParserData::AppControlInfo& m_appControl;
1019         ConfigParserData& m_data;
1020     };
1021
1022     struct OperationParser : public ElementParser
1023     {
1024       public:
1025         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1026                                             const DPL::String& /*name*/)
1027         {
1028             return &IgnoringParser::Create; //ignore unknown according to w3c
1029         }
1030
1031         virtual void Accept(const Text& /*text*/)
1032         {}
1033
1034         virtual void Accept(const Element& /*element*/)
1035         {}
1036
1037         virtual void Accept(const XmlAttribute& attribute)
1038         {
1039             if (attribute.name == L"name") {
1040                 if (attribute.value.size() > 0) {
1041                     m_value = attribute.value;
1042                 }
1043             }
1044         }
1045
1046         virtual void Verify()
1047         {
1048             if (!m_value || *m_value == L"") {
1049                 return;
1050             }
1051 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
1052             NormalizeString(m_value, MAX_ATTR_ELEMENT_LENGTH, true);
1053 #else
1054             NormalizeString(m_value);
1055 #endif
1056             m_appControl.m_operation = *m_value;
1057         }
1058
1059         OperationParser(ConfigParserData::AppControlInfo& data) :
1060             ElementParser(),
1061             m_properNamespace(false),
1062             m_appControl(data)
1063         {}
1064
1065       private:
1066         bool m_properNamespace;
1067         DPL::OptionalString m_value;
1068         ConfigParserData::AppControlInfo& m_appControl;
1069     };
1070
1071     struct UriParser : public ElementParser
1072     {
1073       public:
1074         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1075                                             const DPL::String& /*name*/)
1076         {
1077             return &IgnoringParser::Create; //ignore unknown according to w3c
1078         }
1079
1080         virtual void Accept(const Text& /*text*/)
1081         {}
1082
1083         virtual void Accept(const Element& /*element*/)
1084         {}
1085
1086         virtual void Accept(const XmlAttribute& attribute)
1087         {
1088             if (attribute.name == L"name") {
1089                 if (attribute.value.size() > 0) {
1090                     m_value = attribute.value;
1091                 }
1092             }
1093         }
1094
1095         virtual void Verify()
1096         {
1097             // exception
1098             DPL::String ignoreUri(L"file");
1099
1100             if (!!m_value && *m_value == ignoreUri)
1101             {
1102                 _D("exception : '%ls' scheme will be ignored.", (*m_value).c_str());
1103                 m_value = DPL::OptionalString();
1104             }
1105
1106             if (!m_value || *m_value == L"") {
1107                 return;
1108             }
1109 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
1110             NormalizeString(m_value, MAX_ATTR_ELEMENT_LENGTH, true);
1111 #else
1112             NormalizeString(m_value);
1113 #endif
1114             DPL::String wildString(L"*/*");
1115             if ((m_appControl.m_uriList.find(wildString) == m_appControl.m_uriList.end())
1116                 && (m_appControl.m_uriList.find(*m_value) == m_appControl.m_uriList.end()))
1117             {
1118                 m_appControl.m_uriList.insert(*m_value);
1119             } else {
1120                 _D("Ignoring uri with name %ls", (*m_value).c_str());
1121             }
1122         }
1123
1124         UriParser(ConfigParserData::AppControlInfo& data) :
1125             ElementParser(),
1126             m_properNamespace(false),
1127             m_appControl(data)
1128         {}
1129
1130       private:
1131         bool m_properNamespace;
1132         DPL::OptionalString m_value;
1133         ConfigParserData::AppControlInfo& m_appControl;
1134     };
1135
1136     struct MimeParser : public ElementParser
1137     {
1138       public:
1139         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1140                                             const DPL::String& /*name*/)
1141         {
1142             return &IgnoringParser::Create; //ignore unknown according to w3c
1143         }
1144
1145         virtual void Accept(const Text& /*text*/)
1146         {}
1147
1148         virtual void Accept(const Element& /*element*/)
1149         {}
1150
1151         virtual void Accept(const XmlAttribute& attribute)
1152         {
1153             if (attribute.name == L"name") {
1154                 if (attribute.value.size() > 0) {
1155                     m_value = attribute.value;
1156                 }
1157             }
1158         }
1159
1160         virtual void Verify()
1161         {
1162             if (!m_value || *m_value == L"") {
1163                 return;
1164             }
1165 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
1166             NormalizeString(m_value, MAX_ATTR_ELEMENT_LENGTH, true);
1167 #else
1168             NormalizeString(m_value);
1169 #endif
1170             DPL::String wildString(L"*/*");
1171             if ((m_appControl.m_mimeList.find(wildString) ==
1172                  m_appControl.m_mimeList.end())
1173                 && (m_appControl.m_mimeList.find(*m_value) ==
1174                     m_appControl.m_mimeList.end()))
1175             {
1176                 m_appControl.m_mimeList.insert(*m_value);
1177             } else {
1178                 _D("Ignoring mime with name %ls", (*m_value).c_str());
1179             }
1180         }
1181
1182         MimeParser(ConfigParserData::AppControlInfo& data) :
1183             ElementParser(),
1184             m_properNamespace(false),
1185             m_appControl(data)
1186         {}
1187
1188       private:
1189         bool m_properNamespace;
1190         DPL::OptionalString m_value;
1191         ConfigParserData::AppControlInfo& m_appControl;
1192     };
1193
1194     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1195                                         const DPL::String& name)
1196     {
1197         if (name == L"src") {
1198             return std::bind(&AppControlParser::OnSourceElement, this);
1199         } else if (name == L"operation") {
1200             return std::bind(&AppControlParser::OnOperationElement, this);
1201         } else if (name == L"uri") {
1202             return std::bind(&AppControlParser::OnUriElement, this);
1203         } else if (name == L"mime") {
1204             return std::bind(&AppControlParser::OnMimeElement, this);
1205         } else {
1206             return &IgnoringParser::Create; //ignore unknown according to w3c
1207         }
1208     }
1209
1210     virtual void Accept(const XmlAttribute& /*attribute*/)
1211     {}
1212
1213     virtual void Accept(const Element& element)
1214     {
1215         _W("namespace for app service = %ls", element.ns.c_str());
1216         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1217             ThrowMsg(Exception::ParseError,
1218                      "Wrong xml namespace for widget element");
1219         }
1220     }
1221
1222     virtual void Accept(const Text& /*text*/)
1223     {
1224         ThrowMsg(Exception::ParseError, "param element must be empty");
1225     }
1226
1227     virtual void Verify()
1228     {
1229         if (m_appControl.m_src == L"") {
1230             ThrowMsg(Exception::ParseError, "service element must have src element");
1231         }
1232
1233         if (m_appControl.m_operation == L"") {
1234             ThrowMsg(Exception::ParseError, "service element must have operation element");
1235         }
1236
1237         auto res = std::find(m_data.appControlList.begin(), m_data.appControlList.end(), m_appControl);
1238         if(res != m_data.appControlList.end()) {
1239             ThrowMsg(Exception::ParseError, "service element must be unique");
1240         }
1241
1242 #ifdef NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY
1243         // XXX This feature should be retained to Tizen 2.2 only.
1244         // NFC exception handling which was requested from Tizen Device API team.
1245
1246         const DPL::String exceptionNfcOperation =
1247                        L"http://tizen.org/appcontrol/operation/nfc/transaction";
1248         const DPL::String exceptionNfcUri  = L"nfc://secure/aid/";
1249         const DPL::String divertingNfcUri1 = L"nfc://secure/SIM1/aid/";
1250         const DPL::String divertingNfcUri2 = L"nfc://secure/eSE/aid/";
1251
1252         if (m_appControl.m_operation == exceptionNfcOperation
1253             && m_appControl.m_mimeList.empty()
1254             && m_appControl.m_uriList.size() == 1
1255             && (m_appControl.m_uriList.begin())->compare(0, exceptionNfcUri.length(), exceptionNfcUri) == 0)
1256         {
1257             DPL::String originalUri = *m_appControl.m_uriList.begin();
1258             DPL::String newUri = originalUri;
1259
1260             newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri1);
1261             m_appControl.m_uriList.erase(m_appControl.m_uriList.begin());
1262             m_appControl.m_uriList.insert(newUri);
1263             m_data.appControlList.push_back(m_appControl);
1264             _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str());
1265
1266             newUri = originalUri;
1267             newUri.replace(0, exceptionNfcUri.length(), divertingNfcUri2);
1268             m_appControl.m_uriList.erase(m_appControl.m_uriList.begin());
1269             m_appControl.m_uriList.insert(newUri);
1270             m_data.appControlList.push_back(m_appControl);
1271             _D("NFC exception : %ls -> %ls", originalUri.c_str(), newUri.c_str());
1272
1273             return;
1274         }
1275 #endif // NFC_EXCEPTION_HANDLING_FOR_TIZEN_2_2_ONLY
1276
1277         m_data.appControlList.push_back(m_appControl);
1278     }
1279
1280     ElementParserPtr OnSourceElement()
1281     {
1282         return ElementParserPtr(new SourceParser(m_appControl, m_data));
1283     }
1284
1285     ElementParserPtr OnOperationElement()
1286     {
1287         return ElementParserPtr(new OperationParser(m_appControl));
1288     }
1289
1290     ElementParserPtr OnUriElement()
1291     {
1292         return ElementParserPtr(new UriParser(m_appControl));
1293     }
1294
1295     ElementParserPtr OnMimeElement()
1296     {
1297         return ElementParserPtr(new MimeParser(m_appControl));
1298     }
1299
1300     AppControlParser(ConfigParserData& data) :
1301         ElementParser(),
1302         m_data(data),
1303         m_appControl(L"")
1304     {}
1305
1306   private:
1307     ConfigParserData& m_data;
1308     ConfigParserData::AppControlInfo m_appControl;
1309 };
1310
1311 class ApplicationParser : public ElementParser
1312 {
1313   public:
1314     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1315                                         const DPL::String& /*name*/)
1316     {
1317         return &IgnoringParser::Create; //ignore unknown according to w3c
1318     }
1319
1320     virtual void Accept(const Text& /*text*/)
1321     {
1322         if (m_properNamespace) {
1323             ThrowMsg(Exception::ParseError, "application element must be empty");
1324         }
1325     }
1326
1327     virtual void Accept(const Element& element)
1328     {
1329         if (element.ns ==
1330             ConfigurationNamespace::TizenWebAppNamespaceName)
1331         {
1332             m_properNamespace = true;
1333         }
1334     }
1335
1336     virtual void Accept(const XmlAttribute& attribute)
1337     {
1338         if (m_properNamespace) {
1339             if (attribute.name == L"id") {
1340                 if (attribute.value.length() > MAX_APPLICATION_ID_LENGTH) {
1341                     ThrowMsg(Exception::ParseError,
1342                              "length of application id has crossed the allowed limit");
1343                 } else {
1344                     m_id = attribute.value;
1345                     NormalizeAndTrimSpaceString(m_id);
1346                 }
1347             } else if (attribute.name == L"package") {
1348                 m_package = attribute.value;
1349             } else if (attribute.name == L"required_version") {
1350                 m_version = attribute.value;
1351             } else if (attribute.name == L"launch_mode") {
1352                 m_launchMode = attribute.value;
1353 #ifdef AMBIENT_ENABLED
1354             } else if (attribute.name == L"ambient_support") {
1355                 m_ambient = attribute.value;
1356 #endif
1357             } else {
1358                 ThrowMsg(Exception::ParseError,
1359                          "unknown attribute '" +
1360                          DPL::ToUTF8String(attribute.name) +
1361                          "' in application element");
1362             }
1363         }
1364     }
1365
1366     virtual void Verify()
1367     {
1368         if (m_data.didFoundTizenApplicationElement) {
1369             ThrowMsg(Exception::ParseError, "tizen:application element must occur only once");
1370         }
1371         m_data.didFoundTizenApplicationElement = true;
1372
1373         VerifyIdAndPackage();
1374         VerifyVersion();
1375
1376         if (!!m_launchMode) {
1377             if (*m_launchMode != L"caller" && *m_launchMode != L"group" && *m_launchMode != L"single") {
1378                 ThrowMsg(Exception::ParseError, "Wrong launch_mode value. only caller, single and group are acceptable");
1379             }
1380             m_data.launchMode = m_launchMode;
1381         }
1382
1383 #ifdef AMBIENT_ENABLED
1384         if (!!m_ambient) {
1385             if (*m_ambient == L"enable") {
1386                 m_data.ambient = L"true";
1387             } else if (*m_ambient == L"disable") {
1388                 m_data.ambient = L"false";
1389             } else {
1390                 ThrowMsg(Exception::ParseError, "Wrong ambient_support value. enable or disable");
1391             }
1392         }
1393 #endif
1394     }
1395
1396     ApplicationParser(ConfigParserData& data) :
1397         ElementParser(),
1398         m_data(data),
1399         m_id(DPL::OptionalString()),
1400         m_version(DPL::OptionalString()),
1401         m_launchMode(DPL::OptionalString()),
1402 #ifdef AMBIENT_ENABLED
1403         m_ambient(DPL::OptionalString()),
1404 #endif
1405         m_properNamespace(false)
1406     {}
1407
1408     static const char* const REGEXP_ID;
1409
1410   private:
1411     void VerifyIdAndPackage()
1412     {
1413         if (!m_package)
1414         {
1415             ThrowMsg(Exception::ParseError,
1416                      "application element must have package attribute");
1417         }
1418         else
1419         {
1420             pcrecpp::RE re(REGEXP_PACKAGE);
1421             if (!re.FullMatch(DPL::ToUTF8String(*m_package)))
1422             {
1423                 ThrowMsg(Exception::ParseError,
1424                          "invalid format of package attribute");
1425             }
1426         }
1427
1428         if (!m_id) {
1429             ThrowMsg(Exception::ParseError,
1430                      "application element must have id attribute");
1431         }
1432         else
1433         {
1434             std::string package;
1435             pcrecpp::RE re(REGEXP_ID);
1436             if (!re.FullMatch(DPL::ToUTF8String(*m_id), &package))
1437             {
1438                 ThrowMsg(Exception::ParseError,
1439                          "invalid format of id attribute");
1440             }
1441             if (package != DPL::ToUTF8String(*m_package))
1442             {
1443                 ThrowMsg(Exception::ParseError,
1444                          "invalid package prefix in id attribute");
1445             }
1446         }
1447
1448         m_data.tizenAppId = m_id;
1449         m_data.tizenPkgId = m_package;
1450     }
1451
1452     void VerifyVersion()
1453     {
1454         if (!m_version)
1455         {
1456             ThrowMsg(Exception::ParseError,
1457                      "application element must have required_version attribute");
1458         }
1459         else
1460         {
1461             pcrecpp::RE re(REGEXP_VERSION);
1462 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
1463             NormalizeString(m_version, MAX_ATTR_ELEMENT_LENGTH, true);
1464 #else
1465             NormalizeString(m_version);
1466 #endif
1467             if (!re.FullMatch(DPL::ToUTF8String(*m_version)))
1468             {
1469                 ThrowMsg(Exception::ParseError,
1470                          "invalid format of version attribute");
1471             }
1472         }
1473
1474         m_data.tizenMinVersionRequired = m_version;
1475     }
1476
1477     static const char* const REGEXP_PACKAGE;
1478     static const char* const REGEXP_VERSION;
1479
1480     ConfigParserData& m_data;
1481     DPL::OptionalString m_id;
1482     DPL::OptionalString m_package;
1483     DPL::OptionalString m_version;
1484     DPL::OptionalString m_launchMode;
1485 #ifdef AMBIENT_ENABLED
1486     DPL::OptionalString m_ambient;
1487 #endif
1488     bool m_properNamespace;
1489 };
1490
1491 const char* const ApplicationParser::REGEXP_PACKAGE = "[0-9A-Za-z]{10}";
1492 const char* const ApplicationParser::REGEXP_ID = "([0-9A-Za-z]{10})\\.[0-9A-Za-z]{1,52}";
1493 const char* const ApplicationParser::REGEXP_VERSION = "\\d+\\.\\d+(\\.\\d+)*";
1494
1495 class SplashParser : public ElementParser
1496 {
1497   public:
1498     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1499                                         const DPL::String& /*name*/)
1500     {
1501         return &IgnoringParser::Create; //ignore unknown according to w3c
1502     }
1503
1504     virtual void Accept(const XmlAttribute& attribute)
1505     {
1506         if (m_properNamespace)
1507         {
1508             if (attribute.name == L"src") {
1509                 if (attribute.value.size() > 0) {
1510                     m_src = attribute.value;
1511                 }
1512             }
1513         }
1514     }
1515
1516     virtual void Accept(const Element& element)
1517     {
1518         if (element.ns ==
1519             ConfigurationNamespace::TizenWebAppNamespaceName)
1520         {
1521             m_properNamespace = true;
1522         }
1523     }
1524
1525     virtual void Accept(const Text& /*text*/)
1526     {}
1527
1528     virtual void Verify()
1529     {
1530         if (!m_src)
1531         {
1532             _W("src attribute of splash element is mandatory - ignoring");
1533             return;
1534         }
1535
1536         m_data.splashImgSrc = m_src;
1537     }
1538
1539     SplashParser(ConfigParserData& data) :
1540         ElementParser(),
1541         m_data(data),
1542         m_properNamespace(false)
1543     {}
1544
1545   private:
1546     DPL::OptionalString m_src;
1547     ConfigParserData& m_data;
1548     bool m_properNamespace;
1549 };
1550
1551 class BackgroundParser : public ElementParser
1552 {
1553   public:
1554     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1555                                         const DPL::String& /*name*/)
1556     {
1557         return &IgnoringParser::Create; //ignore unknown according to w3c
1558     }
1559
1560     virtual void Accept(const XmlAttribute& attribute)
1561     {
1562         if (attribute.name == L"src") {
1563             if (attribute.value.size() > 0) {
1564                 m_src = attribute.value;
1565             }
1566         }
1567     }
1568
1569     virtual void Accept(const Element& /*element*/)
1570     {}
1571
1572     virtual void Accept(const Text& /*text*/)
1573     {}
1574
1575     virtual void Verify()
1576     {
1577         if (!m_src) {
1578             _W("src attribute of background element is mandatory - ignoring");
1579             return;
1580         }
1581
1582         m_data.backgroundPage = m_src;
1583     }
1584
1585     explicit BackgroundParser(ConfigParserData& data) :
1586         m_data(data)
1587     {}
1588
1589   private:
1590     DPL::OptionalString m_src;
1591     ConfigParserData& m_data;
1592 };
1593
1594 class PrivilegeParser : public ElementParser
1595 {
1596   public:
1597     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1598                                         const DPL::String& /*name*/)
1599     {
1600         return &IgnoringParser::Create; //ignore unknown according to w3c
1601     }
1602
1603     virtual void Accept(const Text& /*text*/)
1604     {}
1605
1606     virtual void Accept(const Element& element)
1607     {
1608         if (element.ns ==
1609             ConfigurationNamespace::TizenWebAppNamespaceName)
1610         {
1611             m_properNamespace = true;
1612         }
1613         _D("element");
1614     }
1615
1616     virtual void Accept(const XmlAttribute& attribute)
1617     {
1618         if (m_properNamespace) {
1619             if (attribute.name == L"name") {
1620                 m_feature.name = attribute.value;
1621                 m_privilege.name = attribute.value;
1622             }
1623         }
1624     }
1625
1626     virtual void Verify()
1627     {
1628         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
1629
1630         if (m_feature.name != L"") {
1631             if (iri.Validate()) {
1632                 if (m_data.featuresList.find(m_feature) ==
1633                     m_data.featuresList.end())
1634                 {
1635                     m_data.featuresList.insert(m_feature);
1636                 } else {
1637                     _D("Ignoring feature with name %ls", m_feature.name.c_str());
1638                 }
1639             }
1640         }
1641
1642         LibIri::Wrapper iriPrivilege(
1643             DPL::ToUTF8String(m_privilege.name).c_str());
1644
1645         if (m_privilege.name != L"") {
1646             if (iriPrivilege.Validate()) {
1647                 if (m_data.privilegeList.find(m_privilege) ==
1648                     m_data.privilegeList.end())
1649                 {
1650                     m_data.privilegeList.insert(m_privilege);
1651                 } else {
1652                     _D("Ignoring privilege with name %ls", m_privilege.name.c_str());
1653                 }
1654             }
1655         }
1656     }
1657
1658     PrivilegeParser(ConfigParserData& data) :
1659         ElementParser(),
1660         m_data(data),
1661         m_feature(L""),
1662         m_privilege(L""),
1663         m_properNamespace(false)
1664     {}
1665
1666   private:
1667     ConfigParserData& m_data;
1668     ConfigParserData::Feature m_feature;
1669     ConfigParserData::Privilege m_privilege;
1670     bool m_properNamespace;
1671 };
1672
1673 class CategoryParser : public ElementParser
1674 {
1675   public:
1676     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1677                                         const DPL::String& /*name*/)
1678     {
1679         return &IgnoringParser::Create; //ignore unknown according to w3c
1680     }
1681
1682     virtual void Accept(const Element& element)
1683     {
1684         if (element.ns ==
1685             ConfigurationNamespace::TizenWebAppNamespaceName)
1686         {
1687             m_properNamespace = true;
1688         }
1689         _W("element");
1690     }
1691
1692     virtual void Accept(const XmlAttribute& attribute)
1693     {
1694         if (m_properNamespace) {
1695             if (attribute.name == L"name") {
1696                 if (attribute.value.size() > 0) {
1697                     m_name = attribute.value;
1698                 }
1699             }
1700         }
1701     }
1702
1703     virtual void Accept(const Text& /*text*/)
1704     {}
1705
1706     virtual void Verify()
1707     {
1708         if (!m_name) {
1709             _W("name attribute of category element is mandatory - ignoring");
1710             return;
1711         }
1712
1713         if (m_data.categoryList.find(*m_name) ==
1714             m_data.categoryList.end())
1715         {
1716             m_data.categoryList.insert(*m_name);
1717         }
1718     }
1719
1720     explicit CategoryParser(ConfigParserData& data) :
1721         m_data(data),
1722         m_properNamespace(false)
1723     {}
1724
1725   private:
1726     DPL::OptionalString m_name;
1727     ConfigParserData& m_data;
1728     bool m_properNamespace;
1729 };
1730
1731 class BackgroundCategoryParser : public ElementParser
1732 {
1733   public:
1734     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1735                                         const DPL::String& /*name*/)
1736     {
1737         return &IgnoringParser::Create; //ignore unknown according to w3c
1738     }
1739
1740     virtual void Accept(const XmlAttribute& attribute)
1741     {
1742         if (attribute.name == L"value") {
1743             if (attribute.value.size() > 0) {
1744                 m_value = attribute.value;
1745             }
1746         }
1747     }
1748
1749     virtual void Accept(const Element& /*element*/)
1750     {}
1751
1752     virtual void Accept(const Text& /*text*/)
1753     {}
1754
1755     virtual void Verify()
1756     {
1757         if (!m_value) {
1758             _W("value attribute of background-category element is mandatory - ignoring");
1759             return;
1760         }
1761
1762         if (m_data.backgroundCategoryList.find(*m_value) ==
1763             m_data.backgroundCategoryList.end())
1764         {
1765             m_data.backgroundCategoryList.insert(*m_value);
1766         }
1767     }
1768
1769     explicit BackgroundCategoryParser(ConfigParserData& data) :
1770         m_data(data)
1771     {}
1772
1773   private:
1774     DPL::OptionalString m_value;
1775     ConfigParserData& m_data;
1776 };
1777
1778 #if USE(WEB_PROVIDER)
1779 class AppWidgetParser : public ElementParser
1780 {
1781   public:
1782
1783     struct BoxLabelParser : public ElementParser
1784     {
1785         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1786                                             const DPL::String& /*name*/)
1787         {
1788             return &IgnoringParser::Create; //ignore unknown according to w3c
1789         }
1790
1791         virtual void Accept(const XmlAttribute& attribute)
1792         {
1793             if (m_properNamespace) {
1794                  m_lang = attribute.lang;
1795             }
1796         }
1797         virtual void Accept(const Element& element)
1798         {
1799             if (element.ns ==
1800                 ConfigurationNamespace::TizenWebAppNamespaceName)
1801             {
1802                 m_properNamespace = true;
1803             }
1804         }
1805
1806         virtual void Accept(const Text& text)
1807         {
1808             if (m_properNamespace) {
1809                 m_label = text.value;
1810             }
1811         }
1812
1813         virtual void Verify()
1814         {
1815             std::pair<DPL::String, DPL::String> boxLabel;
1816             if (m_label.empty()) {
1817                 _W("box-label element is empty");
1818                 boxLabel.first = DPL::FromUTF8String("");
1819                 boxLabel.second = DPL::FromUTF8String("");
1820                 m_data.m_label.push_back(boxLabel);
1821             }
1822             else {
1823                 boxLabel.first = m_lang;
1824                 boxLabel.second = m_label;
1825                 m_data.m_label.push_back(boxLabel);
1826             }
1827         }
1828
1829         BoxLabelParser(ConfigParserData::LiveboxInfo& data) :
1830             ElementParser(),
1831             m_properNamespace(false),
1832             m_data(data)
1833         {}
1834
1835       private:
1836         DPL::String m_lang;
1837         DPL::String m_label;
1838         bool m_properNamespace;
1839         ConfigParserData::LiveboxInfo& m_data;
1840     };
1841
1842     struct BoxIconParser : public ElementParser
1843     {
1844         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1845                                             const DPL::String& /*name*/)
1846         {
1847             return &IgnoringParser::Create; //ignore unknown according to w3c
1848         }
1849
1850         virtual void Accept(const XmlAttribute& attribute)
1851         {
1852             if (m_properNamespace) {
1853                 if (attribute.name == L"src") {
1854                     m_icon = attribute.value;
1855                 }
1856             }
1857         }
1858
1859         virtual void Accept(const Element& element)
1860         {
1861             if (element.ns ==
1862                 ConfigurationNamespace::TizenWebAppNamespaceName)
1863             {
1864                 m_properNamespace = true;
1865             }
1866         }
1867
1868         virtual void Accept(const Text& /*text*/)
1869         {}
1870
1871         virtual void Verify()
1872         {
1873             if (m_icon.empty()) {
1874                 ThrowMsg(Exception::ParseError,
1875                     "src attribute of box-icon element is mandatory - ignoring");
1876             }
1877             if (!m_data.m_icon.empty()) {
1878                 ThrowMsg(Exception::ParseError,
1879                     "<tizen:box-icon /> element should occur as 0 or 1 time");
1880             }
1881             m_data.m_icon = m_icon;
1882         }
1883
1884         explicit BoxIconParser(ConfigParserData::LiveboxInfo& data) :
1885             ElementParser(),
1886             m_properNamespace(false),
1887             m_data(data)
1888         {}
1889
1890       private:
1891         DPL::String m_icon;
1892         bool m_properNamespace;
1893         ConfigParserData::LiveboxInfo& m_data;
1894     };
1895
1896     struct BoxContentParser : public ElementParser
1897     {
1898         struct BoxSizeParser : public ElementParser
1899         {
1900             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1901                                                 const DPL::String& /*name*/)
1902             {
1903                 return &IgnoringParser::Create; //ignore unknown according to w3c
1904             }
1905
1906             virtual void Accept(const XmlAttribute& attribute)
1907             {
1908                 if (m_properNamespace) {
1909                     if (attribute.name == L"preview") {
1910                         m_preview = attribute.value;
1911                     }
1912                     if (attribute.name == L"use-decoration") {
1913                         m_useDecoration = attribute.value;
1914                     }
1915                 }
1916             }
1917
1918             virtual void Accept(const Element& element)
1919             {
1920                 if (element.ns ==
1921                     ConfigurationNamespace::TizenWebAppNamespaceName)
1922                 {
1923                     m_properNamespace = true;
1924                 }
1925             }
1926
1927             virtual void Accept(const Text& text)
1928             {
1929                 if (m_properNamespace) {
1930                     m_size = text.value;
1931                 }
1932             }
1933
1934             virtual void Verify()
1935             {
1936                 if(m_size.empty()) {
1937                     ThrowMsg(Exception::ParseError,
1938                         "size is mandatory - ignoring");
1939                 }
1940
1941                 if (m_useDecoration.empty() || CheckIfNotTrueNorFalse(m_useDecoration)) {
1942                     m_useDecoration = L"true"; // default value
1943                 }
1944
1945                 ConfigParserData::LiveboxInfo::BoxSizeInfo boxSizeInfo;
1946                 boxSizeInfo.m_size = m_size;
1947                 boxSizeInfo.m_preview = m_preview;
1948                 boxSizeInfo.m_useDecoration = m_useDecoration;
1949                 m_data.m_boxSize.push_back(boxSizeInfo);
1950             }
1951
1952             explicit BoxSizeParser(
1953                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
1954                 ElementParser(),
1955                 m_properNamespace(false),
1956                 m_data(data)
1957             {}
1958
1959           private:
1960             DPL::String m_size;
1961             DPL::String m_preview;
1962             DPL::String m_useDecoration;
1963             bool m_properNamespace;
1964             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
1965         };
1966
1967         struct PdParser : public ElementParser
1968         {
1969             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1970                                                 const DPL::String& /*name*/)
1971             {
1972                 return &IgnoringParser::Create; //ignore unknown according to w3c
1973             }
1974
1975             virtual void Accept(const XmlAttribute& attribute)
1976             {
1977                 if (m_properNamespace) {
1978                     if (attribute.name == L"src") {
1979                         m_src = attribute.value;
1980                     } else if (attribute.name == L"width") {
1981                         m_width = attribute.value;
1982                     } else if (attribute.name == L"height") {
1983                         m_height = attribute.value;
1984                     } else if (attribute.name == L"fast-open") {
1985                         m_fastOpen= attribute.value;
1986                     }
1987                 }
1988             }
1989
1990             virtual void Accept(const Element& element)
1991             {
1992                 if (element.ns ==
1993                     ConfigurationNamespace::TizenWebAppNamespaceName)
1994                 {
1995                     m_properNamespace = true;
1996                 }
1997             }
1998
1999             virtual void Accept(const Text& /*text*/)
2000             {}
2001
2002             virtual void Verify()
2003             {
2004                 if (m_src.empty()) {
2005                     ThrowMsg(Exception::ParseError,
2006                         "src attribute of pd element is mandatory - ignoring");
2007                 }
2008
2009                 if (m_width.empty()) {
2010                     ThrowMsg(Exception::ParseError,
2011                         "width attribute of pd element is mandatory - ignoring");
2012                 }
2013
2014                 if (m_height.empty()) {
2015                     ThrowMsg(Exception::ParseError,
2016                         "height attribute of pd element is mandatory - ignoring");
2017                 }
2018
2019                 if (!ConvertToInt(m_width)) {
2020                     ThrowMsg(Exception::ParseError,
2021                         "width attribute of pd element cannot be converted to int - ignoring. value: " << m_width);
2022                 }
2023
2024
2025                 DPL::OptionalInt height = ConvertToInt(m_height);
2026
2027                 if (!height) {
2028                     ThrowMsg(Exception::ParseError,
2029                         "height attribute of pd element cannot be converted to int - ignoring. value: " << m_height);
2030                 }
2031
2032                 if (*height < 1) {
2033                     m_height = L"1";
2034                     _D("height attribute of pd element shouldn't be less than 1. Changed to 1 from %d", *height);
2035                 } else if (*height > 380){
2036                     m_height = L"380";
2037                     _D("height attribute of pd element shouldn't be greater than 380. Changed to 380 from %d", *height);
2038                 }
2039
2040                 if (!m_data.m_pdSrc.empty()) {
2041                     ThrowMsg(Exception::ParseError, "<tizen:pd> element should occur as 0 or 1 time");
2042                 }
2043
2044                 m_data.m_pdSrc = m_src;
2045                 m_data.m_pdWidth = m_width;
2046                 m_data.m_pdHeight = m_height;
2047                 m_data.m_pdFastOpen = m_fastOpen;
2048             }
2049
2050             explicit PdParser(
2051                 ConfigParserData::LiveboxInfo::BoxContentInfo& data) :
2052                 ElementParser(),
2053                 m_properNamespace(false),
2054                 m_data(data)
2055             {}
2056
2057           private:
2058             DPL::OptionalInt ConvertToInt(const DPL::String& intAsString)
2059             {
2060                 char * endptr;
2061                 std::string tempStr = DPL::ToUTF8String(intAsString);
2062                 const char * intAsString_c = tempStr.c_str();
2063                 errno = 0;
2064                 long int intAsString_i = strtol(intAsString_c, &endptr, 10);
2065
2066                 if ((errno == ERANGE && (intAsString_i == LONG_MAX || intAsString_i == LONG_MIN))
2067                         || intAsString_i > INT_MAX || intAsString_i < INT_MIN //Intended code for INT_MAX/MIN
2068                         || *endptr != '\0') {
2069                     return DPL::OptionalInt();
2070                 }
2071
2072                 return static_cast<int>(intAsString_i);
2073             }
2074
2075             DPL::String m_src;
2076             DPL::String m_width;
2077             DPL::String m_height;
2078             DPL::String m_fastOpen;
2079
2080             bool m_properNamespace;
2081             ConfigParserData::LiveboxInfo::BoxContentInfo& m_data;
2082         };
2083
2084         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2085                                             const DPL::String& name)
2086         {
2087             if (name == L"box-size") {
2088                 return std::bind(&AppWidgetParser::BoxContentParser::OnBoxSizeElement, this);
2089             } else if (name == L"pd") {
2090                 return std::bind(&AppWidgetParser::BoxContentParser::OnPdElement, this);
2091             } else {
2092                 ThrowMsg(Exception::ParseError,
2093                          "No element parser for name: " << name);
2094             }
2095         }
2096
2097         virtual void Accept(const XmlAttribute& attribute)
2098         {
2099             if (m_properNamespace) {
2100                 if (attribute.name == L"src") {
2101                     m_box.m_boxSrc = attribute.value;
2102                 }
2103                 if (attribute.name == L"mouse-event") {
2104                     m_box.m_boxMouseEvent = attribute.value;
2105                 }
2106                 if (attribute.name == L"touch-effect") {
2107                     m_box.m_boxTouchEffect = attribute.value;
2108                 }
2109             }
2110         }
2111
2112         virtual void Accept(const Element& element)
2113         {
2114             if (element.ns ==
2115                 ConfigurationNamespace::TizenWebAppNamespaceName)
2116             {
2117                 m_properNamespace = true;
2118             }
2119         }
2120
2121         virtual void Accept(const Text& /*text*/)
2122         {}
2123
2124         virtual void Verify()
2125         {
2126             if (m_box.m_boxSrc.empty()) {
2127                 ThrowMsg(Exception::ParseError,
2128                     "src attribute of box-content element is mandatory - ignoring");
2129             }
2130
2131             if (m_box.m_boxMouseEvent.empty() || CheckIfNotTrueNorFalse(m_box.m_boxMouseEvent)) {
2132                 m_box.m_boxMouseEvent = L"false"; // default value
2133             }
2134
2135             if (m_box.m_boxTouchEffect.empty() || CheckIfNotTrueNorFalse(m_box.m_boxTouchEffect)) {
2136                 m_box.m_boxTouchEffect = L"true"; // default value
2137             }
2138
2139             if (m_box.m_boxSize.empty()) {
2140                 ThrowMsg(Exception::ParseError,
2141                     "box-size element of box-content element not found - ignoring");
2142             }
2143
2144             if (!m_data.m_boxInfo.m_boxSrc.empty()) {
2145                 ThrowMsg(Exception::ParseError, "<tizen:box-content> element must occur exactly 1 time");
2146             }
2147
2148             m_data.m_boxInfo = m_box;
2149         }
2150
2151         explicit BoxContentParser(ConfigParserData::LiveboxInfo& data) :
2152             ElementParser(),
2153             m_properNamespace(false),
2154             m_data(data)
2155         {}
2156
2157         ElementParserPtr OnBoxSizeElement()
2158         {
2159             return ElementParserPtr(new BoxSizeParser(m_box));
2160         }
2161
2162         ElementParserPtr OnPdElement()
2163         {
2164             return ElementParserPtr(new PdParser(m_box));
2165         }
2166
2167       private:
2168         bool m_properNamespace;
2169         ConfigParserData::LiveboxInfo& m_data;
2170         ConfigParserData::LiveboxInfo::BoxContentInfo m_box;
2171     };
2172
2173     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2174                                         const DPL::String& name)
2175     {
2176         if (name == L"box-label") {
2177             return std::bind(&AppWidgetParser::OnBoxLabelElement, this);
2178         } else if (name == L"box-icon") {
2179             return std::bind(&AppWidgetParser::OnBoxIconElement, this);
2180         } else if (name == L"box-content") {
2181             return std::bind(&AppWidgetParser::OnBoxContentElement, this);
2182         } else {
2183             return &IgnoringParser::Create; //ignore unknown according to w3c
2184         }
2185     }
2186
2187     virtual void Accept(const XmlAttribute& attribute)
2188     {
2189         if (m_properNamespace) {
2190             if (attribute.name == L"id") {
2191                 m_liveboxId = attribute.value;
2192             } else if (attribute.name == L"primary") {
2193                 m_primary = attribute.value;
2194             } else if (attribute.name == L"auto-launch") {
2195                 m_autoLaunch = attribute.value;
2196             } else if (attribute.name == L"update-period") {
2197                 m_updatePeriod = attribute.value;
2198             } else if (attribute.name == L"type") {
2199                 m_type = attribute.value;
2200             }
2201         }
2202     }
2203
2204     virtual void Accept(const Element& element)
2205     {
2206         if (element.ns ==
2207             ConfigurationNamespace::TizenWebAppNamespaceName)
2208         {
2209             m_properNamespace = true;
2210         }
2211     }
2212
2213     virtual void Accept(const Text& /*text*/)
2214     {}
2215
2216     virtual void Verify()
2217     {
2218         if (m_liveboxId.empty()) {
2219             ThrowMsg(Exception::ParseError,
2220                  "app-widget element must have id attribute");
2221         }
2222         else
2223         {
2224             pcrecpp::RE re(REGEXP_ID_STRING.c_str());
2225             if (!re.FullMatch(DPL::ToUTF8String(m_liveboxId)))
2226             {
2227                 ThrowMsg(Exception::ParseError,
2228                      "invalid format of app-widget id attribute");
2229             }
2230         }
2231
2232         if (m_primary.empty() || CheckIfNotTrueNorFalse(m_primary))
2233         {
2234             m_primary = L"true"; // default value
2235         }
2236
2237         if (!m_updatePeriod.empty())
2238         {
2239             char * endptr;
2240             errno = 0;
2241             std::string tempStr = DPL::ToUTF8String(m_updatePeriod);
2242
2243             //set standard locale to fix decimal point mark - '.'
2244             std::string currentLocale = setlocale(LC_NUMERIC, NULL);
2245             if (NULL == setlocale(LC_NUMERIC, "C"))
2246                 _W("Failed to change locale to \"C\"");
2247             double updatePeriod = strtod(tempStr.c_str(), &endptr);
2248
2249             //go back to previous locale
2250             if (NULL == setlocale(LC_NUMERIC, currentLocale.c_str()))
2251                 _W("Failed to set previous locale");
2252
2253             if ((errno == ERANGE && (updatePeriod == -HUGE_VAL || updatePeriod == HUGE_VAL))
2254                     || *endptr != '\0') {
2255                 ThrowMsg(Exception::ParseError,
2256                     "update-period attribute of app-widget element should be a number - ignoring. current value: " << m_updatePeriod);
2257             } else if (updatePeriod < 1800.0) {
2258                 _D("update-period attribute of app-widget element shouldn't be less than 1800.0 - changed to 1800 from value: %ls", m_updatePeriod.c_str());
2259                 m_updatePeriod = L"1800.0";
2260             }
2261         }
2262
2263         if (m_autoLaunch.empty() || CheckIfNotTrueNorFalse(m_autoLaunch))
2264         {
2265             m_autoLaunch = L"false"; // default value
2266         }
2267
2268         if(m_livebox.m_label.empty()) {
2269             ThrowMsg(Exception::ParseError,
2270                 "box-label element of app-widget element not found - ignoring");
2271         }
2272
2273         if(!m_boxContentFound) {
2274             ThrowMsg(Exception::ParseError,
2275                 "box-content element of app-widget element not found - ignoring");
2276         }
2277
2278         m_livebox.m_liveboxId = m_liveboxId;
2279         m_livebox.m_primary = m_primary;
2280         m_livebox.m_autoLaunch = m_autoLaunch;
2281         m_livebox.m_updatePeriod = m_updatePeriod;
2282         m_livebox.m_type = m_type;
2283
2284         m_data.m_livebox.push_back(m_livebox);
2285     }
2286
2287     explicit AppWidgetParser(ConfigParserData& data) :
2288         ElementParser(),
2289         m_data(data),
2290         m_properNamespace(false),
2291         m_boxContentFound(false)
2292     {
2293         m_livebox = ConfigParserData::LiveboxInfo();
2294     }
2295
2296     ElementParserPtr OnBoxLabelElement()
2297     {
2298
2299         return ElementParserPtr(new BoxLabelParser(m_livebox));
2300     }
2301
2302     ElementParserPtr OnBoxIconElement()
2303     {
2304         return ElementParserPtr(new BoxIconParser(m_livebox));
2305     }
2306
2307     ElementParserPtr OnBoxContentElement()
2308     {
2309         m_boxContentFound = true;
2310         return ElementParserPtr(new BoxContentParser(m_livebox));
2311     }
2312
2313   private:
2314     static std::string REGEXP_ID_STRING;
2315     ConfigParserData& m_data;
2316     ConfigParserData::LiveboxInfo m_livebox;
2317     DPL::String m_liveboxId;
2318     DPL::String m_primary;
2319     DPL::String m_autoLaunch;
2320     DPL::String m_updatePeriod;
2321     DPL::String m_type;
2322     bool m_properNamespace;
2323     bool m_boxContentFound;
2324
2325     static bool CheckIfNotTrueNorFalse(const DPL::String &stringToCheck)
2326     {
2327         return stringToCheck.compare(L"true") != 0 && stringToCheck.compare(L"false") != 0;
2328     }
2329 };
2330
2331 std::string AppWidgetParser::REGEXP_ID_STRING = std::string(ApplicationParser::REGEXP_ID) + "\\.[0-9A-Za-z]+";
2332 #endif
2333
2334 class AllowNavigationParser : public ElementParser
2335 {
2336   public:
2337     AllowNavigationParser(ConfigParserData& data) :
2338       ElementParser(),
2339       m_data(data),
2340       m_properNamespace(false)
2341     {}
2342
2343     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2344                                         const DPL::String& /*name*/)
2345     {
2346         return &IgnoringParser::Create; //ignore unknown according to w3c
2347     }
2348
2349     virtual void Accept(const Element& element)
2350     {
2351         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2352             m_properNamespace = true;
2353         }
2354     }
2355
2356     virtual void Accept(const Text& text)
2357     {
2358         if (m_properNamespace)
2359         {
2360             m_origin = text.value;
2361         }
2362     }
2363
2364     virtual void Accept(const XmlAttribute& /*attribute*/)
2365     {
2366     }
2367
2368     virtual void Verify()
2369     {
2370         if (m_data.allowNavigationEncountered || !m_properNamespace)
2371         {
2372             return;
2373         }
2374         m_data.allowNavigationEncountered = true;
2375
2376         if (!m_origin) {
2377             _W("data is empty");
2378             return;
2379         }
2380
2381         char* data = strdup(DPL::ToUTF8String(*m_origin).c_str());
2382         char* saveptr = NULL;
2383         char* ptr = strtok_r(data," \n\r\t", &saveptr);
2384         while (ptr != NULL) {
2385             std::string origin = ptr;
2386             ptr = strtok_r(NULL," \n\r\t", &saveptr);
2387             if(origin == "*") {
2388                 ConfigParserData::AllowNavigationInfo info(L"*", L"*");
2389                 m_data.allowNavigationInfoList.push_back(info);
2390                 continue;
2391             }
2392
2393             std::unique_ptr<iri_t, decltype(&iri_destroy)> iri(iri_parse(origin.c_str()), iri_destroy);
2394             if (!iri->host || strlen(iri->host) == 0) {
2395                 // input origin should has schem and host
2396                 // in case of file scheme path is filled
2397                 // "http://"
2398                 _W("input origin isn't verified");
2399                 continue;
2400             }
2401             DPL::String scheme = L"*";
2402             if (iri->scheme && strlen(iri->scheme) != 0) {
2403                 scheme = DPL::FromUTF8String(iri->scheme);
2404             }
2405             ConfigParserData::AllowNavigationInfo info(
2406                 scheme,
2407                 DPL::FromUTF8String(iri->host));
2408             m_data.allowNavigationInfoList.push_back(info);
2409         }
2410         free(data);
2411     }
2412
2413   private:
2414     DPL::OptionalString m_origin;
2415     ConfigParserData& m_data;
2416     bool m_properNamespace;
2417 };
2418
2419 class CspParser : public ElementParser
2420 {
2421   public:
2422     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2423                                         const DPL::String& /*name*/)
2424     {
2425         return &IgnoringParser::Create; //ignore unknown according to w3c
2426     }
2427
2428     CspParser(ConfigParserData& data) :
2429         ElementParser(),
2430         m_data(data),
2431         m_properNamespace(false)
2432     {}
2433
2434     virtual void Accept(const Element& element)
2435     {
2436         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2437             m_properNamespace = true;
2438         }
2439     }
2440
2441     virtual void Accept(const XmlAttribute& /*attribute*/)
2442     {}
2443
2444     virtual void Accept(const Text& text)
2445     {
2446         if (m_properNamespace) {
2447             m_policy = text.value;
2448         }
2449     }
2450
2451     virtual void Verify()
2452     {
2453         if (m_data.cspPolicyEncountered) {
2454             return;
2455         }
2456         m_data.cspPolicyEncountered = true;
2457
2458         if (!!m_policy) {
2459             m_data.cspPolicy = *m_policy;
2460         }
2461     }
2462
2463   private:
2464     ConfigParserData& m_data;
2465     bool m_properNamespace;
2466     DPL::OptionalString m_policy;
2467 };
2468
2469 class CspReportOnlyParser : public ElementParser
2470 {
2471   public:
2472     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2473                                         const DPL::String& /*name*/)
2474     {
2475         return &IgnoringParser::Create; //ignore unknown according to w3c
2476     }
2477
2478     CspReportOnlyParser(ConfigParserData& data) :
2479         ElementParser(),
2480         m_data(data),
2481         m_properNamespace(false)
2482     {}
2483
2484     virtual void Accept(const Element& element)
2485     {
2486         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2487             m_properNamespace = true;
2488         }
2489     }
2490
2491     virtual void Accept(const XmlAttribute& /*attribute*/)
2492     {}
2493
2494     virtual void Accept(const Text& text)
2495     {
2496         if (m_properNamespace) {
2497             m_policy = text.value;
2498         }
2499     }
2500
2501     virtual void Verify()
2502     {
2503         if (m_data.cspPolicyReportOnlyEncountered) {
2504             return;
2505         }
2506         m_data.cspPolicyReportOnlyEncountered = true;
2507
2508         if (!!m_policy) {
2509             m_data.cspPolicyReportOnly = *m_policy;
2510         }
2511     }
2512
2513   private:
2514     ConfigParserData& m_data;
2515     bool m_properNamespace;
2516     DPL::OptionalString m_policy;
2517 };
2518
2519 class AccountParser : public ElementParser
2520 {
2521   public:
2522       struct IconParser : public ElementParser
2523     {
2524         public:
2525             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2526                     const DPL::String& /*name*/)
2527             {
2528                 return &IgnoringParser::Create; //ignore unknown according to w3c
2529             }
2530
2531             virtual void Accept(const Text& text)
2532             {
2533                 if (text.value == L"") {
2534                     return;
2535                 }
2536                 m_value = text.value;
2537             }
2538
2539             virtual void Accept(const Element& /*element*/)
2540             {}
2541
2542             virtual void Accept(const XmlAttribute& attribute)
2543             {
2544                 if (attribute.name == L"section") {
2545                     if (attribute.value == L"Account") {
2546                         m_type = ConfigParserData::IconSectionType::DefaultIcon;
2547                     } else if (attribute.value == L"AccountSmall") {
2548                         m_type = ConfigParserData::IconSectionType::SmallIcon;
2549                     }
2550                 }
2551             }
2552
2553             virtual void Verify()
2554             {
2555                 if (!m_value || *m_value == L"") {
2556                     return;
2557                 }
2558
2559                 std::pair<ConfigParserData::IconSectionType, DPL::String> icon;
2560                 icon.first = m_type;
2561                 icon.second = *m_value;
2562
2563                 m_data.m_iconSet.insert(icon);
2564             }
2565
2566             IconParser(ConfigParserData::AccountProvider& data) :
2567                 ElementParser(),
2568                 m_properNamespace(false),
2569                 m_type(ConfigParserData::DefaultIcon),
2570                 m_data(data)
2571         {}
2572
2573         private:
2574             bool m_properNamespace;
2575             ConfigParserData::IconSectionType m_type;
2576             ConfigParserData::AccountProvider& m_data;
2577             DPL::OptionalString m_value;
2578     };
2579
2580       struct DisplayNameParser : public ElementParser
2581     {
2582         public:
2583             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2584                     const DPL::String& /*name*/)
2585             {
2586                 return &IgnoringParser::Create; //ignore unknown according to w3c
2587             }
2588
2589             virtual void Accept(const Text& text)
2590             {
2591                 if (text.value == L"") {
2592                     return;
2593                 }
2594                 m_value = text.value;
2595             }
2596
2597             virtual void Accept(const Element& element)
2598             {
2599                 m_lang = element.lang;
2600                 m_value= L"";
2601             }
2602
2603             virtual void Accept(const XmlAttribute& /*attribute*/)
2604             {}
2605
2606             virtual void Verify()
2607             {
2608                 if (!m_value || *m_value == L"") {
2609                     return;
2610                 }
2611
2612                 std::pair<DPL::String, DPL::String> name;
2613                 name.first = *m_lang;
2614                 name.second = *m_value;
2615
2616                 m_data.m_displayNameSet.insert(name);
2617             }
2618
2619             DisplayNameParser(ConfigParserData::AccountProvider& data) :
2620                 ElementParser(),
2621                 m_properNamespace(false),
2622                 m_data(data)
2623         {}
2624
2625         private:
2626             bool m_properNamespace;
2627             DPL::OptionalString m_lang;
2628             DPL::OptionalString m_value;
2629             ConfigParserData::AccountProvider& m_data;
2630     };
2631
2632       struct CapabilityParser : public ElementParser
2633     {
2634         public:
2635             virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2636                     const DPL::String& /*name*/)
2637             {
2638                 return &IgnoringParser::Create; //ignore unknown according to w3c
2639             }
2640
2641             virtual void Accept(const Text& text)
2642             {
2643                 if (text.value == L"") {
2644                     return;
2645                 }
2646                 m_value = text.value;
2647             }
2648
2649             virtual void Accept(const Element& /*element*/)
2650             {}
2651
2652             virtual void Accept(const XmlAttribute& /*attribute*/)
2653             {}
2654
2655             virtual void Verify()
2656             {
2657                 if (!m_value || *m_value == L"") {
2658                     return;
2659                 }
2660                 m_data.m_capabilityList.push_back(*m_value);
2661             }
2662
2663             CapabilityParser(ConfigParserData::AccountProvider& data) :
2664                 ElementParser(),
2665                 m_properNamespace(false),
2666                 m_data(data)
2667         {}
2668
2669         private:
2670             bool m_properNamespace;
2671             DPL::OptionalString m_value;
2672             ConfigParserData::AccountProvider& m_data;
2673     };
2674       virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2675               const DPL::String& name)
2676       {
2677           if (name == L"icon") {
2678               return std::bind(&AccountParser::OnIconElement, this);
2679           } else if (name == L"display-name") {
2680               return std::bind(&AccountParser::OnDisplayNameElement, this);
2681           } else if (name == L"capability") {
2682               return std::bind(&AccountParser::OnCapabilityElement, this);
2683           } else {
2684               return &IgnoringParser::Create; //ignore unknown according to w3c
2685           }
2686       }
2687
2688       virtual void Accept(const Text& /*text*/)
2689       {}
2690
2691       virtual void Accept(const Element& /*element*/)
2692       {}
2693
2694       virtual void Accept(const XmlAttribute& attribute)
2695       {
2696           if (attribute.name == L"multiple-account-support") {
2697               if (attribute.value == L"true") {
2698                   m_account.m_multiAccountSupport = true;
2699               }
2700           }
2701       }
2702
2703       virtual void Verify()
2704       {
2705       }
2706
2707       ElementParserPtr OnIconElement()
2708       {
2709           return ElementParserPtr(new IconParser(m_account));
2710       }
2711
2712       ElementParserPtr OnDisplayNameElement()
2713       {
2714           return ElementParserPtr(new DisplayNameParser(m_account));
2715       }
2716
2717       ElementParserPtr OnCapabilityElement()
2718       {
2719           return ElementParserPtr(new CapabilityParser(m_account));
2720       }
2721
2722       AccountParser(ConfigParserData& data) :
2723           ElementParser(),
2724           m_properNamespace(false),
2725           m_multiSupport(false),
2726           m_data(data),
2727           m_account(data.accountProvider)
2728     {
2729     }
2730
2731   private:
2732       bool m_properNamespace;
2733       bool m_multiSupport;
2734       ConfigParserData& m_data;
2735       ConfigParserData::AccountProvider& m_account;
2736 };
2737
2738 class MetadataParser : public ElementParser
2739 {
2740   public:
2741     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2742                                         const DPL::String& /*name*/)
2743     {
2744         return &IgnoringParser::Create; //ignore unknown according to w3c
2745     }
2746
2747     virtual void Accept(const XmlAttribute& attribute)
2748     {
2749         if (m_properNamespace) {
2750             if (attribute.name == L"key") {
2751                 m_key = attribute.value;
2752             } else if (attribute.name == L"value") {
2753                 m_value = attribute.value;
2754             }
2755         }
2756     }
2757
2758     virtual void Accept(const Element& element)
2759     {
2760         if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
2761             m_properNamespace = true;
2762         }
2763     }
2764
2765     virtual void Accept(const Text& /*text*/)
2766     {
2767         ThrowMsg(Exception::ParseError, "param element must be empty");
2768     }
2769
2770     virtual void Verify()
2771     {
2772         if (!m_key) {
2773             _W("metadata element must have key attribute");
2774             return;
2775         }
2776 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
2777         NormalizeString(m_key, MAX_NAME_KEY_LENGTH, true);
2778         NormalizeString(m_value, MAX_NAME_KEY_VALUE_LENGTH, true);
2779 #else
2780         NormalizeString(m_key);
2781         NormalizeString(m_value);
2782 #endif
2783         ConfigParserData::Metadata metaData(m_key, m_value);
2784         FOREACH(it, m_data.metadataList) {
2785             if (!DPL::StringCompare(*it->key, *m_key)) {
2786                 _E("Key isn't unique");
2787                 return;
2788             }
2789         }
2790         m_data.metadataList.push_back(metaData);
2791     }
2792
2793     MetadataParser(ConfigParserData& data) :
2794         ElementParser(),
2795         m_data(data),
2796         m_properNamespace(false)
2797     {}
2798
2799   private:
2800     DPL::OptionalString m_key;
2801     DPL::OptionalString m_value;
2802     ConfigParserData& m_data;
2803     bool m_properNamespace;
2804 };
2805
2806 #ifdef IME_ENABLED
2807 class ImeParser : public ElementParser
2808 {
2809   public:
2810     struct UuidParser : public ElementParser
2811     {
2812       public:
2813         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2814                                             const DPL::String& /*name*/)
2815         {
2816             return &IgnoringParser::Create;
2817         }
2818
2819         virtual void Accept(const XmlAttribute& /*attribute*/)
2820         {}
2821
2822         virtual void Accept(const Element& /*element*/)
2823         {}
2824
2825         virtual void Accept(const Text& text)
2826         {
2827             if (m_uuid.empty()) {
2828                 m_uuid = text.value;
2829             } else {
2830                 m_uuid += text.value;
2831             }
2832         }
2833
2834         virtual void Verify()
2835         {
2836             if (m_uuid.empty()) {
2837                 ThrowMsg(Exception::ParseError, "uuid text is empty");
2838             }
2839             uuid_t uu;
2840             if (uuid_parse(DPL::ToUTF8String(m_uuid).c_str(), uu)){
2841                 ThrowMsg(Exception::ParseError, "invalid uuid");
2842             }
2843             m_imeAppInfo.uuid = m_uuid;
2844         }
2845
2846         UuidParser(ConfigParserData::ImeAppInfo& data) :
2847             ElementParser(),
2848             m_imeAppInfo(data)
2849         {}
2850
2851       private:
2852           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2853           DPL::String m_uuid;
2854     };
2855
2856     struct LanguagesParser : public ElementParser
2857     {
2858       public:
2859         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2860                                             const DPL::String& name)
2861         {
2862             if (name == L"language") {
2863                 return std::bind(&LanguagesParser::OnLanguageElement, this);
2864             } else {
2865                 return &IgnoringParser::Create;
2866             }
2867         }
2868
2869         virtual void Accept(const XmlAttribute& /*attribute*/)
2870         {}
2871
2872         virtual void Accept(const Element& /*element*/)
2873         {}
2874
2875         virtual void Accept(const Text& /*text*/)
2876         {
2877             ThrowMsg(Exception::ParseError, "param element must be empty");
2878         }
2879
2880         virtual void Verify()
2881         {}
2882
2883         LanguagesParser(ConfigParserData::ImeAppInfo& data) :
2884             ElementParser(),
2885             m_imeAppInfo(data)
2886         {}
2887
2888         ElementParserPtr OnLanguageElement()
2889         {
2890             return ElementParserPtr(new LanguageParser(m_imeAppInfo));
2891         }
2892
2893       private:
2894           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2895     };
2896
2897     struct LanguageParser : public ElementParser
2898     {
2899       public:
2900         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2901                                                     const DPL::String& /*name*/)
2902         {
2903             return &IgnoringParser::Create;
2904         }
2905
2906         virtual void Accept(const XmlAttribute& /*attribute*/)
2907         {}
2908
2909         virtual void Accept(const Element& /*element*/)
2910         {}
2911
2912         virtual void Accept(const Text& text)
2913         {
2914             if (m_language.empty()) {
2915                 m_language = text.value;
2916             } else {
2917                 m_language += text.value;
2918             }
2919         }
2920
2921         virtual void Verify()
2922         {
2923             if (m_language.empty()) {
2924                 ThrowMsg(Exception::ParseError, "language text is empty");
2925             }
2926             m_imeAppInfo.languageList.insert(m_language);
2927         }
2928
2929         LanguageParser(ConfigParserData::ImeAppInfo& data) :
2930             ElementParser(),
2931             m_imeAppInfo(data)
2932         {}
2933
2934       private:
2935           ConfigParserData::ImeAppInfo& m_imeAppInfo;
2936           DPL::String m_language;
2937     };
2938
2939     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
2940                                         const DPL::String& name)
2941     {
2942         if (name == L"uuid") {
2943             m_uuidTagCount++;
2944             return std::bind(&ImeParser::OnUuidElement, this);
2945         } else if (name == L"languages") {
2946             m_languagesTagCount++;
2947             return std::bind(&ImeParser::OnLanguagesElement, this);
2948         } else {
2949             return &IgnoringParser::Create;
2950         }
2951     }
2952
2953     virtual void Accept(const Text& /*text*/)
2954     {
2955         ThrowMsg(Exception::ParseError, "param element must be empty");
2956     }
2957
2958     virtual void Accept(const Element& /*element*/)
2959     {}
2960
2961     virtual void Accept(const XmlAttribute& /*attribute*/)
2962     {}
2963
2964     virtual void Verify()
2965     {
2966         if (m_imeAppInfo.uuid.empty()) {
2967             ThrowMsg(Exception::ParseError, "ime element must have uuid element");
2968             return;
2969         }
2970
2971         if (m_imeAppInfo.languageList.empty()) {
2972             ThrowMsg(Exception::ParseError, "ime element must have language element");
2973             return;
2974         }
2975
2976         if (m_uuidTagCount > 1) {
2977             ThrowMsg(Exception::ParseError, "As per Tizen 2.3 wrt core spec, occurence of uuid must be 1");
2978         }
2979
2980         if (m_languagesTagCount > 1) {
2981             ThrowMsg(Exception::ParseError, "As per Tizen 2.3 wrt core spec, occurence of languages must be 1");
2982         }
2983         m_data.imeAppInfoList.push_back(m_imeAppInfo);
2984     }
2985
2986     ImeParser(ConfigParserData& data) :
2987         ElementParser(),
2988         m_data(data),
2989         m_imeAppInfo(),
2990         m_uuidTagCount(0),
2991         m_languagesTagCount(0)
2992     {}
2993
2994     ElementParserPtr OnLanguagesElement()
2995     {
2996         return ElementParserPtr(new LanguagesParser(m_imeAppInfo));
2997     }
2998
2999     ElementParserPtr OnUuidElement()
3000     {
3001         return ElementParserPtr(new UuidParser(m_imeAppInfo));
3002     }
3003
3004   private:
3005     ConfigParserData& m_data;
3006     ConfigParserData::ImeAppInfo m_imeAppInfo;
3007     unsigned char m_uuidTagCount;
3008     unsigned char m_languagesTagCount;
3009 };
3010 #endif
3011
3012 #ifdef SERVICE_ENABLED
3013 class ServiceAppParser : public ElementParser
3014 {
3015   public:
3016     struct ServiceContentParser : public ElementParser
3017     {
3018         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
3019                                             const DPL::String& /*name*/)
3020         {
3021             return &IgnoringParser::Create; //ignore unknown according to w3c
3022         }
3023
3024         virtual void Accept(const XmlAttribute& attribute)
3025         {
3026            if (attribute.name == L"src") {
3027                m_src = attribute.value;
3028            }
3029         }
3030
3031         virtual void Accept(const Element& /*element*/)
3032         {}
3033
3034         virtual void Accept(const Text& /*text*/)
3035         {
3036             ThrowMsg(Exception::ParseError, "param element must be empty");
3037         }
3038
3039         virtual void Verify()
3040         {
3041             if (m_src.empty()) {
3042                 ThrowMsg(Exception::ParseError, "src attribute of content element is mandatory");
3043             }
3044
3045             if (!m_serviceAppInfo.serviceContent.empty()) {
3046                 ThrowMsg(Exception::ParseError, "content element occurs more than 1 time");
3047             }
3048             m_serviceAppInfo.serviceContent = m_src;
3049         }
3050
3051         explicit ServiceContentParser(ConfigParserData::ServiceAppInfo& data) :
3052             ElementParser(),
3053             m_serviceAppInfo(data)
3054         {}
3055
3056       private:
3057         DPL::String m_src;
3058         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3059     };
3060
3061     struct ServiceNameParser : public ElementParser
3062     {
3063         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
3064                                             const DPL::String& /*name*/)
3065         {
3066             return &IgnoringParser::Create;
3067         }
3068
3069         virtual void Accept(const XmlAttribute& attribute)
3070         {
3071             m_lang = attribute.lang;
3072         }
3073
3074         virtual void Accept(const Element& /*element*/)
3075         {}
3076
3077         virtual void Accept(const Text& text)
3078         {
3079             m_name = text.value;
3080         }
3081
3082         virtual void Verify()
3083         {
3084             ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang];
3085             if (!data.name) {
3086                 if (!!m_name) {
3087 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3088                     NormalizeString(m_name, MAX_ATTR_ELEMENT_LENGTH, true);
3089 #else
3090                     NormalizeString(m_name);
3091 #endif
3092                 }
3093                 data.name = m_name;
3094             }
3095         }
3096
3097         ServiceNameParser(ConfigParserData::ServiceAppInfo& data) :
3098             ElementParser(),
3099             m_serviceAppInfo(data)
3100         {}
3101
3102       private:
3103         DPL::String m_lang;
3104         DPL::OptionalString m_name;
3105         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3106     };
3107
3108     struct ServiceIconParser : public ElementParser
3109     {
3110         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
3111                                             const DPL::String& /*name*/)
3112         {
3113             return &IgnoringParser::Create;
3114         }
3115
3116         virtual void Accept(const XmlAttribute& attribute)
3117         {
3118             if (attribute.name == L"src") {
3119                 m_icon.src = attribute.value;
3120             }
3121             else if (attribute.name == L"width") {
3122                 m_icon.width = ParseSizeAttributeValue(attribute.value);
3123             }
3124             else if (attribute.name == L"height") {
3125                 m_icon.height = ParseSizeAttributeValue(attribute.value);
3126             }
3127         }
3128
3129         virtual void Accept(const Element& /*element*/)
3130         {}
3131
3132         virtual void Accept(const Text& /*text*/)
3133         {
3134             ThrowMsg(Exception::ParseError, "param element must be empty");
3135         }
3136
3137         virtual void Verify()
3138         {
3139             if (m_icon.src.empty()) {
3140                 ThrowMsg(Exception::ParseError,
3141                     "src attribute of icon element is mandatory - ignoring");
3142             }
3143              m_serviceAppInfo.m_iconsList.push_back(m_icon);
3144         }
3145
3146         explicit ServiceIconParser(ConfigParserData::ServiceAppInfo& data) :
3147             ElementParser(),
3148             m_icon(L""),
3149             m_serviceAppInfo(data)
3150         {}
3151
3152     private:
3153       ConfigParserData::Icon m_icon;
3154       ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3155
3156       static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
3157       {
3158           DPL::OptionalString normalizedValue = value;
3159           NormalizeString(normalizedValue);
3160           if (!(*normalizedValue).empty()) {
3161               char* reterr = NULL;
3162               errno = 0;
3163               long int valueInt = strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
3164               if (errno != 0 || std::string(reterr) == DPL::ToUTF8String(value) || valueInt <= 0) {
3165                   return DPL::OptionalInt();
3166               } else {
3167                   return valueInt;
3168               }
3169           }
3170           return DPL::OptionalInt();
3171       }
3172     };
3173
3174     struct ServiceDescriptionParser : public ElementParser
3175     {
3176         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, const DPL::String& /*name*/)
3177         {
3178             return &IgnoringParser::Create; //ignore unknown according to w3c
3179         }
3180
3181         virtual void Accept(const XmlAttribute& attribute)
3182         {
3183             m_lang = attribute.lang;
3184         }
3185
3186         virtual void Accept(const Element& /*element*/)
3187         {}
3188
3189         virtual void Accept(const Text& text)
3190         {
3191             m_description = text.value;
3192         }
3193
3194         virtual void Verify()
3195         {
3196             ConfigParserData::LocalizedData& data = m_serviceAppInfo.m_localizedDataSet[m_lang];
3197             if (!data.description) {
3198                 data.description = m_description;
3199             }
3200         }
3201
3202         ServiceDescriptionParser(ConfigParserData::ServiceAppInfo& data) :
3203             ElementParser(),
3204             m_serviceAppInfo(data)
3205         {}
3206
3207     private:
3208         DPL::String m_lang;
3209         DPL::OptionalString m_description;
3210         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3211     };
3212
3213     struct ServiceMetadataParser : public ElementParser
3214     {
3215         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, const DPL::String& /*name*/)
3216         {
3217             return &IgnoringParser::Create; //ignore unknown according to w3c
3218         }
3219
3220         virtual void Accept(const XmlAttribute& attribute)
3221         {
3222             if (attribute.name == L"key") {
3223                 m_key = attribute.value;
3224             } else if (attribute.name == L"value") {
3225                 m_value = attribute.value;
3226             }
3227         }
3228
3229         virtual void Accept(const Element& /*element*/)
3230         {}
3231
3232         virtual void Accept(const Text& /*text*/)
3233         {
3234             ThrowMsg(Exception::ParseError, "param element must be empty");
3235         }
3236
3237         virtual void Verify()
3238         {
3239             if (!m_key) {
3240             _W("metadata element must have key attribute");
3241             return;
3242             }
3243 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3244             NormalizeString(m_key, MAX_NAME_KEY_LENGTH, true);
3245             NormalizeString(m_value, MAX_NAME_KEY_VALUE_LENGTH, true);
3246 #else
3247             NormalizeString(m_key);
3248             NormalizeString(m_value);
3249 #endif
3250             ConfigParserData::Metadata metaData(m_key, m_value);
3251             FOREACH(it, m_serviceAppInfo.m_metadataList) {
3252                 if (!DPL::StringCompare(*it->key, *m_key)) {
3253                     _E("Key isn't unique");
3254                     return;
3255                 }
3256             }
3257             m_serviceAppInfo.m_metadataList.push_back(metaData);
3258         }
3259
3260         ServiceMetadataParser(ConfigParserData::ServiceAppInfo& data) :
3261             ElementParser(),
3262             m_serviceAppInfo(data)
3263         {}
3264
3265       private:
3266         DPL::OptionalString m_key;
3267         DPL::OptionalString m_value;
3268         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3269     };
3270
3271     struct ServiceCategoryParser : public ElementParser
3272     {
3273         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/, const DPL::String& /*name*/)
3274         {
3275             return &IgnoringParser::Create; //ignore unknown according to w3c
3276         }
3277
3278         virtual void Accept(const XmlAttribute& attribute)
3279         {
3280             if (attribute.name == L"name") {
3281                 if (attribute.value.size() > 0) {
3282                     m_name = attribute.value;
3283                 }
3284             }
3285         }
3286
3287         virtual void Accept(const Element& /*element*/)
3288         {}
3289
3290         virtual void Accept(const Text& /*text*/)
3291         {
3292             ThrowMsg(Exception::ParseError, "param element must be empty");
3293         }
3294
3295         virtual void Verify()
3296         {
3297             if (!m_name) {
3298                 _W("name attribute of category element is mandatory - ignoring");
3299                 return;
3300             }
3301
3302             if (m_serviceAppInfo.m_categoryList.find(*m_name) == m_serviceAppInfo.m_categoryList.end()) {
3303                 m_serviceAppInfo.m_categoryList.insert(*m_name);
3304             }
3305         }
3306
3307         ServiceCategoryParser(ConfigParserData::ServiceAppInfo& data) :
3308             ElementParser(),
3309             m_serviceAppInfo(data)
3310         {}
3311
3312       private:
3313         DPL::OptionalString m_name;
3314         ConfigParserData::ServiceAppInfo& m_serviceAppInfo;
3315     };
3316
3317     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
3318                                         const DPL::String& name)
3319     {
3320         if (name == L"content") {
3321             return std::bind(&ServiceAppParser::OnServiceContentElement, this);
3322         } else if (name == L"name") {
3323             return std::bind(&ServiceAppParser::OnServiceNameElement, this);
3324         } else if (name == L"icon") {
3325             return std::bind(&ServiceAppParser::OnServiceIconElement, this);
3326         } else if (name == L"description") {
3327             return std::bind(&ServiceAppParser::OnServiceDescriptionElement, this);
3328         } else if (name == L"metadata") {
3329             return std::bind(&ServiceAppParser::OnServiceMetadataElement, this);
3330         } else if (name == L"category") {
3331             return std::bind(&ServiceAppParser::OnServiceCategoryElement, this);
3332         } else {
3333             return &IgnoringParser::Create;
3334         }
3335     }
3336
3337     virtual void Accept(const Element& /*element*/)
3338     {}
3339
3340     virtual void Accept(const XmlAttribute& attribute)
3341     {
3342         if (attribute.name == L"id") {
3343             if (attribute.value.size() > 0) {
3344                 m_serviceId = attribute.value;
3345             }
3346         } else if (attribute.name == L"auto-restart") {
3347             if (attribute.value == L"true") {
3348                 m_autoRestart = true;
3349             } else if (attribute.value == L"false") {
3350                 m_autoRestart = false;
3351             } else {
3352                 ThrowMsg(Exception::ParseError, "Wrong boolean value");
3353             }
3354         } else if (attribute.name == L"on-boot") {
3355             if (attribute.value == L"true") {
3356                 m_onBoot = true;
3357             } else if (attribute.value == L"false") {
3358                 m_onBoot = false;
3359             } else {
3360                 ThrowMsg(Exception::ParseError, "Wrong boolean value");
3361             }
3362         }
3363     }
3364
3365     virtual void Accept(const Text& /*text*/)
3366     {
3367         ThrowMsg(Exception::ParseError, "param element must be empty");
3368     }
3369
3370     virtual void Verify()
3371     {
3372         FOREACH(it, m_data.settingsList) {
3373             if (it->m_name == L"encryption" && it->m_value == L"enable") {
3374                 ThrowMsg(Exception::ParseError, "Service application does not support application encryption");
3375             }
3376         }
3377
3378         if (m_serviceAppInfo.serviceContent.empty()) {
3379             ThrowMsg(Exception::ParseError, "service element must have content element");
3380         }
3381
3382         if (m_serviceId.empty()) {
3383             ThrowMsg(Exception::ParseError, "service attribute must have id attribute");
3384         }
3385
3386         m_serviceAppInfo.serviceId = m_serviceId;
3387
3388         m_serviceAppInfo.autoRestart = m_autoRestart;
3389
3390         m_serviceAppInfo.onBoot = m_onBoot;
3391
3392         m_data.serviceAppInfoList.push_back(m_serviceAppInfo);
3393     }
3394
3395     ServiceAppParser(ConfigParserData& data) :
3396         ElementParser(),
3397         m_autoRestart(false),
3398         m_onBoot(false),
3399         m_data(data),
3400         m_serviceAppInfo()
3401     {}
3402
3403     ElementParserPtr OnServiceContentElement()
3404     {
3405         return ElementParserPtr(new ServiceContentParser(m_serviceAppInfo));
3406     }
3407
3408     ElementParserPtr OnServiceNameElement()
3409     {
3410         return ElementParserPtr(new ServiceNameParser(m_serviceAppInfo));
3411     }
3412
3413     ElementParserPtr OnServiceIconElement()
3414     {
3415         return ElementParserPtr(new ServiceIconParser(m_serviceAppInfo));
3416     }
3417
3418     ElementParserPtr OnServiceDescriptionElement()
3419     {
3420         return ElementParserPtr(new ServiceDescriptionParser(m_serviceAppInfo));
3421     }
3422
3423     ElementParserPtr OnServiceMetadataElement()
3424     {
3425         return ElementParserPtr(new ServiceMetadataParser(m_serviceAppInfo));
3426     }
3427
3428     ElementParserPtr OnServiceCategoryElement()
3429     {
3430         return ElementParserPtr(new ServiceCategoryParser(m_serviceAppInfo));
3431     }
3432
3433   private:
3434     bool m_autoRestart;
3435     bool m_onBoot;
3436     DPL::String m_serviceId;
3437     ConfigParserData& m_data;
3438     ConfigParserData::ServiceAppInfo m_serviceAppInfo;
3439 };
3440 #endif
3441
3442 ElementParser::ActionFunc WidgetParser::GetElementParser(
3443     const DPL::String& /*ns*/,
3444     const DPL::String& name)
3445 {
3446     FuncMap::const_iterator it = m_map.find(name);
3447     if (it != m_map.end()) {
3448         return it->second;
3449     } else {
3450         return &IgnoringParser::Create; //ignore unknown according to w3c
3451     }
3452 }
3453
3454 WidgetParser::WidgetParser(ConfigParserData& data) :
3455     m_data(data),
3456     m_textDirection(Unicode::EMPTY)
3457 {
3458     m_map[L"name"] = std::bind(&WidgetParser::OnNameElement, this);
3459     m_map[L"access"] = std::bind(&WidgetParser::OnAccessElement, this);
3460     m_map[L"description"] = std::bind(&WidgetParser::OnDescriptionElement, this);
3461     m_map[L"author"] = std::bind(&WidgetParser::OnAuthorElement, this);
3462     m_map[L"license"] = std::bind(&WidgetParser::OnLicenseElement, this);
3463     m_map[L"icon"] = std::bind(&WidgetParser::OnIconElement, this);
3464     m_map[L"small-icon"] = std::bind(&WidgetParser::OnSmallIconElement, this);
3465     m_map[L"content"] = std::bind(&WidgetParser::OnContentElement, this);
3466     m_map[L"preference"] = std::bind(&WidgetParser::OnPreferenceElement, this);
3467     m_map[L"setting"] = std::bind(&WidgetParser::OnSettingElement, this);
3468     m_map[L"application"] = std::bind(&WidgetParser::OnApplicationElement, this);
3469 #ifdef IME_ENABLED
3470     m_map[L"ime"] = std::bind(&WidgetParser::OnImeElement, this);
3471 #endif
3472 #ifdef SERVICE_ENABLED
3473     m_map[L"service"] = std::bind(&WidgetParser::OnServiceAppElement, this);
3474 #endif
3475     m_map[L"splash"] = std::bind(&WidgetParser::OnSplashElement, this);
3476     m_map[L"background"] = std::bind(&WidgetParser::OnBackgroundElement, this);
3477     m_map[L"privilege"] = std::bind(&WidgetParser::OnPrivilegeElement, this);
3478     m_map[L"app-control"] = std::bind(&WidgetParser::OnAppControlElement, this);
3479     m_map[L"category"] = std::bind(&WidgetParser::OnCategoryElement, this);
3480     m_map[L"background-category"] = std::bind(&WidgetParser::OnBackgroundCategoryElement, this);
3481 #if USE(WEB_PROVIDER)
3482     m_map[L"app-widget"] = std::bind(&WidgetParser::OnAppWidgetElement, this);
3483 #endif
3484 #if ENABLE(CONTENT_SECURITY_POLICY)
3485     m_map[L"content-security-policy"] = std::bind(&WidgetParser::OnCspElement, this);
3486     m_map[L"content-security-policy-report-only"] = std::bind(&WidgetParser::OnCspReportOnlyElement, this);
3487 #endif
3488 #if ENABLE(ALLOW_NAVIGATION)
3489     m_map[L"allow-navigation"] = std::bind(&WidgetParser::OnAllowNavigationElement, this);
3490 #endif
3491     m_map[L"account"] = std::bind(&WidgetParser::OnAccountElement, this);
3492     m_map[L"metadata"] = std::bind(&WidgetParser::OnMetadataElement, this);
3493 }
3494
3495 ElementParserPtr WidgetParser::OnNameElement()
3496 {
3497     return ElementParserPtr(new NameParser(m_textDirection, m_data));
3498 }
3499
3500 ElementParserPtr WidgetParser::OnAccessElement()
3501 {
3502     return ElementParserPtr(new AccessParser(m_data));
3503 }
3504
3505 ElementParserPtr WidgetParser::OnDescriptionElement()
3506 {
3507     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
3508 }
3509
3510 ElementParserPtr WidgetParser::OnAuthorElement()
3511 {
3512     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
3513 }
3514
3515 ElementParserPtr WidgetParser::OnLicenseElement()
3516 {
3517     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
3518 }
3519
3520 ElementParserPtr WidgetParser::OnIconElement()
3521 {
3522     return ElementParserPtr(new IconParser(m_data));
3523 }
3524
3525 ElementParserPtr WidgetParser::OnSmallIconElement()
3526 {
3527     return ElementParserPtr(new IconParser(m_data, true));
3528 }
3529
3530 ElementParserPtr WidgetParser::OnContentElement()
3531 {
3532     return ElementParserPtr(new ContentParser(m_data));
3533 }
3534
3535 ElementParserPtr WidgetParser::OnPreferenceElement()
3536 {
3537     return ElementParserPtr(new PreferenceParser(m_data));
3538 }
3539
3540 ElementParserPtr WidgetParser::OnSettingElement()
3541 {
3542     return ElementParserPtr(new SettingParser(m_data));
3543 }
3544
3545 ElementParserPtr WidgetParser::OnApplicationElement()
3546 {
3547     return ElementParserPtr(new ApplicationParser(m_data));
3548 }
3549
3550 ElementParserPtr WidgetParser::OnSplashElement()
3551 {
3552     return ElementParserPtr(new SplashParser(m_data));
3553 }
3554
3555 ElementParserPtr WidgetParser::OnBackgroundElement()
3556 {
3557     return ElementParserPtr(new BackgroundParser(m_data));
3558 }
3559
3560 ElementParserPtr WidgetParser::OnPrivilegeElement()
3561 {
3562     return ElementParserPtr(new PrivilegeParser(m_data));
3563 }
3564
3565 ElementParserPtr WidgetParser::OnAppControlElement()
3566 {
3567     return ElementParserPtr(new AppControlParser(m_data));
3568 }
3569
3570 ElementParserPtr WidgetParser::OnCategoryElement()
3571 {
3572     return ElementParserPtr(new CategoryParser(m_data));
3573 }
3574
3575 ElementParserPtr WidgetParser::OnBackgroundCategoryElement()
3576 {
3577     return ElementParserPtr(new BackgroundCategoryParser(m_data));
3578 }
3579
3580 #if USE(WEB_PROVIDER)
3581 ElementParserPtr WidgetParser::OnAppWidgetElement()
3582 {
3583     return ElementParserPtr(new AppWidgetParser(m_data));
3584 }
3585 #endif
3586
3587 ElementParserPtr WidgetParser::OnCspElement()
3588 {
3589     return ElementParserPtr(new CspParser(m_data));
3590 }
3591
3592 ElementParserPtr WidgetParser::OnCspReportOnlyElement()
3593 {
3594     return ElementParserPtr(new CspReportOnlyParser(m_data));
3595 }
3596
3597 ElementParserPtr WidgetParser::OnAllowNavigationElement()
3598 {
3599     return ElementParserPtr(new AllowNavigationParser(m_data));
3600 }
3601
3602 ElementParserPtr WidgetParser::OnAccountElement()
3603 {
3604     return ElementParserPtr(new AccountParser(m_data));
3605 }
3606
3607 ElementParserPtr WidgetParser::OnMetadataElement()
3608 {
3609     return ElementParserPtr(new MetadataParser(m_data));
3610 }
3611
3612 #ifdef IME_ENABLED
3613 ElementParserPtr WidgetParser::OnImeElement()
3614 {
3615     return ElementParserPtr(new ImeParser(m_data));
3616 }
3617 #endif
3618
3619 #ifdef SERVICE_ENABLED
3620 ElementParserPtr WidgetParser::OnServiceAppElement()
3621 {
3622     return ElementParserPtr(new ServiceAppParser(m_data));
3623 }
3624 #endif
3625
3626 void WidgetParser::Accept(const Element& element)
3627 {
3628     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
3629         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
3630     {
3631         ThrowMsg(Exception::ParseError,
3632                  "Wrong xml namespace for widget element");
3633     }
3634 }
3635
3636 void WidgetParser::Accept(const Text& /*text*/)
3637 {
3638     ThrowMsg(Exception::ParseError, "widged element must be empty");
3639 }
3640
3641 void WidgetParser::Accept(const XmlAttribute& attribute)
3642 {
3643     if (attribute.name == L"id") {
3644         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
3645         //If may important tests starts to fail this test we will have
3646         //to consider commenting this test out again.
3647         if (iri.Validate()) {
3648             m_widgetId = attribute.value;
3649         } else {
3650             _W("Widget id validation failed: %ls", attribute.value.c_str());
3651         }
3652     } else if (attribute.name == L"version") {
3653         m_version = attribute.value;
3654     } else if (attribute.name == L"min-version") {
3655         _D("min-version attribute was found. Value: %ls", attribute.value.c_str());
3656         m_minVersion = attribute.value;
3657         m_data.minVersionRequired = m_minVersion;
3658     } else if (attribute.name == L"height") {
3659         DPL::OptionalString value = attribute.value;
3660         if (!(*value).empty()) {
3661 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3662             NormalizeString(value, MAX_ATTR_ELEMENT_LENGTH, true);
3663 #else
3664             NormalizeString(value);
3665 #endif
3666             std::string v = DPL::ToUTF8String(*value);
3667             unsigned char c = v.c_str()[0];
3668             if (isdigit(c)) {
3669                 int val = 0;
3670                 for (size_t i = 0; i < v.size(); ++i) {
3671                     c = v.c_str()[i];
3672                     if (isdigit(c)) {
3673                         val *= 10;
3674                         val += (c - '0');
3675                     } else {
3676                         break;
3677                     }
3678                 }
3679                 m_data.height = val;
3680             }
3681         }
3682     } else if (attribute.name == L"width") {
3683         DPL::OptionalString value = attribute.value;
3684         if (!(*value).empty()) {
3685 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3686             NormalizeString(value, MAX_ATTR_ELEMENT_LENGTH, true);
3687 #else
3688             NormalizeString(value);
3689 #endif
3690             std::string v = DPL::ToUTF8String(*value);
3691             unsigned char c = v.c_str()[0];
3692             if (c >= '0' && c <= '9') {
3693                 int val = 0;
3694                 for (size_t i = 0; i < v.size(); ++i) {
3695                     c = v.c_str()[i];
3696                     if (c >= '0' && c <= '9') {
3697                         val *= 10;
3698                         val += (c - '0');
3699                     } else {
3700                         break;
3701                     }
3702                 }
3703                 m_data.width = val;
3704             }
3705         }
3706     } else if (attribute.name == L"viewmodes") {
3707         DPL::Tokenize(attribute.value,
3708                       L" ",
3709                       std::inserter(m_windowModes,
3710                                     m_windowModes.end()),
3711                       true);
3712     } else if (attribute.name == L"dir") {
3713         m_textDirection = Unicode::ParseDirAttribute(attribute);
3714     } else if (L"defaultlocale" == attribute.name) {
3715         if (!m_defaultlocale) {
3716             m_defaultlocale = attribute.value;
3717         } else {
3718             _W("Ignoring subsequent default locale");
3719         }
3720         //Any other value consider as a namespace definition
3721     } else if (attribute.name == L"xmlns" || attribute.prefix == L"xmlns") {
3722         _D("Namespace domain: %ls", attribute.name.c_str());
3723         _D("Namespace value: %ls", attribute.value.c_str());
3724         m_nameSpaces[attribute.name] = attribute.value;
3725     } else {
3726         _E("Unknown attirbute: namespace=%ls, name=%ls, value=%ls",
3727             attribute.ns.c_str(), attribute.name.c_str(), attribute.value.c_str());
3728     }
3729 }
3730
3731 void WidgetParser::Verify()
3732 {
3733     if (m_data.imeAppInfoList.size() > 1) {
3734         ThrowMsg(Exception::ParseError, "ime element must not be more than one");
3735         return;
3736     } else if (m_data.imeAppInfoList.size() == 1) {
3737         if (m_data.categoryList.end() == m_data.categoryList.find(L"http://tizen.org/category/ime")) {
3738             ThrowMsg(Exception::ParseError,\
3739                 "<tizen:category name=\"http://tizen.org/category/ime\"/> should be defined to activate <tizen:ime>");
3740             return;
3741         }
3742     }
3743     FOREACH(mode, m_windowModes) {
3744         if (L"windowed" == *mode || L"floating" == *mode ||
3745             L"fullscreen" == *mode || L"maximized" == *mode ||
3746             L"minimized" == *mode)
3747         {
3748             m_data.windowModes.insert(*mode);
3749         }
3750     }
3751     if (!!m_widgetId) {
3752 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3753         NormalizeString(m_widgetId, MAX_ATTR_ELEMENT_LENGTH, true);
3754 #else
3755         NormalizeString(m_widgetId);
3756 #endif
3757         m_data.widget_id = m_widgetId;
3758     }
3759     if (!!m_version) {
3760 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3761         NormalizeString(m_version, MAX_ATTR_ELEMENT_LENGTH, true);
3762 #else
3763         NormalizeString(m_version);
3764 #endif
3765         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
3766         m_data.version = m_version;
3767     }
3768     if (!!m_minVersion) {
3769 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3770         NormalizeString(m_minVersion, MAX_ATTR_ELEMENT_LENGTH, true);
3771 #else
3772         NormalizeString(m_minVersion);
3773 #endif
3774         m_data.minVersionRequired = m_minVersion;
3775     }
3776     if (!!m_defaultlocale) {
3777 #if ENABLE(ELEMENT_ATTR_MAX_LENGTH)
3778         NormalizeString(m_defaultlocale, MAX_ATTR_ELEMENT_LENGTH, true);
3779 #else
3780         NormalizeString(m_defaultlocale);
3781 #endif
3782         std::string dl = DPL::ToUTF8String(*m_defaultlocale);
3783
3784         if (!LanguageSubtagRstTreeSingleton::Instance().
3785                 ValidateLanguageTag(dl)) {
3786             _W("Language tag: %s is not valid", dl.c_str());
3787             m_defaultlocale = DPL::OptionalString();
3788         } else {
3789             _D("Default locale found %s", dl.c_str());
3790         }
3791         m_data.defaultlocale = m_defaultlocale;
3792     }
3793     FOREACH(ns, m_nameSpaces) {
3794         m_data.nameSpaces.insert(ns->second);
3795     }
3796 }