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