Update wrt-installer_0.0.51
[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 #include "widget_parser.h"
28 #include "ignoring_parser.h"
29 #include "deny_all_parser.h"
30 #include <dpl/wrt-dao-ro/config_parser_data.h>
31 #include "libiriwrapper.h"
32 #include <dpl/utils/warp_iri.h>
33 #include <dpl/utils/mime_type_utils.h>
34 #include <language_subtag_rst_tree.h>
35
36 #include <iri.h>
37 #include <dpl/log/log.h>
38 #include <dpl/fast_delegate.h>
39 #include <dpl/foreach.h>
40 #include <algorithm>
41 #include <cstdio>
42 #include <cerrno>
43
44 using namespace WrtDB;
45
46 namespace Unicode {
47 static const DPL::String UTF_LRE = L"\x0202a";
48 static const DPL::String UTF_LRO = L"\x0202d";
49 static const DPL::String UTF_RLE = L"\x0202b";
50 static const DPL::String UTF_RLO = L"\x0202e";
51 static const DPL::String UTF_PDF = L"\x0202c";
52
53 Direction ParseDirAttribute(const XmlAttribute& attribute)
54 {
55     Assert(L"dir" == attribute.name);
56     if (L"ltr" == attribute.value) {
57         return LRE;
58     } else if (L"rtl" == attribute.value) {
59         return RLE;
60     } else if (L"lro" == attribute.value) {
61         return LRO;
62     } else if (L"rlo" == attribute.value) {
63         return RLO;
64     } else {
65         LogWarning("dir attribute has wrong value:" << attribute.value);
66         return EMPTY;
67     }
68 }
69
70 void UpdateTextWithDirectionMark(Direction direction,
71         DPL::String* text)
72 {
73     Assert(text);
74     switch (direction) {
75     case RLO:
76         *text = UTF_RLO + *text + UTF_PDF;
77         break;
78     case RLE:
79         *text = UTF_RLE + *text + UTF_PDF;
80         break;
81     case LRE:
82         *text = UTF_LRE + *text + UTF_PDF;
83         break;
84     case LRO:
85         *text = UTF_LRO + *text + UTF_PDF;
86         break;
87     case EMPTY:
88         break;
89     default:
90         Assert(false);
91     }
92 }
93 } // namespace Unicode
94
95 class InnerElementsParser : public ElementParser
96 {
97   public:
98     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
99             const DPL::String& /*name*/)
100     {
101         return DPL::MakeDelegate(this, &InnerElementsParser::Other);
102     }
103
104     virtual void Accept(const Element& /*element*/)
105     {
106     }
107
108     virtual void Accept(const Text& text)
109     {
110         if (m_text.IsNull()) {
111             m_text = text;
112         } else {
113             m_text->value += text.value;
114         }
115     }
116
117     virtual void Accept(const XmlAttribute& attribute)
118     {
119         if (attribute.name == L"dir") {
120             m_textDirection = Unicode::ParseDirAttribute(attribute);
121         }
122     }
123
124     virtual void Verify()
125     {
126         if (!m_text.IsNull()) {
127             Unicode::UpdateTextWithDirectionMark(m_textDirection,
128                                                  &m_text->value);
129             m_parentParser->Accept(*m_text);
130         }
131     }
132
133     InnerElementsParser(ElementParserPtr parent) :
134         m_parentParser(parent),
135         m_textDirection(Unicode::EMPTY)
136     {
137     }
138
139     ElementParserPtr Other()
140     {
141         return ElementParserPtr(new InnerElementsParser(
142                                     DPL::StaticPointerCast<ElementParser>(
143                                         SharedFromThis())));
144     }
145
146   private:
147     DPL::Optional<Text> m_text;
148     ElementParserPtr m_parentParser;
149     Unicode::Direction m_textDirection;
150 };
151
152 class NameParser : public ElementParser
153 {
154   public:
155     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
156             const DPL::String& /*name*/)
157     {
158         return DPL::MakeDelegate(this, &NameParser::Other);
159     }
160
161     virtual void Accept(const Element& element)
162     {
163         m_lang = element.lang;
164         m_name = L"";
165     }
166
167     virtual void Accept(const Text& text)
168     {
169         if (m_name.IsNull()) {
170             m_name = text.value;
171         } else {
172             *m_name += text.value;
173         }
174     }
175
176     virtual void Accept(const XmlAttribute& attribute)
177     {
178         if (attribute.name == L"short") {
179             if (m_shortName.IsNull()) {
180                 m_shortName = attribute.value;
181             }
182         } else if (attribute.name == L"dir") {
183             m_textDirection = Unicode::ParseDirAttribute(attribute);
184         }
185     }
186
187     virtual void Verify()
188     {
189         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
190         if (data.name.IsNull()) {
191             NormalizeString(m_name);
192             NormalizeString(m_shortName);
193             if (!m_name.IsNull()) {
194                 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
195             }
196             data.name = m_name;
197             if (!m_shortName.IsNull()) {
198                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
199                                                      &*m_shortName);
200             }
201             data.shortName = m_shortName;
202         }
203     }
204
205     NameParser(Unicode::Direction direction,
206             ConfigParserData& data) :
207         m_data(data),
208         m_textDirection(direction)
209     {
210     }
211
212     ElementParserPtr Other()
213     {
214         return ElementParserPtr(new InnerElementsParser(
215                                     DPL::StaticPointerCast<ElementParser>(
216                                         SharedFromThis())));
217     }
218
219   private:
220     ConfigParserData& m_data;
221     DPL::OptionalString m_name;
222     DPL::OptionalString m_shortName;
223     DPL::OptionalString m_dir;
224     DPL::String m_lang;
225     Unicode::Direction m_textDirection;
226 };
227
228 class AccessParser : public ElementParser
229 {
230   public:
231     enum StandardType
232     {
233         STANDARD_TYPE_NONE,
234         STANDARD_TYPE_WARP
235     };
236
237     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
238             const DPL::String& /*name*/)
239     {
240         return DPL::MakeDelegate(this, &AccessParser::Other);
241     }
242
243     virtual void Accept(const Element& element)
244     {
245         // for tizen web apps WARP should be used
246         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName ||
247             element.ns == ConfigurationNamespace::TizenWebAppNamespaceName)
248         {
249             m_standardType = STANDARD_TYPE_WARP;
250         }
251     }
252
253     virtual void Accept(const Text& /*text*/)
254     {
255     }
256
257     void AcceptWac(const XmlAttribute& attribute)
258     {
259         if (attribute.name == L"origin") {
260             m_strIRIOrigin = attribute.value;
261             NormalizeString(m_strIRIOrigin);
262         } else if (attribute.name == L"subdomains") {
263             DPL::String normalizedValue = attribute.value;
264             NormalizeString(normalizedValue);
265
266             if (normalizedValue == L"true") {
267                 m_bSubDomainAccess = true;
268             } else if (normalizedValue == L"false") {
269                 m_bSubDomainAccess = false;
270             }
271         }
272     }
273
274     virtual void Accept(const XmlAttribute& attribute)
275     {
276         switch (m_standardType) {
277         case STANDARD_TYPE_WARP:
278             AcceptWac(attribute);
279             break;
280         default:
281             LogError("Error in Access tag - unknown standard.");
282         }
283     }
284
285     void VerifyWac()
286     {
287         WarpIRI iri;
288         iri.set(m_strIRIOrigin, false);
289
290         if (!iri.isAccessDefinition()) {
291             LogWarning("Access list element: " <<
292                        m_strIRIOrigin <<
293                        " is not acceptable by WARP" <<
294                        "standard and will be ignored!");
295             return;
296         }
297
298         ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
299                                                 m_bSubDomainAccess);
300         std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
301             m_data.accessInfoSet.insert(accessInfo);
302     }
303
304     virtual void Verify()
305     {
306         switch (m_standardType) {
307         case STANDARD_TYPE_WARP:
308             VerifyWac();
309             break;
310         default:
311             LogError("Error in Access tag - unknown standard.");
312         }
313     }
314
315     AccessParser(ConfigParserData& data) :
316         ElementParser(),
317         m_bSubDomainAccess(false),
318         m_standardType(STANDARD_TYPE_NONE),
319         m_network(false),
320         m_data(data)
321     {
322     }
323
324     ElementParserPtr Other()
325     {
326         return ElementParserPtr(new InnerElementsParser(
327                                     ElementParserPtr(SharedFromThis())));
328     }
329
330   private:
331     DPL::String m_strIRIOrigin;
332     bool m_bSubDomainAccess;
333     StandardType m_standardType;
334     bool m_network;
335     ConfigParserData& m_data;
336 };
337
338 class DescriptionParser : public ElementParser
339 {
340   public:
341     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
342             const DPL::String& /*name*/)
343     {
344         return DPL::MakeDelegate(this, &DescriptionParser::Other);
345     }
346
347     virtual void Accept(const Element& element)
348     {
349         m_lang = element.lang;
350         m_description = L"";
351     }
352
353     ElementParserPtr Other()
354     {
355         return ElementParserPtr(new InnerElementsParser(
356                                     DPL::StaticPointerCast<ElementParser>(
357                                         SharedFromThis())));
358     }
359
360     virtual void Accept(const Text& text)
361     {
362         if (m_description.IsNull()) {
363             m_description = text.value;
364         } else {
365             *m_description += text.value;
366         }
367     }
368
369     virtual void Accept(const XmlAttribute& attribute)
370     {
371         if (attribute.name == L"dir") {
372             m_textDirection = Unicode::ParseDirAttribute(attribute);
373         }
374     }
375
376     virtual void Verify()
377     {
378         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
379         if (data.description.IsNull()) {
380             if (!m_description.IsNull()) {
381                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
382                                                      &*m_description);
383             }
384             data.description = m_description;
385         }
386     }
387
388     DescriptionParser(Unicode::Direction direction,
389             ConfigParserData& data) :
390         m_data(data),
391         m_lang(),
392         m_description(),
393         m_textDirection(direction)
394     {
395     }
396
397   private:
398     ConfigParserData& m_data;
399     DPL::String m_lang;
400     DPL::OptionalString m_description;
401     Unicode::Direction m_textDirection;
402 };
403
404 class AuthorParser : public ElementParser
405 {
406   public:
407     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
408             const DPL::String& /*name*/)
409     {
410         return DPL::MakeDelegate(this, &AuthorParser::Other);
411     }
412
413     AuthorParser(Unicode::Direction direction,
414             ConfigParserData& data) :
415         m_data(data),
416         m_textDirection(direction)
417     {
418     }
419
420     virtual void Accept(const Element& /*element*/)
421     {
422         m_authorName = L"";
423     }
424
425     virtual void Accept(const Text& text)
426     {
427         *(m_authorName) += text.value;
428     }
429
430     virtual void Accept(const XmlAttribute& attribute)
431     {
432         if (attribute.name == L"href") {
433             //Validate href IRI and ignore it if invalid
434             //See also test: ta-argMozRiC-an
435             LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
436             if (iri.Validate()) {
437                 m_authorHref = attribute.value;
438             }
439         } else if (attribute.name == L"email") {
440             m_authorEmail = attribute.value;
441         } else if (attribute.name == L"dir") {
442             m_textDirection = Unicode::ParseDirAttribute(attribute);
443         }
444     }
445
446     virtual void Verify()
447     {
448         if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
449             NormalizeString(m_authorName);
450             NormalizeString(m_authorHref);
451             NormalizeString(m_authorEmail);
452             if (!!m_authorName) {
453                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
454                                                      &*m_authorName);
455                 m_data.authorName = m_authorName;
456             }
457             if (!!m_authorHref) {
458                 m_data.authorHref = m_authorHref;
459             }
460             if (!!m_authorEmail) {
461                 m_data.authorEmail = m_authorEmail;
462             }
463         }
464     }
465
466     ElementParserPtr Other()
467     {
468         return ElementParserPtr(new InnerElementsParser(
469                                     DPL::StaticPointerCast<ElementParser>(
470                                         SharedFromThis())));
471     }
472
473   private:
474     ConfigParserData& m_data;
475     DPL::OptionalString m_authorEmail;
476     DPL::OptionalString m_authorHref;
477     DPL::OptionalString m_authorName;
478     Unicode::Direction m_textDirection;
479 };
480
481 class LicenseParser : public ElementParser
482 {
483   public:
484     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
485             const DPL::String& /*name*/)
486     {
487         return DPL::MakeDelegate(this, &LicenseParser::Other);
488     }
489
490     LicenseParser(Unicode::Direction direction,
491             ConfigParserData& data) :
492         m_data(data),
493         m_ignore(true),
494         m_textDirection(direction)
495     {
496     }
497
498     virtual void Accept(const Element& element)
499     {
500         if (m_license.IsNull()) {
501             m_lang = element.lang;
502             m_license = L"";
503             m_ignore = false;
504         }
505     }
506
507     virtual void Accept(const Text& text)
508     {
509         if (!m_ignore) {
510             *m_license += text.value;
511         }
512     }
513
514     virtual void Accept(const XmlAttribute& attribute)
515     {
516         if (!m_ignore) {
517             if (attribute.name == L"href" && m_licenseHref.IsNull()) {
518                 m_licenseHref = attribute.value;
519             } else if (attribute.name == L"file" && m_licenseFile.IsNull()) {
520                 m_licenseFile = attribute.value;
521             } else if (attribute.name == L"dir") {
522                 m_textDirection = Unicode::ParseDirAttribute(attribute);
523             }
524         }
525     }
526
527     virtual void Verify()
528     {
529         ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
530         if (data.license.IsNull()) {
531             if (!m_license.IsNull()) {
532                 Unicode::UpdateTextWithDirectionMark(m_textDirection,
533                                                      &*m_license);
534             }
535             data.license = m_license;
536             data.licenseHref = m_licenseHref;
537             data.licenseFile = m_licenseFile;
538         }
539     }
540
541     ElementParserPtr Other()
542     {
543         return ElementParserPtr(new InnerElementsParser(
544                                     ElementParserPtr(SharedFromThis())));
545     }
546
547   private:
548     ConfigParserData& m_data;
549     DPL::String m_lang;
550     bool m_ignore;
551
552     DPL::OptionalString m_license;
553     DPL::OptionalString m_licenseFile;
554     DPL::OptionalString m_licenseHref;
555     Unicode::Direction m_textDirection;
556 };
557
558 class IconParser : public ElementParser
559 {
560     DECLARE_EXCEPTION_TYPE(ElementParser::Exception::ParseError, BadSrcError)
561
562   public:
563     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
564             const DPL::String& /*name*/)
565     {
566         return &IgnoringParser::Create;
567     }
568
569     IconParser(ConfigParserData& data) : ElementParser(),
570         m_data(data)
571     {
572     }
573
574     virtual void Accept(const Element& /*element*/)
575     {
576     }
577
578     virtual void Accept(const XmlAttribute& attribute)
579     {
580         if (attribute.name == L"src") {
581             if (attribute.value.size() > 0) {
582                 m_src = attribute.value;
583             }
584         } else if (attribute.name == L"width") {
585             m_width = ParseSizeAttributeValue(attribute.value);
586         } else if (attribute.name == L"height") {
587             m_height = ParseSizeAttributeValue(attribute.value);
588         }
589     }
590
591     virtual void Accept(const Text& /*text*/)
592     {
593         ThrowMsg(Exception::ParseError, "Icon element must be empty");
594     }
595
596     virtual void Verify()
597     {
598         if (m_src.IsNull()) {
599             LogWarning("src attribute of icon element is mandatory - ignoring");
600             return;
601         }
602
603         Try
604         {
605             ConfigParserData::Icon icon(delocalizeSrcPath(*m_src));
606             icon.width = m_width;
607             icon.height = m_height;
608
609             ConfigParserData::IconsList::iterator it = std::find(
610                     m_data.iconsList.begin(), m_data.iconsList.end(), icon);
611             if (it == m_data.iconsList.end()) {
612                 m_data.iconsList.push_front(icon);
613             }
614         }
615         Catch(BadSrcError)
616         {
617             LogWarning("src attribute is invalid: " << m_src);
618         }
619     }
620
621   private:
622     ConfigParserData& m_data;
623     DPL::OptionalString m_src;
624     DPL::OptionalInt m_width;
625     DPL::OptionalInt m_height;
626
627     static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
628     {
629         DPL::OptionalString normalizedValue = value;
630         NormalizeString(normalizedValue);
631         if (!(*normalizedValue).empty()) {
632             char* reterr = NULL;
633             errno = 0;
634             long int valueInt =
635                 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
636             if (errno != 0 ||
637                 std::string(reterr) == DPL::ToUTF8String(value) ||
638                 valueInt <= 0) {
639                 return DPL::OptionalInt::Null;
640             } else {
641                 return valueInt;
642             }
643         }
644         return DPL::OptionalInt::Null;
645     }
646
647     /**
648      * @brief delocalizePath removes locales folder from relative path if neccessary
649      * @param source source string
650      *
651      * @throw BadSrcError if string is bad value of src attribute
652      *
653      * @return corrected string
654      */
655     static DPL::String delocalizeSrcPath(const DPL::String & source)
656     {
657         static const DPL::String localeFolder(L"locales/");
658         static const int index = localeFolder.size();
659
660         DPL::String result = source;
661
662         if(source.substr(0,index) == localeFolder)
663         {
664             int pos = result.find_first_of('/',index);
665             if(pos != std::string::npos && pos + 1 < source.size())
666             {
667                 result = result.substr(pos + 1,source.size());
668             }
669             else
670             {
671                 Throw(BadSrcError);
672             }
673         }
674         return result;
675     }
676 };
677
678 class ContentParser : public ElementParser
679 {
680   public:
681     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
682             const DPL::String& /*name*/)
683     {
684         return &IgnoringParser::Create;
685     }
686
687     ContentParser(ConfigParserData& data) :
688         ElementParser(),
689         m_data(data)
690     {
691     }
692
693     virtual void Accept(const Element& /*element*/)
694     {
695     }
696
697     virtual void Accept(const Text& /*text*/)
698     {
699     }
700
701     virtual void Accept(const XmlAttribute& attribute)
702     {
703         DPL::String value = attribute.value;
704         NormalizeString(value);
705
706         if (attribute.name == L"src") {
707             m_src = value;
708         } else if (attribute.name == L"type") {
709             m_type = value;
710             MimeTypeUtils::MimeAttributes mimeAttributes =
711                 MimeTypeUtils::getMimeAttributes(value);
712             if (mimeAttributes.count(L"charset") > 0) {
713                 m_encoding = mimeAttributes[L"charset"];
714             }
715         } else if (attribute.name == L"encoding") {
716             if (!value.empty()) {
717                 m_encoding = value;
718             }
719         }
720     }
721
722     virtual void Verify()
723     {
724         if (m_data.startFileEncountered) {
725             LogWarning("This is not the first encountered "
726                        "'content' element - ignoring.");
727             return;
728         }
729
730         m_data.startFileEncountered = true;
731
732         //we're consciously setting startFile even if m_src is null or invalid.
733         //WidgetConfigurationManager will deal with this.
734         m_data.startFile = m_src;
735
736         if (!!m_src) {
737             m_data.startFileContentType = m_type;
738             if (!!m_encoding) {
739                 m_data.startFileEncoding = m_encoding;
740             } else {
741                 m_data.startFileEncoding = L"UTF-8";
742             }
743         }
744     }
745
746   private:
747     DPL::OptionalString m_src;
748     DPL::OptionalString m_type;
749     DPL::OptionalString m_encoding;
750     ConfigParserData& m_data;
751 };
752
753 class FeatureParser : public ElementParser
754 {
755   public:
756     struct ParamParser : public ElementParser
757     {
758         virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
759                 const DPL::String& /*name*/)
760         {
761             return &IgnoringParser::Create;
762         }
763
764         virtual void Accept(const XmlAttribute& attribute)
765         {
766             if (attribute.name == L"name") {
767                 m_name = attribute.value;
768                 NormalizeString(m_name);
769             } else if (attribute.name == L"value") {
770                 m_value = attribute.value;
771                 NormalizeString(m_value);
772             }
773         }
774
775         virtual void Accept(const Element& /*element*/)
776         {
777         }
778
779         virtual void Accept(const Text& /*text*/)
780         {
781             ThrowMsg(Exception::ParseError, "param element must be empty");
782         }
783
784         virtual void Verify()
785         {
786             if (m_name.IsNull() || *m_name == L"") {
787                 return;
788             }
789             if (m_value.IsNull() || *m_value == L"") {
790                 return;
791             }
792
793             ConfigParserData::Param param(*m_name);
794             param.value = *m_value;
795
796             if (m_data.paramsList.find(param) == m_data.paramsList.end()) {
797                 m_data.paramsList.insert(param);
798             }
799         }
800
801         ParamParser(ConfigParserData::Feature& data) :
802             ElementParser(),
803             m_data(data)
804         {
805         }
806
807       private:
808         DPL::OptionalString m_name;
809         DPL::OptionalString m_value;
810         ConfigParserData::Feature& m_data;
811     };
812
813     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
814             const DPL::String& name)
815     {
816         if (name == L"param") {
817             return DPL::MakeDelegate(this, &FeatureParser::OnParamElement);
818         } else {
819             return &IgnoringParser::Create;
820         }
821     }
822
823     virtual void Accept(const Text& /*text*/)
824     {
825     }
826
827     virtual void Accept(const Element& /*element*/)
828     {
829     }
830
831     virtual void Accept(const XmlAttribute& attribute)
832     {
833         if (attribute.name == L"name") {
834             m_feature.name = attribute.value;
835         } else if (attribute.name == L"required") {
836             if (attribute.value == L"false") {
837                 m_feature.required = false;
838             } else {
839                 m_feature.required = true;
840             }
841         }
842     }
843
844     virtual void Verify()
845     {
846         LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
847
848         if (m_feature.name != L"") {
849             if (iri.Validate()) {
850                 if (m_data.featuresList.find(m_feature) ==
851                     m_data.featuresList.end()) {
852                     m_data.featuresList.insert(m_feature);
853                 } else {
854                     LogDebug("Ignoring feature with name" <<
855                              DPL::ToUTF8String(m_feature.name));
856                 }
857             } else {
858                 if (m_feature.required) {
859                     //Throw only if required
860                     ThrowMsg(Exception::ParseError, "invalid feature IRI");
861                 }
862             }
863         }
864     }
865
866     ElementParserPtr OnParamElement()
867     {
868         return ElementParserPtr(new ParamParser(m_feature));
869     }
870
871     FeatureParser(ConfigParserData& data) :
872         ElementParser(),
873         m_data(data),
874         m_feature(L"")
875     {
876     }
877
878   private:
879     ConfigParserData& m_data;
880     ConfigParserData::Feature m_feature;
881 };
882
883 class PreferenceParser : public ElementParser
884 {
885   public:
886     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
887             const DPL::String& /*name*/)
888     {
889         return &IgnoringParser::Create;
890     }
891
892     virtual void Accept(const XmlAttribute& attribute)
893     {
894         if (attribute.name == L"name") {
895             m_name = attribute.value;
896         } else if (attribute.name == L"value") {
897             m_value = attribute.value;
898         } else if (attribute.name == L"readonly") {
899             if (attribute.value == L"true") {
900                 m_required = true;
901             } else {
902                 m_required = false;
903             }
904         }
905     }
906
907     virtual void Accept(const Element& /*element*/)
908     {
909     }
910
911     virtual void Accept(const Text& /*text*/)
912     {
913         ThrowMsg(Exception::ParseError, "param element must be empty");
914     }
915
916     virtual void Verify()
917     {
918         if (m_name.IsNull()) {
919             LogWarning("preference element must have name attribute");
920             return;
921         }
922         NormalizeString(m_name);
923         NormalizeString(m_value);
924         ConfigParserData::Preference preference(*m_name, m_required);
925         preference.value = m_value;
926         if (m_data.preferencesList.find(preference) ==
927             m_data.preferencesList.end()) {
928             m_data.preferencesList.insert(preference);
929         }
930     }
931
932     PreferenceParser(ConfigParserData& data) :
933         ElementParser(),
934         m_required(false),
935         m_data(data)
936     {
937     }
938
939   private:
940     DPL::OptionalString m_name;
941     DPL::OptionalString m_value;
942     bool m_required;
943     ConfigParserData& m_data;
944 };
945
946 class FlashParser : public ElementParser
947 {
948   public:
949     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
950             const DPL::String& /*name*/)
951     {
952         return &IgnoringParser::Create;
953     }
954
955     virtual void Accept(const XmlAttribute& attribute)
956     {
957         if (attribute.name == L"needed") {
958             if (attribute.value == L"true") {
959                 m_flashNeeded = true;
960             } else {
961                 m_flashNeeded = false;
962             }
963         }
964     }
965
966     virtual void Accept(const Element& /*element*/)
967     {
968         //if empty flash element will be passed, we say true
969         m_data.flashNeeded = true;
970     }
971
972     virtual void Accept(const Text& /*text*/)
973     {
974         ThrowMsg(Exception::ParseError, "flash element must be empty");
975     }
976
977     virtual void Verify()
978     {
979         m_data.flashNeeded = m_flashNeeded;
980     }
981
982     FlashParser(ConfigParserData& data) :
983         ElementParser(),
984         m_flashNeeded(false),
985         m_data(data)
986     {
987     }
988
989   private:
990     bool m_flashNeeded;
991     ConfigParserData& m_data;
992 };
993
994 class LinkParser : public ElementParser
995 {
996   public:
997     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
998             const DPL::String& /*name*/)
999     {
1000         return &DenyAllParser::Create;
1001     }
1002
1003     virtual void Accept(const XmlAttribute& attribute)
1004     {
1005         if (m_properNamespace) {
1006             LogDebug("attribute");
1007             if (attribute.name == L"rel") {
1008                 if (attribute.value != L"describedby") {
1009                     ThrowMsg(Exception::ParseError,
1010                              "rel attribute must have describedby value");
1011                 }
1012             } else if (attribute.name == L"type") {
1013             } else if (attribute.name == L"href") {
1014                 LogDebug("here is href");
1015                 m_href = attribute.value;
1016             } else {
1017                 ThrowMsg(Exception::ParseError,
1018                          "unknown attribute '" +
1019                          DPL::ToUTF8String(attribute.name) +
1020                          "' in link element");
1021             }
1022         }
1023     }
1024
1025     virtual void Accept(const Element& element)
1026     {
1027         if (element.ns ==
1028             ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement)
1029         {
1030             m_properNamespace = true;
1031         }
1032         LogDebug("element");
1033     }
1034
1035     virtual void Accept(const Text&)
1036     {
1037         if (m_properNamespace) {
1038             LogDebug("text");
1039             ThrowMsg(Exception::ParseError, "link element must be empty");
1040         }
1041     }
1042
1043     virtual void Verify()
1044     {
1045         if (!m_href) {
1046             ThrowMsg(Exception::ParseError,
1047                      "link element must have href attribute");
1048         }
1049
1050         LibIri::Wrapper iri(DPL::ToUTF8String(*m_href).c_str());
1051         if (!iri.Validate()) { // TODO: Better uri validator ?
1052             ThrowMsg(Exception::ParseError,
1053                      "href attribute must be a valid iri/uri/url");
1054         }
1055
1056         m_data.powderDescriptionLinks.insert(*m_href);
1057     }
1058
1059     LinkParser(ConfigParserData& data) :
1060         ElementParser(),
1061         m_properNamespace(false),
1062         m_data(data),
1063         m_href(DPL::OptionalString::Null)
1064     {
1065     }
1066
1067   private:
1068     bool m_properNamespace;
1069     ConfigParserData& m_data;
1070     DPL::OptionalString m_href;
1071 };
1072
1073 class SettingParser : public ElementParser
1074 {
1075   public:
1076     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1077             const DPL::String& /*name*/)
1078     {
1079         return &IgnoringParser::Create;
1080     }
1081
1082     virtual void Accept(const Text& /*text*/)
1083     {
1084     }
1085
1086     virtual void Accept(const Element& /*element*/)
1087     {
1088     }
1089
1090     virtual void Accept(const XmlAttribute& attribute)
1091     {
1092         m_setting.m_name = attribute.name;
1093         m_setting.m_value = attribute.value;
1094         m_data.settingsList.insert(m_setting);
1095     }
1096
1097     virtual void Verify()
1098     {
1099     }
1100
1101     SettingParser(ConfigParserData& data) :
1102         ElementParser(),
1103         m_data(data),
1104         m_setting(L"", L"")
1105     {
1106     }
1107
1108   private:
1109     ConfigParserData& m_data;
1110     ConfigParserData::Setting m_setting;
1111 };
1112
1113 class ServiceParser : public ElementParser
1114 {
1115   public:
1116     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1117                                         const DPL::String& /*name*/)
1118     {
1119         return &IgnoringParser::Create;
1120     }
1121
1122     virtual void Accept(const XmlAttribute& attribute)
1123     {
1124         if (attribute.name == L"src") {
1125             m_src = attribute.value;
1126         } else if (attribute.name == L"operation") {
1127             m_operation = attribute.value;
1128         } else if (attribute.name == L"scheme") {
1129             m_scheme = attribute.value;
1130         } else if (attribute.name == L"mime") {
1131             m_mime = attribute.value;
1132         }
1133     }
1134
1135     virtual void Accept(const Element& element)
1136     {
1137         LogWarning("namespace for app service = " << element.ns);
1138         if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1139             ThrowMsg(Exception::ParseError,
1140                 "Wrong xml namespace for widget element");
1141         }
1142     }
1143
1144     virtual void Accept(const Text& /*text*/)
1145     {
1146         ThrowMsg(Exception::ParseError, "param element must be empty");
1147     }
1148
1149     virtual void Verify()
1150     {
1151         if (m_src.IsNull()) {
1152             LogWarning("service element must have target attribute");
1153             return;
1154         } else if (m_operation.IsNull()) {
1155             LogWarning("service element must have operation attribute");
1156             return;
1157         }
1158         NormalizeString(m_src);
1159         NormalizeString(m_operation);
1160         NormalizeString(m_scheme);
1161         NormalizeString(m_mime);
1162
1163         // verify duplicate element
1164         DPL::String wildString(L"*/*");
1165         DPL::String nullString(L"");
1166         ConfigParserData::ServiceInfo serviceInfo(
1167             m_src.IsNull()       ? nullString:*m_src,
1168             m_operation.IsNull() ? nullString:*m_operation,
1169             m_scheme.IsNull()    ? nullString:*m_scheme,
1170             m_mime.IsNull()      ? nullString:*m_mime);
1171
1172         FOREACH(iterator, m_data.appServiceList) {
1173             if (iterator->m_operation == serviceInfo.m_operation &&
1174                 // check scheme
1175                 (iterator->m_scheme == serviceInfo.m_scheme ||
1176                 // check input scheme is "*/*" case
1177                 (iterator->m_scheme == wildString &&
1178                  serviceInfo.m_scheme != nullString) ||
1179                 // check iterator scheme is "*/*" case
1180                 (serviceInfo.m_scheme == wildString &&
1181                  iterator->m_scheme != nullString)) &&
1182
1183                 (iterator->m_mime == serviceInfo.m_mime ||
1184                 // check input mime is "*/*" case
1185                 (iterator->m_mime == wildString &&
1186                  serviceInfo.m_mime != nullString) ||
1187                 // check iterator mime is "*/*" case
1188                 (serviceInfo.m_mime == wildString &&
1189                  iterator->m_mime != nullString)))
1190             {
1191                 ThrowMsg(Exception::ParseError,
1192                     "service operation is duplicated " +
1193                     DPL::ToUTF8String(*m_operation));
1194             }
1195         }
1196         m_data.appServiceList.push_back(serviceInfo);
1197     }
1198
1199     ServiceParser(ConfigParserData& data) :
1200         ElementParser(),
1201         m_src(DPL::OptionalString::Null),
1202         m_operation(DPL::OptionalString::Null),
1203         m_scheme(DPL::OptionalString::Null),
1204         m_mime(DPL::OptionalString::Null),
1205         m_data(data)
1206     {
1207     }
1208
1209   private:
1210     DPL::OptionalString m_src;
1211     DPL::OptionalString m_operation;
1212     DPL::OptionalString m_scheme;
1213     DPL::OptionalString m_mime;
1214     ConfigParserData& m_data;
1215 };
1216
1217 class ApplicationParser : public ElementParser
1218 {
1219   public:
1220     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1221             const DPL::String& /*name*/)
1222     {
1223         return &IgnoringParser::Create;
1224     }
1225
1226     virtual void Accept(const Text& text)
1227     {
1228         if (m_properNamespace) {
1229             LogDebug("text");
1230             ThrowMsg(Exception::ParseError, "application element must be empty");
1231         }
1232     }
1233
1234     virtual void Accept(const Element& element)
1235     {
1236         if (element.ns == 
1237             ConfigurationNamespace::TizenWebAppNamespaceName)
1238         {
1239             m_properNamespace = true;
1240         }
1241         LogDebug("element");
1242     }
1243
1244     virtual void Accept(const XmlAttribute& attribute)
1245     {
1246         if (m_properNamespace) {
1247             LogDebug("attribute");
1248             if (attribute.name == L"id") {
1249                 m_id = attribute.value;
1250             } else if (attribute.name == L"required_version") {
1251                 m_version = attribute.value;
1252                 NormalizeString(m_version);
1253             } else {
1254                 ThrowMsg(Exception::ParseError,
1255                          "unknown attribute '" +
1256                          DPL::ToUTF8String(attribute.name) +
1257                          "' in application element");
1258             }
1259         }
1260     }
1261
1262     virtual void Verify()
1263     {
1264         if(!m_id) {
1265             ThrowMsg(Exception::ParseError,
1266                      "application element must have id attribute");
1267         }
1268
1269         if(!m_version) {
1270             ThrowMsg(Exception::ParseError,
1271                      "application element must have required_version attribute");
1272         }
1273
1274         //TODO check if id and version format is right
1275         m_data.tizenId = m_id;
1276         m_data.tizenMinVersionRequired = m_version;
1277     }
1278
1279     ApplicationParser(ConfigParserData& data) :
1280         ElementParser(),
1281         m_data(data),
1282         m_id(DPL::OptionalString::Null),
1283         m_version(DPL::OptionalString::Null),
1284         m_properNamespace(false)
1285     {
1286     }
1287
1288   private:
1289     ConfigParserData& m_data;
1290     DPL::OptionalString m_id;
1291     DPL::OptionalString m_version;
1292     bool m_properNamespace;
1293 };
1294
1295 class SplashParser : public ElementParser
1296 {
1297   public:
1298     virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1299                                         const DPL::String& /*name*/)
1300     {
1301         return &IgnoringParser::Create;
1302     }
1303
1304     virtual void Accept(const XmlAttribute& attribute)
1305     {
1306         if (attribute.name == L"src") {
1307             if (attribute.value.size() > 0) {
1308                 m_src = attribute.value;
1309             }
1310         }
1311     }
1312
1313     virtual void Accept(const Element& element)
1314     {
1315     }
1316
1317     virtual void Accept(const Text& /*text*/)
1318     {
1319     }
1320
1321     virtual void Verify()
1322     {
1323         if (m_src.IsNull()) {
1324             LogWarning("src attribute of splash element is mandatory - ignoring");
1325             return;
1326         }
1327
1328         m_data.splashImgSrc = m_src;
1329     }
1330
1331     SplashParser(ConfigParserData& data) :
1332         ElementParser(),
1333         m_data(data)
1334     {
1335     }
1336
1337   private:
1338     DPL::OptionalString m_src;
1339     ConfigParserData& m_data;
1340 };
1341
1342 ElementParser::ActionFunc WidgetParser::GetElementParser(const DPL::String& /*ns*/,
1343         const DPL::String& name)
1344 {
1345     FuncMap::const_iterator it = m_map.find(name);
1346     if (it != m_map.end()) {
1347         return it->second;
1348     } else {
1349         return &IgnoringParser::Create;
1350     }
1351 }
1352
1353 WidgetParser::WidgetParser(ConfigParserData& data) :
1354     m_data(data),
1355     m_textDirection(Unicode::EMPTY)
1356 {
1357     m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
1358     m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
1359     m_map[L"description"] =
1360         DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
1361     m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
1362     m_map[L"license"] =
1363         DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
1364     m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
1365     m_map[L"content"] =
1366         DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
1367     m_map[L"feature"] =
1368         DPL::MakeDelegate(this, &WidgetParser::OnFeatureElement);
1369     m_map[L"preference"] =
1370         DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
1371     m_map[L"flash"] = DPL::MakeDelegate(this, &WidgetParser::OnFlashElement);
1372     m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
1373     m_map[L"setting"] =
1374         DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
1375     m_map[L"appservice"] = DPL::MakeDelegate(this, &WidgetParser::OnServiceElement);
1376     m_map[L"application"] = DPL::MakeDelegate(this, &WidgetParser::OnApplicationElement);
1377     m_map[L"splash"] = DPL::MakeDelegate(this, &WidgetParser::OnSplashElement);
1378 }
1379
1380 ElementParserPtr WidgetParser::OnNameElement()
1381 {
1382     return ElementParserPtr(new NameParser(m_textDirection, m_data));
1383 }
1384
1385 ElementParserPtr WidgetParser::OnAccessElement()
1386 {
1387     return ElementParserPtr(new AccessParser(m_data));
1388 }
1389
1390 ElementParserPtr WidgetParser::OnDescriptionElement()
1391 {
1392     return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
1393 }
1394
1395 ElementParserPtr WidgetParser::OnAuthorElement()
1396 {
1397     return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
1398 }
1399
1400 ElementParserPtr WidgetParser::OnLicenseElement()
1401 {
1402     return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
1403 }
1404
1405 ElementParserPtr WidgetParser::OnIconElement()
1406 {
1407     return ElementParserPtr(new IconParser(m_data));
1408 }
1409
1410 ElementParserPtr WidgetParser::OnContentElement()
1411 {
1412     return ElementParserPtr(new ContentParser(m_data));
1413 }
1414
1415 ElementParserPtr WidgetParser::OnFeatureElement()
1416 {
1417     return ElementParserPtr(new FeatureParser(m_data));
1418 }
1419
1420 ElementParserPtr WidgetParser::OnPreferenceElement()
1421 {
1422     return ElementParserPtr(new PreferenceParser(m_data));
1423 }
1424
1425 ElementParserPtr WidgetParser::OnFlashElement()
1426 {
1427     return ElementParserPtr(new FlashParser(m_data));
1428 }
1429
1430 ElementParserPtr WidgetParser::OnLinkElement()
1431 {
1432     return ElementParserPtr(new LinkParser(m_data));
1433 }
1434
1435 ElementParserPtr WidgetParser::OnSettingElement()
1436 {
1437     return ElementParserPtr(new SettingParser(m_data));
1438 }
1439
1440 ElementParserPtr WidgetParser::OnServiceElement()
1441 {
1442     return ElementParserPtr(new ServiceParser(m_data));
1443 }
1444
1445 ElementParserPtr WidgetParser::OnApplicationElement()
1446 {
1447     return ElementParserPtr(new ApplicationParser(m_data));
1448 }
1449
1450 ElementParserPtr WidgetParser::OnSplashElement()
1451 {
1452     return ElementParserPtr(new SplashParser(m_data));
1453 }
1454
1455 void WidgetParser::Accept(const Element& element)
1456 {
1457     if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName &&
1458         element.ns != ConfigurationNamespace::TizenWebAppNamespaceName)
1459     {
1460         ThrowMsg(Exception::ParseError,
1461                  "Wrong xml namespace for widget element");
1462     }
1463 }
1464
1465 void WidgetParser::Accept(const Text& /*text*/)
1466 {
1467     ThrowMsg(Exception::ParseError, "widged element must be empty");
1468 }
1469
1470 void WidgetParser::Accept(const XmlAttribute& attribute)
1471 {
1472     if (attribute.name == L"id") {
1473         LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
1474         //If may important tests starts to fail this test we will have
1475         //to consider commenting this test out again.
1476         if (iri.Validate()) {
1477             m_data.widget_id = attribute.value;
1478             NormalizeString(m_data.widget_id);
1479         }
1480     } else if (attribute.name == L"version") {
1481         m_version = attribute.value;
1482         NormalizeString(m_version);
1483     } else if (attribute.name == L"min-version") {
1484         LogInfo("min-version attribute was found. Value: " << attribute.value);
1485         m_minVersion = attribute.value;
1486         NormalizeString(m_minVersion);
1487         m_data.minVersionRequired = m_minVersion;
1488     } else if (attribute.name == L"height") {
1489         DPL::OptionalString value = attribute.value;
1490         NormalizeString(value);
1491         std::string v = DPL::ToUTF8String(*value);
1492
1493         if (!v.empty()) {
1494             unsigned char c = v.c_str()[0];
1495             if (c >= '0' && c <= '9') {
1496                 int val = 0;
1497                 for (size_t i = 0; i < v.size(); ++i) {
1498                     c = v.c_str()[i];
1499                     if (c >= '0' && c <= '9') {
1500                         val *= 10;
1501                         val += (c - '0');
1502                     } else {
1503                         break;
1504                     }
1505                 }
1506                 m_data.height = val;
1507             }
1508         }
1509     } else if (attribute.name == L"width") {
1510         DPL::OptionalString value = attribute.value;
1511         NormalizeString(value);
1512         std::string v = DPL::ToUTF8String(*value);
1513
1514         if (!v.empty()) {
1515             unsigned char c = v.c_str()[0];
1516             if (c >= '0' && c <= '9') {
1517                 int val = 0;
1518                 for (size_t i = 0; i < v.size(); ++i) {
1519                     c = v.c_str()[i];
1520                     if (c >= '0' && c <= '9') {
1521                         val *= 10;
1522                         val += (c - '0');
1523                     } else {
1524                         break;
1525                     }
1526                 }
1527                 m_data.width = val;
1528             }
1529         }
1530     } else if (attribute.name == L"viewmodes") {
1531         DPL::Tokenize(attribute.value,
1532                       L" ",
1533                       std::inserter(m_windowModes,
1534                                     m_windowModes.end()),
1535                       true);
1536     } else if (attribute.name == L"dir") {
1537         m_textDirection = Unicode::ParseDirAttribute(attribute);
1538     } else if (L"defaultlocale" == attribute.name) {
1539         if (!m_defaultlocale) {
1540             m_defaultlocale = attribute.value;
1541             NormalizeString(m_defaultlocale);
1542             if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
1543                     DPL::ToUTF8String(*m_defaultlocale))) {
1544                 LogWarning("Language tag: " <<
1545                            m_defaultlocale << " is not valid");
1546                 m_defaultlocale = DPL::OptionalString::Null;
1547             }
1548             else
1549                 LogDebug("Default Locale Found " << m_defaultlocale);
1550         } else {
1551             LogWarning("Ignoring subsequent default locale");
1552         }
1553
1554     //Any other value consider as a namespace definition
1555     } else if (attribute.name == L"xmlns" ||
1556             attribute.ns == m_nameSpaces[L"xmlns"]) {
1557         LogInfo("Namespace domain: " << attribute.name);
1558         LogInfo("Namespace value: " << attribute.value);
1559         m_nameSpaces[attribute.name] = attribute.value;
1560     } else {
1561         LogError("Unknown attirbute: namespace=" << attribute.ns <<
1562                 ", name=" << attribute.name <<
1563                 ", value=" << attribute.value);
1564     }
1565 }
1566
1567 void WidgetParser::Verify()
1568 {
1569     FOREACH(mode, m_windowModes) {
1570         if (L"windowed" == *mode || L"floating" == *mode ||
1571             L"fullscreen" == *mode || L"maximized" == *mode ||
1572             L"minimized" == *mode) {
1573             m_data.windowModes.insert(*mode);
1574         }
1575     }
1576     if (!m_version.IsNull()) {
1577         Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
1578         m_data.version = m_version;
1579     }
1580     m_data.defaultlocale = m_defaultlocale;
1581     FOREACH(ns, m_nameSpaces) {
1582         m_data.nameSpaces.insert(ns->second);
1583     }
1584 }
1585