source: proto/parabix2/src/xmldecl.c @ 527

Last change on this file since 527 was 527, checked in by lindanl, 9 years ago

encoding name validation

File size: 8.3 KB
Line 
1/*  xmldecl.c - Parsing XML and Text Declarations.
2    Copyright (c) 2008, Robert D. Cameron.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6
7*/
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/types.h>
12
13#include "xmldecl.h"
14#include "xml_error.h"
15#include "multiliteral.h"
16#include "bytelex.h"
17
18
19Entity_Info::Entity_Info() {
20        encoding = NULL;
21}
22Entity_Info::~Entity_Info() {
23        delete [] encoding;
24}
25
26/* Signature-based character set family detection in accord with
27   Appendix F of the XML 1.0 and 1.1 specifications. */
28
29/* These definitions use b2int16 to determine appropriate doublebyte
30   values based on endianness of the underlying architecture. */
31static const int x0000 = b2int16<0x00, 0x00>::value;
32static const int xFEFF = b2int16<0xFE, 0xFF>::value;
33static const int xFFFE = b2int16<0xFF, 0xFE>::value;
34static const int x003C = b2int16<0x00, 0x3C>::value;
35static const int x3C00 = b2int16<0x3C, 0x00>::value;
36static const int x4C6F = b2int16<0x4C, 0x6F>::value;
37static const int xA794 = b2int16<0xA7, 0x94>::value;
38static const int xEFBE = b2int16<0xEF, 0xBE>::value;
39
40void Entity_Info::AnalyzeSignature(unsigned char * signature) {
41        uint16_t * XML_dbl_byte = (uint16_t *) signature;
42        switch (XML_dbl_byte[0]) {
43                case x0000:
44                        switch (XML_dbl_byte[1]) {
45                                case xFEFF: set_charset_family(ASCII, QuadByte, BigEndian, 1);break;
46                                case xFFFE: set_charset_family(ASCII, QuadByte, Unusual_2143, 1);break;
47                                case x3C00: set_charset_family(ASCII, QuadByte, Unusual_2143, 0);break;
48                                default: set_charset_family(ASCII, QuadByte, BigEndian, 0);
49                        }
50                        break;
51                case xFEFF:
52                        if (XML_dbl_byte[1] == x0000)
53                                set_charset_family(ASCII, QuadByte, Unusual_3412, 1);
54                        else set_charset_family(ASCII, DoubleByte, BigEndian, 1);
55                        break;
56                case xFFFE:
57                        if (XML_dbl_byte[1] == x0000)
58                                set_charset_family(ASCII, QuadByte, LittleEndian, 1);
59                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 1);
60                        break;
61                case x003C:
62                        if (XML_dbl_byte[1] == x0000)
63                                set_charset_family(ASCII, QuadByte, Unusual_3412, 0);
64                        else set_charset_family(ASCII, DoubleByte, BigEndian, 0);
65                        break;
66                case x3C00:
67                        if (XML_dbl_byte[1] == x0000)
68                                set_charset_family(ASCII, QuadByte, LittleEndian, 0);
69                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 0);
70                        break;
71                case x4C6F:
72                        if (XML_dbl_byte[1] == xA794)
73                                set_charset_family(EBCDIC, SingleByte, BigEndian, 0);
74                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
75                        break;
76                case xEFBE:
77                        if (signature[2] == 0xBF)
78                                set_charset_family(ASCII, SingleByte, BigEndian, 3);
79                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
80                        break;
81                default:
82                        set_charset_family(ASCII, SingleByte, BigEndian, 0);
83        }
84}
85void Entity_Info::set_charset_family(CodeUnit_Base C, CodeUnit_Size S, CodeUnit_ByteOrder O, int B){
86                code_unit_base = C;
87                code_unit_size = S;
88                byte_order = O;
89                BOM_units = B;
90 }
91
92
93template <CodeUnit_Base C>
94XML_Decl_Parser<C>::XML_Decl_Parser(unsigned char * bytes){
95        buffer_base_pos = 0;
96        x8data = bytes;
97}
98
99template <CodeUnit_Base C>
100XML_Decl_Parser<C>::~XML_Decl_Parser(){
101}
102
103template <CodeUnit_Base C>
104inline void XML_Decl_Parser<C>::DeclError() {
105        DeclarationError(AbsPos());
106}
107
108template <CodeUnit_Base C>
109inline int XML_Decl_Parser<C>::AbsPos() const {
110        return  buffer_base_pos + buffer_rel_pos;
111}
112
113template <CodeUnit_Base C>
114inline unsigned char * XML_Decl_Parser<C>::cur() const {
115        return &x8data[buffer_rel_pos];
116}
117
118template <CodeUnit_Base C>
119inline void XML_Decl_Parser<C>::Advance(int n) {
120        buffer_rel_pos += n;
121}
122
123template <CodeUnit_Base C>
124inline void XML_Decl_Parser<C>::Scan_WS() {
125        while (at_WhiteSpace_10<C>(cur())) Advance(1);
126}
127
128template <CodeUnit_Base C>
129inline void XML_Decl_Parser<C>::ScanEncodingName() {
130        if (at_ASCII_letter<C>(cur())) {
131          Advance(1);
132          while (at_ASCII_ncnamechar<C>(cur())) Advance(1);
133        }
134}
135
136template <CodeUnit_Base C>
137inline void XML_Decl_Parser<C>::ParseVersion(Entity_Info & e) {
138        /* Skip "version" */
139        Advance(7);
140        Scan_WS();
141        if (!AtChar<C,'='>(cur())) DeclError();
142        Advance(1);
143        Scan_WS();
144        if (at_1_0<C>(cur())) e.version = XML_1_0;
145        else if (at_1_1<C>(cur())) e.version = XML_1_1;
146        else DeclError();
147        Advance(5);
148}
149
150template <CodeUnit_Base C>
151inline void XML_Decl_Parser<C>::ParseEncoding(Entity_Info & e) {
152        /* Skip "encoding" */
153        Advance(8);
154        e.has_encoding_decl = true;
155        Scan_WS();
156        if (!AtChar<C,'='>(cur())) DeclError();
157        Advance(1);
158        Scan_WS();
159        if (AtQuote<C>(cur())) {
160                unsigned char quoteCh = cur()[0];
161                Advance(1);
162                int start_pos = AbsPos();
163                ScanEncodingName();
164                if (cur()[0] != quoteCh) DeclError();
165                int lgth = AbsPos() - start_pos;
166                e.encoding = new unsigned char[lgth + 1];
167                memcpy(e.encoding, &x8data[start_pos-buffer_base_pos], lgth);
168                e.encoding[lgth] = '\0';
169        }
170        else DeclError();
171        Advance(1);
172}
173
174template <CodeUnit_Base C>
175inline void XML_Decl_Parser<C>::ParseStandalone(Entity_Info & e) {
176        /* Skip "standalone" */
177        Advance(10);
178        Scan_WS();
179        if (!AtChar<C,'='>(cur())) DeclError();
180        Advance(1);
181        Scan_WS();
182        if (at_yes<C>(cur())) {Advance(5); e.standalone = Standalone_yes;}
183        else if (at_no<C>(cur())) {Advance(4); e.standalone = Standalone_no;}
184        else DeclError();
185}
186
187template <CodeUnit_Base C>
188void XML_Decl_Parser<C>::ReadXMLInfo(Entity_Info & e) {
189        e.version = no_XML_version_value;
190        e.has_encoding_decl = false;
191        e.standalone = Standalone_no_value;
192        buffer_rel_pos = e.BOM_units;
193        // It is possible that there is no XML declaration.
194        if (!at_XmlDecl_start<C>(cur())) {
195                e.content_start = AbsPos();
196                return;
197        }
198        // Otherwise, the XML declaration exists and must have
199        // at least version information.
200        Advance(6);
201        Scan_WS();
202        if (!at_version<C>(cur())) DeclError();
203        ParseVersion(e);
204        if (at_PI_End<C>(cur())) {
205                e.content_start = AbsPos()+2;
206                return;
207        }
208        if (!at_WhiteSpace_10<C>(cur())) DeclError();
209        Scan_WS();
210        if (at_encoding<C>(cur())) {
211                ParseEncoding(e);
212                if (at_PI_End<C>(cur())) {
213                        e.content_start = AbsPos()+2;
214                        return;
215                }
216                if (!at_WhiteSpace_10<C>(cur())) DeclError();
217                Scan_WS();
218        }
219        if (at_standalone<C>(cur())) {
220                ParseStandalone(e);
221                Scan_WS();
222        }
223        if (!at_PI_End<C>(cur())) DeclError();
224        e.content_start = AbsPos()+2;
225}
226
227// Similar to reading the XML_declaration of the document entity,
228// ReadTextDeclaration reads the text declaration of an external
229// parsed entity.
230
231template <CodeUnit_Base C>
232void XML_Decl_Parser<C>::ReadTextDeclaration(Entity_Info & e) {
233        e.version = no_XML_version_value;
234        e.has_encoding_decl = false;
235        e.standalone = Standalone_no_value;
236        buffer_rel_pos = e.BOM_units;
237        // It is possible that there is no text declaration.
238        if (!at_XmlDecl_start<C>(cur())) {
239                e.content_start = AbsPos();
240                return;
241        }
242        // Otherwise, the text declaration exists and may have
243        // version information.
244        Advance(6);
245        Scan_WS();
246        if (at_version<C>(cur())) {
247                ParseVersion(e);
248                // Must have whitespace character before encoding declaration.
249                if (!at_WhiteSpace_10<C>(cur())) DeclError();
250                Scan_WS();
251        }
252        if (!at_encoding<C>(cur())) DeclError();
253        ParseEncoding(e);
254        Scan_WS();
255        if (!at_PI_End<C>(cur())) DeclError();
256        e.content_start = AbsPos()+2;
257}
258
259template <CodeUnit_Base C>
260void XML_Decl_Parser<C>::ReadXMLorTextDecl(Entity_Info & e) {
261        e.version = no_XML_version_value;
262        e.has_encoding_decl = false;
263        e.standalone = Standalone_no_value;
264        buffer_rel_pos = e.BOM_units;
265        // It is possible that there is no XML or text declaration.
266        if (!at_XmlDecl_start<C>(cur())) {
267                e.content_start = AbsPos();
268                return;
269        }
270        // Otherwise, the XML or text declaration exists and may have
271        // version information.
272        Advance(6);
273        Scan_WS();
274        if (at_version<C>(cur())) {
275                ParseVersion(e);
276                if (at_PI_End<C>(cur())) {
277                        e.content_start = AbsPos()+2;
278                        return;
279                }
280                if (!at_WhiteSpace_10<C>(cur())) DeclError();
281                Scan_WS();
282                if (at_encoding<C>(cur())) {
283                        ParseEncoding(e);
284                        if (at_PI_End<C>(cur())) {
285                                e.content_start = AbsPos()+2;
286                                return;
287                        }
288                        if (!at_WhiteSpace_10<C>(cur())) DeclError();
289                        Scan_WS();
290                }
291                if (at_standalone<C>(cur())) {
292                        ParseStandalone(e);
293                        Scan_WS();
294                }
295        }
296        else {  // Without version, we can only have a text declaration,
297                // in which case an encoding spec is required.
298                if (!at_encoding<C>(cur())) DeclError();
299                ParseEncoding(e);
300                Scan_WS();
301                // No standalone spec is allowed in a text declaration.
302        }
303        if (!at_PI_End<C>(cur())) DeclError(); 
304        e.content_start = AbsPos()+2;
305}
Note: See TracBrowser for help on using the repository browser.