Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Baranyi, Botond | |
11 | * Ormandi, Matyas | |
12 | * Raduly, Csaba | |
13 | * | |
14 | ******************************************************************************/ | |
970ed795 EL |
15 | #define DEFINE_XER_STRUCT |
16 | #include "XER.hh" | |
17 | ||
18 | //#include <libxml/xmlreader.h> | |
19 | #include "XmlReader.hh" | |
20 | #include "Module_list.hh" | |
21 | ||
22 | // FIXME: there ought to be a better way than this | |
23 | static const char indent_buffer[] = | |
24 | // --------------------------- 32 ----------------------------- || | |
25 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //1 | |
26 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //2 | |
27 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //3 | |
28 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //4 | |
29 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //5 | |
30 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //6 | |
31 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //7 | |
32 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //8 | |
33 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //9 | |
34 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //10 | |
35 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //11 | |
36 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //12 | |
37 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //13 | |
38 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //14 | |
39 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" //15 | |
40 | "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";//16 | |
41 | ||
42 | // FIXME do_indent's level should be size_t, but there were plans of passing negative values | |
43 | int do_indent(TTCN_Buffer& buf, int level) | |
44 | { | |
45 | if (level > 0 && level < (int)sizeof(indent_buffer)) { | |
46 | buf.put_s((size_t)level, (const unsigned char*)indent_buffer); | |
47 | } | |
48 | return level; | |
49 | } | |
50 | ||
51 | const char* verify_name(XmlReaderWrap& reader, const XERdescriptor_t& p_td, int exer) | |
52 | { | |
53 | const char *name = (const char*)reader.LocalName(); | |
54 | const char *nsuri= (const char*)reader.NamespaceUri(); // NULL if no ns | |
55 | ||
56 | const namespace_t *expected_ns = 0; | |
57 | if (p_td.my_module != 0 && p_td.ns_index != -1) { | |
58 | expected_ns = p_td.my_module->get_ns(p_td.ns_index); | |
59 | } | |
60 | ||
61 | if (0 == name) { | |
62 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
63 | "NULL XML name instead of `%.*s'", | |
64 | p_td.namelens[exer]-2, p_td.names[exer]); | |
65 | } | |
66 | if (!check_name(name, p_td, exer)) { | |
67 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
68 | "Bad XML tag `%s' instead of `%.*s'", | |
69 | name, p_td.namelens[exer]-2, p_td.names[exer]); | |
70 | } | |
71 | ||
72 | if (exer) { // XML namespaces only apply to EXER | |
73 | const char *prefix = (const char*)reader.Prefix(); // may be NULL | |
74 | if (expected_ns == 0) { // get_ns was not called | |
75 | if (nsuri != 0) { | |
76 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
77 | "Unexpected namespace '%s' (%s)", nsuri, prefix ? prefix : ""); | |
78 | } | |
79 | } | |
80 | else { // a namespace was expected | |
81 | if (p_td.xer_bits & FORM_UNQUALIFIED) { | |
82 | if (prefix && *prefix) TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
83 | "Unexpected prefix '%s'", prefix); | |
84 | } | |
85 | else { | |
86 | if (nsuri == 0) { // XML node has no namespace | |
87 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
88 | "Missing namespace '%s'", expected_ns->ns); | |
89 | } | |
90 | else { // and there is one, but is it the right one ? | |
91 | if (strcmp(nsuri, expected_ns->ns)) { | |
92 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
93 | "Bad XML namespace `%s' instead of `%s'", nsuri, expected_ns->ns); | |
94 | } | |
95 | } | |
96 | } | |
97 | } | |
98 | } // if exer | |
99 | ||
100 | return name; | |
101 | } | |
102 | ||
103 | void verify_end(XmlReaderWrap& reader, const XERdescriptor_t& p_td, const int depth, int exer) | |
104 | { | |
105 | TTCN_EncDec_ErrorContext endcontext("While checking end tag: "); | |
106 | verify_name(reader, p_td, exer); | |
107 | const int currdepth = reader.Depth(); | |
108 | if (currdepth!=depth) { | |
109 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG, | |
110 | "Bad depth in XML, %d instead of %d", currdepth, depth); | |
111 | } | |
112 | } | |
113 | ||
114 | // This should be called for EXER only | |
115 | bool check_namespace(const char *ns_uri, const XERdescriptor_t& p_td) | |
116 | { | |
117 | if (p_td.my_module==0 || p_td.ns_index==-1) {// no namespace in XER descriptor | |
118 | return ns_uri==0 || *ns_uri=='\0'; // there should be no ns | |
119 | } | |
120 | else { | |
121 | const namespace_t *expected_ns = p_td.my_module->get_ns(p_td.ns_index); | |
122 | if (ns_uri!=0) return strcmp(ns_uri, expected_ns->ns)==0; | |
123 | else return true; // if no namespace we presume it's the expected one | |
124 | } | |
125 | } | |
126 | ||
127 | void write_ns_prefix(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf) | |
128 | { | |
129 | if (p_td.my_module != 0 && p_td.ns_index != -1 | |
130 | && !(p_td.xer_bits & FORM_UNQUALIFIED)) { | |
131 | const namespace_t *my_ns = p_td.my_module->get_ns(p_td.ns_index); | |
132 | if (my_ns->px[0] != 0) { // not an empty prefix | |
133 | p_buf.put_s(strlen(my_ns->px), (cbyte*)my_ns->px); | |
134 | p_buf.put_c(':'); | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
51fa56b9 | 139 | const char* get_ns_uri_from_prefix(const char *prefix, const XERdescriptor_t& p_td) |
140 | { | |
141 | if (p_td.my_module != 0 && prefix != NULL && prefix[0] != 0) { | |
142 | for (size_t i = 0; i < p_td.my_module->get_num_ns(); ++i) { | |
143 | const namespace_t *ns = p_td.my_module->get_ns(i); | |
144 | if (ns->px != NULL && strcmp(ns->px, prefix) == 0) { | |
145 | return ns->ns; | |
146 | } | |
147 | } | |
148 | } | |
149 | return NULL; | |
150 | } | |
151 | ||
970ed795 EL |
152 | void check_namespace_restrictions(const XERdescriptor_t& p_td, const char* p_xmlns) |
153 | { | |
154 | // In case of "anyElement from ..." matching namespaces is good | |
155 | // in case of "anyElement except ..." matching namespaces is bad | |
156 | bool ns_match_allowed = (p_td.xer_bits & ANY_FROM) ? true : false; | |
157 | ||
158 | bool ns_error = ns_match_allowed; | |
159 | for (unsigned short idx = 0; idx < p_td.nof_ns_uris; ++idx) { | |
160 | if ((p_xmlns == 0 && strlen(p_td.ns_uris[idx]) == 0) || | |
161 | (p_xmlns != 0 && strcmp(p_td.ns_uris[idx], p_xmlns) == 0)) | |
162 | { | |
163 | ns_error = !ns_match_allowed; | |
164 | break; | |
165 | } | |
166 | } | |
167 | ||
168 | if (ns_error) { | |
169 | if (p_xmlns) { | |
170 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, | |
171 | "XML namespace \"%s\" is %s namespace list.", p_xmlns, ns_match_allowed ? "not in the allowed" : "in the excluded"); | |
172 | } | |
173 | else { | |
174 | TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, | |
175 | "The unqualified XML namespace is %s namespace list.", ns_match_allowed ? "not in the allowed" : "in the excluded"); | |
176 | } | |
177 | } | |
178 | } |