2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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
22 * @file widget_parser.cpp
23 * @author Lukasz Wrzosek (l.wrzosek@samsung.com)
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>
38 #include <dpl/log/log.h>
39 #include <dpl/fast_delegate.h>
40 #include <dpl/foreach.h>
45 using namespace WrtDB;
48 static const DPL::String UTF_LRE = L"\x0202a";
49 static const DPL::String UTF_LRO = L"\x0202d";
50 static const DPL::String UTF_RLE = L"\x0202b";
51 static const DPL::String UTF_RLO = L"\x0202e";
52 static const DPL::String UTF_PDF = L"\x0202c";
54 Direction ParseDirAttribute(const XmlAttribute& attribute)
56 Assert(L"dir" == attribute.name);
57 if (L"ltr" == attribute.value) {
59 } else if (L"rtl" == attribute.value) {
61 } else if (L"lro" == attribute.value) {
63 } else if (L"rlo" == attribute.value) {
66 LogWarning("dir attribute has wrong value:" << attribute.value);
71 void UpdateTextWithDirectionMark(Direction direction,
77 *text = UTF_RLO + *text + UTF_PDF;
80 *text = UTF_RLE + *text + UTF_PDF;
83 *text = UTF_LRE + *text + UTF_PDF;
86 *text = UTF_LRO + *text + UTF_PDF;
94 } // namespace Unicode
96 class InnerElementsParser : public ElementParser
99 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
100 const DPL::String& /*name*/)
102 return DPL::MakeDelegate(this, &InnerElementsParser::Other);
105 virtual void Accept(const Element& /*element*/)
109 virtual void Accept(const Text& text)
111 if (m_text.IsNull()) {
114 m_text->value += text.value;
118 virtual void Accept(const XmlAttribute& attribute)
120 if (attribute.name == L"dir") {
121 m_textDirection = Unicode::ParseDirAttribute(attribute);
125 virtual void Verify()
127 if (!m_text.IsNull()) {
128 Unicode::UpdateTextWithDirectionMark(m_textDirection,
130 m_parentParser->Accept(*m_text);
134 InnerElementsParser(ElementParserPtr parent) :
135 m_parentParser(parent),
136 m_textDirection(Unicode::EMPTY)
140 ElementParserPtr Other()
142 return ElementParserPtr(new InnerElementsParser(
143 DPL::StaticPointerCast<ElementParser>(
148 DPL::Optional<Text> m_text;
149 ElementParserPtr m_parentParser;
150 Unicode::Direction m_textDirection;
153 class NameParser : public ElementParser
156 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
157 const DPL::String& /*name*/)
159 return DPL::MakeDelegate(this, &NameParser::Other);
162 virtual void Accept(const Element& element)
164 m_lang = element.lang;
168 virtual void Accept(const Text& text)
170 if (m_name.IsNull()) {
173 *m_name += text.value;
177 virtual void Accept(const XmlAttribute& attribute)
179 if (attribute.name == L"short") {
180 if (m_shortName.IsNull()) {
181 m_shortName = attribute.value;
183 } else if (attribute.name == L"dir") {
184 m_textDirection = Unicode::ParseDirAttribute(attribute);
188 virtual void Verify()
190 ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
191 if (data.name.IsNull()) {
192 NormalizeString(m_name);
193 NormalizeString(m_shortName);
194 if (!m_name.IsNull()) {
195 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_name);
198 if (!m_shortName.IsNull()) {
199 Unicode::UpdateTextWithDirectionMark(m_textDirection,
202 data.shortName = m_shortName;
206 NameParser(Unicode::Direction direction,
207 ConfigParserData& data) :
209 m_textDirection(direction)
213 ElementParserPtr Other()
215 return ElementParserPtr(new InnerElementsParser(
216 DPL::StaticPointerCast<ElementParser>(
221 ConfigParserData& m_data;
222 DPL::OptionalString m_name;
223 DPL::OptionalString m_shortName;
224 DPL::OptionalString m_dir;
226 Unicode::Direction m_textDirection;
229 class AccessParser : public ElementParser
239 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
240 const DPL::String& /*name*/)
242 return DPL::MakeDelegate(this, &AccessParser::Other);
245 virtual void Accept(const Element& element)
247 if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
248 m_standardType = STANDARD_TYPE_WARP;
250 if (element.ns == ConfigurationNamespace::JilWidgetNamespaceName) {
251 m_standardType = STANDARD_TYPE_JIL;
255 virtual void Accept(const Text& /*text*/)
259 void AcceptWac(const XmlAttribute& attribute)
261 if (attribute.name == L"origin") {
262 m_strIRIOrigin = attribute.value;
263 NormalizeString(m_strIRIOrigin);
264 } else if (attribute.name == L"subdomains") {
265 DPL::String normalizedValue = attribute.value;
266 NormalizeString(normalizedValue);
268 if (normalizedValue == L"true") {
269 m_bSubDomainAccess = true;
270 } else if (normalizedValue == L"false") {
271 m_bSubDomainAccess = false;
276 void AcceptJil(const XmlAttribute& attribute)
278 if (attribute.name == DPL::FromASCIIString("network")) {
279 if (attribute.value == DPL::FromASCIIString("true")) {
287 virtual void Accept(const XmlAttribute& attribute)
289 switch (m_standardType) {
290 case STANDARD_TYPE_WARP:
291 AcceptWac(attribute);
293 case STANDARD_TYPE_JIL:
294 AcceptJil(attribute);
297 LogError("Error in Access tag - unknown standard.");
304 iri.set(m_strIRIOrigin, false);
306 if (!iri.isAccessDefinition()) {
307 LogWarning("Access list element: " <<
309 " is not acceptable by WARP" <<
310 "standard and will be ignored!");
314 ConfigParserData::AccessInfo accessInfo(m_strIRIOrigin,
316 std::pair <ConfigParserData::AccessInfoSet::iterator, bool> ret =
317 m_data.accessInfoSet.insert(accessInfo);
322 m_data.accessNetwork = m_network;
325 virtual void Verify()
327 switch (m_standardType) {
328 case STANDARD_TYPE_WARP:
331 case STANDARD_TYPE_JIL:
335 LogError("Error in Access tag - unknown standard.");
339 AccessParser(ConfigParserData& data) :
341 m_bSubDomainAccess(false),
342 m_standardType(STANDARD_TYPE_NONE),
348 ElementParserPtr Other()
350 return ElementParserPtr(new InnerElementsParser(
351 ElementParserPtr(SharedFromThis())));
355 DPL::String m_strIRIOrigin;
356 bool m_bSubDomainAccess;
357 StandardType m_standardType;
359 ConfigParserData& m_data;
362 class PkgnameParser : public ElementParser
365 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
366 const DPL::String& /*name*/)
368 return &DenyAllParser::Create;
371 virtual void Accept(const Element& element)
373 if (element.ns == ConfigurationNamespace::TizenWebAppNamespaceName) {
374 m_properNamespace = true;
377 LogDebug("element pkgname");
380 ElementParserPtr Other()
382 return ElementParserPtr(new InnerElementsParser(
383 DPL::StaticPointerCast<ElementParser>(
387 virtual void Accept(const Text& text)
389 if(m_properNamespace) {
390 m_pkgname = text.value;
391 LogDebug("Pkgname value: " << m_pkgname);
395 virtual void Accept(const XmlAttribute& attribute)
397 if (m_properNamespace) {
398 ThrowMsg(Exception::ParseError,
399 "attirubte: '" + DPL::ToUTF8String(attribute.name) +
400 "' in pkgname element not allowed");
404 virtual void Verify()
406 if (m_properNamespace) {
407 if (m_pkgname.IsNull()) {
408 ThrowMsg(Exception::ParseError,
409 "pkgname element must have value");
411 m_data.pkgname = m_pkgname;
412 LogDebug("Pkgname = " << m_pkgname);
416 PkgnameParser(ConfigParserData& data) :
417 m_properNamespace(false),
424 bool m_properNamespace;
425 ConfigParserData& m_data;
426 DPL::OptionalString m_pkgname;
429 class DescriptionParser : public ElementParser
432 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
433 const DPL::String& /*name*/)
435 return DPL::MakeDelegate(this, &DescriptionParser::Other);
438 virtual void Accept(const Element& element)
440 m_lang = element.lang;
444 ElementParserPtr Other()
446 return ElementParserPtr(new InnerElementsParser(
447 DPL::StaticPointerCast<ElementParser>(
451 virtual void Accept(const Text& text)
453 if (m_description.IsNull()) {
454 m_description = text.value;
456 *m_description += text.value;
460 virtual void Accept(const XmlAttribute& attribute)
462 if (attribute.name == L"dir") {
463 m_textDirection = Unicode::ParseDirAttribute(attribute);
467 virtual void Verify()
469 ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
470 if (data.description.IsNull()) {
471 if (!m_description.IsNull()) {
472 Unicode::UpdateTextWithDirectionMark(m_textDirection,
475 data.description = m_description;
479 DescriptionParser(Unicode::Direction direction,
480 ConfigParserData& data) :
484 m_textDirection(direction)
489 ConfigParserData& m_data;
491 DPL::OptionalString m_description;
492 Unicode::Direction m_textDirection;
495 class AuthorParser : public ElementParser
498 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
499 const DPL::String& /*name*/)
501 return DPL::MakeDelegate(this, &AuthorParser::Other);
504 AuthorParser(Unicode::Direction direction,
505 ConfigParserData& data) :
507 m_textDirection(direction)
511 virtual void Accept(const Element& /*element*/)
516 virtual void Accept(const Text& text)
518 *(m_authorName) += text.value;
521 virtual void Accept(const XmlAttribute& attribute)
523 if (attribute.name == L"href") {
524 //Validate href IRI and ignore it if invalid
525 //See also test: ta-argMozRiC-an
526 LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
527 if (iri.Validate()) {
528 m_authorHref = attribute.value;
530 } else if (attribute.name == L"email") {
531 m_authorEmail = attribute.value;
532 } else if (attribute.name == L"dir") {
533 m_textDirection = Unicode::ParseDirAttribute(attribute);
537 virtual void Verify()
539 if (!m_data.authorName && !m_data.authorHref && !m_data.authorEmail) {
540 NormalizeString(m_authorName);
541 NormalizeString(m_authorHref);
542 NormalizeString(m_authorEmail);
543 if (!!m_authorName) {
544 Unicode::UpdateTextWithDirectionMark(m_textDirection,
546 m_data.authorName = m_authorName;
548 if (!!m_authorHref) {
549 m_data.authorHref = m_authorHref;
551 if (!!m_authorEmail) {
552 m_data.authorEmail = m_authorEmail;
557 ElementParserPtr Other()
559 return ElementParserPtr(new InnerElementsParser(
560 DPL::StaticPointerCast<ElementParser>(
565 ConfigParserData& m_data;
566 DPL::OptionalString m_authorEmail;
567 DPL::OptionalString m_authorHref;
568 DPL::OptionalString m_authorName;
569 Unicode::Direction m_textDirection;
572 class LicenseParser : public ElementParser
575 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
576 const DPL::String& /*name*/)
578 return DPL::MakeDelegate(this, &LicenseParser::Other);
581 LicenseParser(Unicode::Direction direction,
582 ConfigParserData& data) :
585 m_textDirection(direction)
589 virtual void Accept(const Element& element)
591 if (m_license.IsNull()) {
592 m_lang = element.lang;
598 virtual void Accept(const Text& text)
601 *m_license += text.value;
605 virtual void Accept(const XmlAttribute& attribute)
608 if (attribute.name == L"href" && m_licenseHref.IsNull()) {
609 m_licenseHref = attribute.value;
610 } else if (attribute.name == L"file" && m_licenseFile.IsNull()) {
611 m_licenseFile = attribute.value;
612 } else if (attribute.name == L"dir") {
613 m_textDirection = Unicode::ParseDirAttribute(attribute);
618 virtual void Verify()
620 ConfigParserData::LocalizedData& data = m_data.localizedDataSet[m_lang];
621 if (data.license.IsNull()) {
622 if (!m_license.IsNull()) {
623 Unicode::UpdateTextWithDirectionMark(m_textDirection,
626 data.license = m_license;
627 data.licenseHref = m_licenseHref;
628 data.licenseFile = m_licenseFile;
632 ElementParserPtr Other()
634 return ElementParserPtr(new InnerElementsParser(
635 ElementParserPtr(SharedFromThis())));
639 ConfigParserData& m_data;
643 DPL::OptionalString m_license;
644 DPL::OptionalString m_licenseFile;
645 DPL::OptionalString m_licenseHref;
646 Unicode::Direction m_textDirection;
649 class IconParser : public ElementParser
652 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
653 const DPL::String& /*name*/)
655 return &IgnoringParser::Create;
658 IconParser(ConfigParserData& data) : ElementParser(),
663 virtual void Accept(const Element& /*element*/)
667 virtual void Accept(const XmlAttribute& attribute)
669 if (attribute.name == L"src") {
670 if (attribute.value.size() > 0) {
671 m_src = attribute.value;
673 } else if (attribute.name == L"width") {
674 m_width = ParseSizeAttributeValue(attribute.value);
675 } else if (attribute.name == L"height") {
676 m_height = ParseSizeAttributeValue(attribute.value);
680 virtual void Accept(const Text& /*text*/)
682 ThrowMsg(Exception::ParseError, "Icon element must be empty");
685 virtual void Verify()
687 if (m_src.IsNull()) {
688 LogWarning("src attribute of icon element is mandatory - ignoring");
692 ConfigParserData::Icon icon(*m_src);
693 icon.width = m_width;
694 icon.height = m_height;
696 ConfigParserData::IconsList::iterator it = std::find(
697 m_data.iconsList.begin(), m_data.iconsList.end(), icon);
698 if (it == m_data.iconsList.end()) {
699 m_data.iconsList.push_front(icon);
704 ConfigParserData& m_data;
705 DPL::OptionalString m_src;
706 DPL::OptionalInt m_width;
707 DPL::OptionalInt m_height;
709 static DPL::OptionalInt ParseSizeAttributeValue(const DPL::String& value)
711 DPL::OptionalString normalizedValue = value;
712 NormalizeString(normalizedValue);
713 if (!(*normalizedValue).empty()) {
717 strtol(DPL::ToUTF8String(value).c_str(), &reterr, 10);
719 std::string(reterr) == DPL::ToUTF8String(value) ||
721 return DPL::OptionalInt::Null;
726 return DPL::OptionalInt::Null;
730 class ContentParser : public ElementParser
733 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
734 const DPL::String& /*name*/)
736 return &IgnoringParser::Create;
739 ContentParser(ConfigParserData& data) :
745 virtual void Accept(const Element& /*element*/)
749 virtual void Accept(const Text& /*text*/)
753 virtual void Accept(const XmlAttribute& attribute)
755 DPL::String value = attribute.value;
756 NormalizeString(value);
758 if (attribute.name == L"src") {
760 } else if (attribute.name == L"type") {
762 MimeTypeUtils::MimeAttributes mimeAttributes =
763 MimeTypeUtils::getMimeAttributes(value);
764 if (mimeAttributes.count(L"charset") > 0) {
765 m_encoding = mimeAttributes[L"charset"];
767 } else if (attribute.name == L"encoding") {
768 if (!value.empty()) {
774 virtual void Verify()
776 if (m_data.startFileEncountered) {
777 LogWarning("This is not the first encountered "
778 "'content' element - ignoring.");
782 m_data.startFileEncountered = true;
784 //we're consciously setting startFile even if m_src is null or invalid.
785 //WidgetConfigurationManager will deal with this.
786 m_data.startFile = m_src;
789 m_data.startFileContentType = m_type;
790 if (!!m_encoding && ewk_text_encoding_is_valid(
791 DPL::ToUTF8String(*m_encoding).c_str())) {
792 m_data.startFileEncoding = m_encoding;
794 m_data.startFileEncoding = L"UTF-8";
800 DPL::OptionalString m_src;
801 DPL::OptionalString m_type;
802 DPL::OptionalString m_encoding;
803 ConfigParserData& m_data;
806 class FeatureParser : public ElementParser
809 struct ParamParser : public ElementParser
811 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
812 const DPL::String& /*name*/)
814 return &IgnoringParser::Create;
817 virtual void Accept(const XmlAttribute& attribute)
819 if (attribute.name == L"name") {
820 m_name = attribute.value;
821 NormalizeString(m_name);
822 } else if (attribute.name == L"value") {
823 m_value = attribute.value;
824 NormalizeString(m_value);
828 virtual void Accept(const Element& /*element*/)
832 virtual void Accept(const Text& /*text*/)
834 ThrowMsg(Exception::ParseError, "param element must be empty");
837 virtual void Verify()
839 if (m_name.IsNull() || *m_name == L"") {
842 if (m_value.IsNull() || *m_value == L"") {
846 ConfigParserData::Param param(*m_name);
847 param.value = *m_value;
849 if (m_data.paramsList.find(param) == m_data.paramsList.end()) {
850 m_data.paramsList.insert(param);
854 ParamParser(ConfigParserData::Feature& data) :
861 DPL::OptionalString m_name;
862 DPL::OptionalString m_value;
863 ConfigParserData::Feature& m_data;
866 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
867 const DPL::String& name)
869 if (name == L"param") {
870 return DPL::MakeDelegate(this, &FeatureParser::OnParamElement);
872 return &IgnoringParser::Create;
876 virtual void Accept(const Text& /*text*/)
880 virtual void Accept(const Element& /*element*/)
884 virtual void Accept(const XmlAttribute& attribute)
886 if (attribute.name == L"name") {
887 m_feature.name = attribute.value;
888 } else if (attribute.name == L"required") {
889 if (attribute.value == L"false") {
890 m_feature.required = false;
892 m_feature.required = true;
897 virtual void Verify()
899 LibIri::Wrapper iri(DPL::ToUTF8String(m_feature.name).c_str());
901 if (m_feature.name != L"") {
902 if (iri.Validate()) {
903 if (m_data.featuresList.find(m_feature) ==
904 m_data.featuresList.end()) {
905 m_data.featuresList.insert(m_feature);
907 LogDebug("Ignoring feature with name" <<
908 DPL::ToUTF8String(m_feature.name));
911 if (m_feature.required) {
912 //Throw only if required
913 ThrowMsg(Exception::ParseError, "invalid feature IRI");
919 ElementParserPtr OnParamElement()
921 return ElementParserPtr(new ParamParser(m_feature));
924 FeatureParser(ConfigParserData& data) :
932 ConfigParserData& m_data;
933 ConfigParserData::Feature m_feature;
936 class PreferenceParser : public ElementParser
939 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
940 const DPL::String& /*name*/)
942 return &IgnoringParser::Create;
945 virtual void Accept(const XmlAttribute& attribute)
947 if (attribute.name == L"name") {
948 m_name = attribute.value;
949 } else if (attribute.name == L"value") {
950 m_value = attribute.value;
951 } else if (attribute.name == L"readonly") {
952 if (attribute.value == L"true") {
960 virtual void Accept(const Element& /*element*/)
964 virtual void Accept(const Text& /*text*/)
966 ThrowMsg(Exception::ParseError, "param element must be empty");
969 virtual void Verify()
971 if (m_name.IsNull()) {
972 LogWarning("preference element must have name attribute");
975 NormalizeString(m_name);
976 NormalizeString(m_value);
977 ConfigParserData::Preference preference(*m_name, m_required);
978 preference.value = m_value;
979 if (m_data.preferencesList.find(preference) ==
980 m_data.preferencesList.end()) {
981 m_data.preferencesList.insert(preference);
985 PreferenceParser(ConfigParserData& data) :
993 DPL::OptionalString m_name;
994 DPL::OptionalString m_value;
996 ConfigParserData& m_data;
999 class FlashParser : public ElementParser
1002 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1003 const DPL::String& /*name*/)
1005 return &IgnoringParser::Create;
1008 virtual void Accept(const XmlAttribute& attribute)
1010 if (attribute.name == L"needed") {
1011 if (attribute.value == L"true") {
1012 m_flashNeeded = true;
1014 m_flashNeeded = false;
1019 virtual void Accept(const Element& /*element*/)
1021 //if empty flash element will be passed, we say true
1022 m_data.flashNeeded = true;
1025 virtual void Accept(const Text& /*text*/)
1027 ThrowMsg(Exception::ParseError, "flash element must be empty");
1030 virtual void Verify()
1032 m_data.flashNeeded = m_flashNeeded;
1035 FlashParser(ConfigParserData& data) :
1037 m_flashNeeded(false),
1044 ConfigParserData& m_data;
1047 class LinkParser : public ElementParser
1050 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1051 const DPL::String& /*name*/)
1053 return &DenyAllParser::Create;
1056 virtual void Accept(const XmlAttribute& attribute)
1058 if (m_properNamespace) {
1059 LogDebug("attribute");
1060 if (attribute.name == L"rel") {
1061 if (attribute.value != L"describedby") {
1062 ThrowMsg(Exception::ParseError,
1063 "rel attribute must have describedby value");
1065 } else if (attribute.name == L"type") {
1066 } else if (attribute.name == L"href") {
1067 LogDebug("here is href");
1068 m_href = attribute.value;
1070 ThrowMsg(Exception::ParseError,
1071 "unknown attribute '" +
1072 DPL::ToUTF8String(attribute.name) +
1073 "' in link element");
1078 virtual void Accept(const Element& element)
1081 ConfigurationNamespace::WacWidgetNamespaceNameForLinkElement)
1083 m_properNamespace = true;
1085 LogDebug("element");
1088 virtual void Accept(const Text&)
1090 if (m_properNamespace) {
1092 ThrowMsg(Exception::ParseError, "link element must be empty");
1096 virtual void Verify()
1099 ThrowMsg(Exception::ParseError,
1100 "link element must have href attribute");
1103 LibIri::Wrapper iri(DPL::ToUTF8String(*m_href).c_str());
1104 if (!iri.Validate()) { // TODO: Better uri validator ?
1105 ThrowMsg(Exception::ParseError,
1106 "href attribute must be a valid iri/uri/url");
1109 m_data.powderDescriptionLinks.insert(*m_href);
1112 LinkParser(ConfigParserData& data) :
1114 m_properNamespace(false),
1116 m_href(DPL::OptionalString::Null)
1121 bool m_properNamespace;
1122 ConfigParserData& m_data;
1123 DPL::OptionalString m_href;
1126 class MinVersionParser : public ElementParser
1129 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1130 const DPL::String& /*name*/)
1132 return &DenyAllParser::Create;
1135 virtual void Accept(const XmlAttribute& attribute)
1137 if (m_properNamespace) {
1138 ThrowMsg(Exception::ParseError,
1139 "attirubte: '" + DPL::ToUTF8String(attribute.name) +
1140 "' in min-version element not allowed");
1144 virtual void Accept(const Element& element)
1146 if (element.ns == ConfigurationNamespace::WacWidgetNamespaceName) {
1147 m_properNamespace = true;
1150 LogDebug("element min-version");
1153 virtual void Accept(const Text& text)
1155 if (m_properNamespace) {
1156 m_minVersion = text.value;
1157 LogDebug("min-version value: " << m_minVersion);
1161 virtual void Verify()
1163 if (m_properNamespace) {
1164 if (m_minVersion.IsNull()) {
1165 ThrowMsg(Exception::ParseError,
1166 "min-version element must have value");
1169 DPL::OptionalFloat version = ParseMinVersion(*m_minVersion);
1170 if (version.IsNull()) {
1171 ThrowMsg(Exception::ParseError,
1172 "min-version element must have value"
1173 " that can be parsed to float");
1176 if (m_data.minVersionRequiredFound.IsNull()) {
1177 m_data.minVersionRequiredFound = 1;
1178 m_data.minVersionRequired = version;
1179 LogDebug("MinVersionRequired = " << version);
1181 ThrowMsg(Exception::ParseError,
1182 "multiple min-version elements not allowed");
1187 MinVersionParser(ConfigParserData& data) :
1189 m_properNamespace(false),
1193 LogDebug("MinVersionParser created");
1197 bool m_properNamespace;
1198 ConfigParserData& m_data;
1199 DPL::OptionalString m_minVersion;
1201 static DPL::OptionalFloat ParseMinVersion(const DPL::String& value)
1203 DPL::OptionalString normalizedValue = value;
1204 NormalizeString(normalizedValue);
1205 if (!(*normalizedValue).empty()) {
1206 char* reterr = NULL;
1209 strtof(DPL::ToUTF8String(value).c_str(), &reterr);
1211 std::string(reterr) == DPL::ToUTF8String(value) ||
1212 valueFloat <= 0.0) {
1213 return DPL::OptionalFloat::Null;
1218 return DPL::OptionalFloat::Null;
1222 // tag: <back supported=true>
1223 class BackParser : public ElementParser
1226 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1227 const DPL::String& /*name*/)
1229 return &IgnoringParser::Create;
1232 virtual void Accept(const XmlAttribute& attribute)
1234 LogDebug("attribute");
1235 if (attribute.name == L"supported") {
1236 if (attribute.value == L"true") {
1237 m_backSupported = true;
1239 m_backSupported = false;
1244 virtual void Accept(const Element&)
1246 LogDebug("element");
1247 //if empty back element will be passed, we say true
1248 m_data.backSupported = true;
1251 virtual void Accept(const Text&)
1254 ThrowMsg(Exception::ParseError, "back element must be empty");
1257 virtual void Verify()
1259 m_data.backSupported = m_backSupported;
1262 BackParser(ConfigParserData& data) :
1264 m_backSupported(false),
1270 bool m_backSupported;
1271 ConfigParserData& m_data;
1274 class SettingParser : public ElementParser
1277 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1278 const DPL::String& /*name*/)
1280 return &IgnoringParser::Create;
1283 virtual void Accept(const Text& /*text*/)
1287 virtual void Accept(const Element& /*element*/)
1291 virtual void Accept(const XmlAttribute& attribute)
1293 m_setting.m_name = attribute.name;
1294 m_setting.m_value = attribute.value;
1295 m_data.settingsList.insert(m_setting);
1298 virtual void Verify()
1302 SettingParser(ConfigParserData& data) :
1310 ConfigParserData& m_data;
1311 ConfigParserData::Setting m_setting;
1314 class ServiceParser : public ElementParser
1317 virtual ActionFunc GetElementParser(const DPL::String& /*ns*/,
1318 const DPL::String& /*name*/)
1320 return &IgnoringParser::Create;
1323 virtual void Accept(const XmlAttribute& attribute)
1325 if (attribute.name == L"src") {
1326 m_src = attribute.value;
1327 } else if (attribute.name == L"operation") {
1328 m_operation = attribute.value;
1329 } else if (attribute.name == L"scheme") {
1330 m_scheme = attribute.value;
1331 } else if (attribute.name == L"mime") {
1332 m_mime = attribute.value;
1336 virtual void Accept(const Element& element)
1338 LogWarning("namespace for app service = " << element.ns);
1339 if (element.ns == ConfigurationNamespace::W3CWidgetNamespaceName) {
1340 ThrowMsg(Exception::ParseError,
1341 "Wrong xml namespace for widget element");
1345 virtual void Accept(const Text& /*text*/)
1347 ThrowMsg(Exception::ParseError, "param element must be empty");
1350 virtual void Verify()
1352 if (m_src.IsNull()) {
1353 LogWarning("service element must have target attribute");
1355 } else if (m_operation.IsNull()) {
1356 LogWarning("service element must have operation attribute");
1359 NormalizeString(m_src);
1360 NormalizeString(m_operation);
1361 NormalizeString(m_scheme);
1362 NormalizeString(m_mime);
1364 // verify duplicate element
1365 DPL::String wildString(L"*/*");
1366 DPL::String nullString(L"");
1367 ConfigParserData::ServiceInfo serviceInfo(
1368 m_src.IsNull() ? nullString:*m_src,
1369 m_operation.IsNull() ? nullString:*m_operation,
1370 m_scheme.IsNull() ? nullString:*m_scheme,
1371 m_mime.IsNull() ? nullString:*m_mime);
1373 FOREACH(iterator, m_data.appServiceList) {
1374 if (iterator->m_operation == serviceInfo.m_operation &&
1376 (iterator->m_scheme == serviceInfo.m_scheme ||
1377 // check input scheme is "*/*" case
1378 (iterator->m_scheme == wildString &&
1379 serviceInfo.m_scheme != nullString) ||
1380 // check iterator scheme is "*/*" case
1381 (serviceInfo.m_scheme == wildString &&
1382 iterator->m_scheme != nullString)) &&
1384 (iterator->m_mime == serviceInfo.m_mime ||
1385 // check input mime is "*/*" case
1386 (iterator->m_mime == wildString &&
1387 serviceInfo.m_mime != nullString) ||
1388 // check iterator mime is "*/*" case
1389 (serviceInfo.m_mime == wildString &&
1390 iterator->m_mime != nullString)))
1392 ThrowMsg(Exception::ParseError,
1393 "service operation is duplicated " +
1394 DPL::ToUTF8String(*m_operation));
1397 m_data.appServiceList.push_back(serviceInfo);
1400 ServiceParser(ConfigParserData& data) :
1402 m_src(DPL::OptionalString::Null),
1403 m_operation(DPL::OptionalString::Null),
1404 m_scheme(DPL::OptionalString::Null),
1405 m_mime(DPL::OptionalString::Null),
1411 DPL::OptionalString m_src;
1412 DPL::OptionalString m_operation;
1413 DPL::OptionalString m_scheme;
1414 DPL::OptionalString m_mime;
1415 ConfigParserData& m_data;
1418 ElementParser::ActionFunc WidgetParser::GetElementParser(const DPL::String& /*ns*/,
1419 const DPL::String& name)
1421 FuncMap::const_iterator it = m_map.find(name);
1422 if (it != m_map.end()) {
1425 return &IgnoringParser::Create;
1429 WidgetParser::WidgetParser(ConfigParserData& data) :
1431 m_textDirection(Unicode::EMPTY)
1433 m_map[L"name"] = DPL::MakeDelegate(this, &WidgetParser::OnNameElement);
1434 m_map[L"access"] = DPL::MakeDelegate(this, &WidgetParser::OnAccessElement);
1435 m_map[L"description"] =
1436 DPL::MakeDelegate(this, &WidgetParser::OnDescriptionElement);
1437 m_map[L"author"] = DPL::MakeDelegate(this, &WidgetParser::OnAuthorElement);
1439 DPL::MakeDelegate(this, &WidgetParser::OnLicenseElement);
1440 m_map[L"icon"] = DPL::MakeDelegate(this, &WidgetParser::OnIconElement);
1442 DPL::MakeDelegate(this, &WidgetParser::OnContentElement);
1444 DPL::MakeDelegate(this, &WidgetParser::OnFeatureElement);
1445 m_map[L"preference"] =
1446 DPL::MakeDelegate(this, &WidgetParser::OnPreferenceElement);
1447 m_map[L"flash"] = DPL::MakeDelegate(this, &WidgetParser::OnFlashElement);
1448 m_map[L"link"] = DPL::MakeDelegate(this, &WidgetParser::OnLinkElement);
1449 m_map[L"min-version"] =
1450 DPL::MakeDelegate(this, &WidgetParser::OnMinVersionElement);
1451 m_map[L"back"] = DPL::MakeDelegate(this, &WidgetParser::OnBackElement);
1452 m_map[L"pkgname"] = DPL::MakeDelegate(this, &WidgetParser::OnPkgnameElement);
1454 DPL::MakeDelegate(this, &WidgetParser::OnSettingElement);
1455 m_map[L"appservice"] = DPL::MakeDelegate(this, &WidgetParser::OnServiceElement);
1458 ElementParserPtr WidgetParser::OnNameElement()
1460 return ElementParserPtr(new NameParser(m_textDirection, m_data));
1463 ElementParserPtr WidgetParser::OnAccessElement()
1465 return ElementParserPtr(new AccessParser(m_data));
1468 ElementParserPtr WidgetParser::OnDescriptionElement()
1470 return ElementParserPtr(new DescriptionParser(m_textDirection, m_data));
1473 ElementParserPtr WidgetParser::OnAuthorElement()
1475 return ElementParserPtr(new AuthorParser(m_textDirection, m_data));
1478 ElementParserPtr WidgetParser::OnLicenseElement()
1480 return ElementParserPtr(new LicenseParser(m_textDirection, m_data));
1483 ElementParserPtr WidgetParser::OnIconElement()
1485 return ElementParserPtr(new IconParser(m_data));
1488 ElementParserPtr WidgetParser::OnContentElement()
1490 return ElementParserPtr(new ContentParser(m_data));
1493 ElementParserPtr WidgetParser::OnFeatureElement()
1495 return ElementParserPtr(new FeatureParser(m_data));
1498 ElementParserPtr WidgetParser::OnPreferenceElement()
1500 return ElementParserPtr(new PreferenceParser(m_data));
1503 ElementParserPtr WidgetParser::OnFlashElement()
1505 return ElementParserPtr(new FlashParser(m_data));
1508 ElementParserPtr WidgetParser::OnLinkElement()
1510 return ElementParserPtr(new LinkParser(m_data));
1513 ElementParserPtr WidgetParser::OnMinVersionElement()
1515 return ElementParserPtr(new MinVersionParser(m_data));
1518 ElementParserPtr WidgetParser::OnBackElement()
1520 return ElementParserPtr(new BackParser(m_data));
1523 ElementParserPtr WidgetParser::OnPkgnameElement()
1525 return ElementParserPtr(new PkgnameParser(m_data));
1528 ElementParserPtr WidgetParser::OnSettingElement()
1530 return ElementParserPtr(new SettingParser(m_data));
1533 ElementParserPtr WidgetParser::OnServiceElement()
1535 return ElementParserPtr(new ServiceParser(m_data));
1538 void WidgetParser::Accept(const Element& element)
1540 if (element.ns != ConfigurationNamespace::W3CWidgetNamespaceName) {
1541 ThrowMsg(Exception::ParseError,
1542 "Wrong xml namespace for widget element");
1546 void WidgetParser::Accept(const Text& /*text*/)
1548 ThrowMsg(Exception::ParseError, "widged element must be empty");
1551 void WidgetParser::Accept(const XmlAttribute& attribute)
1553 if (attribute.name == L"id") {
1554 LibIri::Wrapper iri(DPL::ToUTF8String(attribute.value).c_str());
1555 //If may important tests starts to fail this test we will have
1556 //to consider commenting this test out again.
1557 if (iri.Validate()) {
1558 m_data.widget_id = attribute.value;
1559 NormalizeString(m_data.widget_id);
1561 } else if (attribute.name == L"version") {
1562 m_version = attribute.value;
1563 NormalizeString(m_version);
1564 } else if (attribute.name == L"height") {
1565 DPL::OptionalString value = attribute.value;
1566 NormalizeString(value);
1567 std::string v = DPL::ToUTF8String(*value);
1570 unsigned char c = v.c_str()[0];
1571 if (c >= '0' && c <= '9') {
1573 for (size_t i = 0; i < v.size(); ++i) {
1575 if (c >= '0' && c <= '9') {
1582 m_data.height = val;
1585 } else if (attribute.name == L"width") {
1586 DPL::OptionalString value = attribute.value;
1587 NormalizeString(value);
1588 std::string v = DPL::ToUTF8String(*value);
1591 unsigned char c = v.c_str()[0];
1592 if (c >= '0' && c <= '9') {
1594 for (size_t i = 0; i < v.size(); ++i) {
1596 if (c >= '0' && c <= '9') {
1606 } else if (attribute.name == L"viewmodes") {
1607 DPL::Tokenize(attribute.value,
1609 std::inserter(m_windowModes,
1610 m_windowModes.end()),
1612 } else if (attribute.name == L"dir") {
1613 m_textDirection = Unicode::ParseDirAttribute(attribute);
1614 } else if (L"defaultlocale" == attribute.name) {
1615 if (!m_defaultlocale) {
1616 m_defaultlocale = attribute.value;
1617 NormalizeString(m_defaultlocale);
1618 if (!LanguageSubtagRstTreeSingleton::Instance().ValidateLanguageTag(
1619 DPL::ToUTF8String(*m_defaultlocale))) {
1620 LogWarning("Language tag: " <<
1621 m_defaultlocale << " is not valid");
1622 m_defaultlocale = DPL::OptionalString::Null;
1625 LogDebug("Default Locale Found " << m_defaultlocale);
1627 LogWarning("Ignoring subsequent default locale");
1629 } else if (DPL::StringCompare(L"xmlns", attribute.name) < 0) {
1630 LogWarning("namespace domain" << attribute.name);
1631 LogWarning("namespace value " << attribute.value);
1632 DPL::OptionalString ns = attribute.value;
1634 if (attribute.name == L"xmlns:wac") {
1635 m_nameSpaces.push_back(attribute.value);
1636 } else if (attribute.name == L"xmlns:tizen") {
1637 m_nameSpaces.push_back(attribute.value);
1638 } else if (attribute.name == L"xmlns:jil") {
1639 m_nameSpaces.push_back(attribute.value);
1644 void WidgetParser::Verify()
1646 FOREACH(mode, m_windowModes) {
1647 if (L"windowed" == *mode || L"floating" == *mode ||
1648 L"fullscreen" == *mode || L"maximized" == *mode ||
1649 L"minimized" == *mode) {
1650 m_data.windowModes.insert(*mode);
1653 if (!m_version.IsNull()) {
1654 Unicode::UpdateTextWithDirectionMark(m_textDirection, &*m_version);
1655 m_data.version = m_version;
1657 m_data.defaultlocale = m_defaultlocale;
1658 FOREACH(ns, m_nameSpaces) {
1659 m_data.nameSpaces.insert(*ns);