1 /*
2 * Copyright (C) 2007 Esmertec AG.
3 * Copyright (C) 2007 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "xml2wbxml.h"
19 #include "wbxml_stl.h"
20 #include "imps_encoder.h"
21
22 struct PublicIdData {
23 const char * pubid;
24 const char * xmlns;
25 PublicId idVal;
26 };
27
28 // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm
29 static const PublicIdData knownPublicId[] = {
30 { "-//OMA//DTD IMPS-CSP 1.3//EN",
31 "http://www.openmobilealliance.org/DTD/IMPS-CSP1.3",
32 PUBLICID_IMPS_1_3 },
33 { "-//OMA//DTD WV-CSP 1.2//EN",
34 "http://www.openmobilealliance.org/DTD/WV-CSP1.2",
35 PUBLICID_IMPS_1_2 },
36 { "-//WIRELESSVILLAGE//DTD CSP 1.1//EN",
37 "http://www.wireless-village.org/CSP1.1",
38 PUBLICID_IMPS_1_1 },
39 /*
40 { "-//OMA//DRM 2.1//EN", XXX, 0x13 },
41 { "-//OMA//DTD DRMREL 1.0//EN", XXX, 0x0e },
42 { "-//SYNCML//DTD DevInf 1.2//EN", XXX, 0x1203 },
43 { "-//SYNCML//DTD MetaInf 1.2//EN", XXX,0x1202 },
44 { "-//SYNCML//DTD SyncML 1.2//EN", XXX, 0x1201 }
45 */
46 };
47
makeEncoder(int publicid)48 static WbxmlEncoder * makeEncoder(int publicid)
49 {
50 switch (publicid) {
51 case PUBLICID_IMPS_1_3:
52 case PUBLICID_IMPS_1_2:
53 case PUBLICID_IMPS_1_1:
54 return new ImpsWbxmlEncoder(publicid);
55
56 default:
57 return NULL;
58 }
59 }
60
Xml2WbxmlEncoder()61 Xml2WbxmlEncoder::Xml2WbxmlEncoder() :
62 mWbxmlHandler(NULL),
63 mEncoder(NULL),
64 mPublicId(-1),
65 mDepth(0),
66 mErrorCode(NO_ERROR)
67 {
68 mExpatParser = new ExpatParser();
69 mExpatParser->setContentHandler(this);
70 }
71
~Xml2WbxmlEncoder()72 Xml2WbxmlEncoder::~Xml2WbxmlEncoder()
73 {
74 delete(mExpatParser);
75 delete(mEncoder);
76 }
77
setWbxmlHandler(WbxmlHandler * handler)78 void Xml2WbxmlEncoder::setWbxmlHandler(WbxmlHandler * handler)
79 {
80 mWbxmlHandler = handler;
81 }
82
startElement(const char * name,const char ** atts)83 void Xml2WbxmlEncoder::startElement(const char *name, const char **atts)
84 {
85 if (getErrorCode() != NO_ERROR)
86 return;
87
88 if (!mDepth) {
89 if (!isPublicIdSet()) {
90 for (int i = 0; atts[i]; i += 2) {
91 // TODO: for now we don't handle xmlns:<prefix> yet
92 if (strcmp(atts[i], "xmlns") == 0) {
93 if (detectPublicIdByXmlns(atts[i + 1]))
94 break;
95 }
96 }
97 }
98 if (isPublicIdSet()) {
99 // TODO: at present fixed to WBXML 1.3, UTF-8, no string table
100 mEncoder = makeEncoder(mPublicId);
101 if (mEncoder == NULL) {
102 setError(ERROR_UNSUPPORTED_DOCTYPE);
103 return;
104 }
105 mEncoder->setWbxmlHandler(mWbxmlHandler);
106 } else {
107 setError(ERROR_NO_PUBLIC_ID);
108 return;
109 }
110 }
111 setError(mEncoder->startElement(name, atts));
112 mDepth++;
113 }
114
endElement(const char * name)115 void Xml2WbxmlEncoder::endElement(const char *name)
116 {
117 if (getErrorCode() != NO_ERROR)
118 return;
119
120 setError(mEncoder->endElement());
121 mDepth--;
122 }
123
characters(const char * data,int len)124 void Xml2WbxmlEncoder::characters(const char *data, int len)
125 {
126 if (getErrorCode() != NO_ERROR)
127 return;
128
129 setError(mEncoder->characters(data, len));
130 }
131
startDoctype(const char * doctypeName,const char * sysid,const char * pubid,int has_internal_subset)132 void Xml2WbxmlEncoder::startDoctype(const char *doctypeName,
133 const char *sysid,
134 const char *pubid,
135 int has_internal_subset)
136 {
137 if (!isPublicIdSet()) {
138 detectPublicId(pubid);
139 }
140 }
141
detectPublicId(const char * pubid)142 bool Xml2WbxmlEncoder::detectPublicId(const char * pubid)
143 {
144 for (size_t i = 0; i < sizeof(knownPublicId) / sizeof(knownPublicId[0]); i++) {
145 if (strcmp(pubid, knownPublicId[i].pubid) == 0) {
146 //printf ("pubid %s => 0x%x\n", pubid, knownPublicId[i].idVal);
147 setPublicId(knownPublicId[i].idVal);
148 return true;
149 }
150 }
151 return false;
152 }
153
detectPublicIdByXmlns(const char * xmlnsUri)154 bool Xml2WbxmlEncoder::detectPublicIdByXmlns(const char * xmlnsUri)
155 {
156 for (size_t i = 0; i < sizeof(knownPublicId) / sizeof(knownPublicId[0]); i++) {
157 if (strcmp(xmlnsUri, knownPublicId[i].xmlns) == 0) {
158 //printf ("xmlns %s => 0x%x\n", xmlnsUri, knownPublicId[i].idVal);
159 setPublicId(knownPublicId[i].idVal);
160 return true;
161 }
162 }
163 return false;
164 }
165
encode(const char * data,uint32_t dataLen,bool end)166 int Xml2WbxmlEncoder::encode(const char * data, uint32_t dataLen, bool end)
167 {
168 if (data == NULL) {
169 return WBXML_STATUS_ERROR;
170 }
171 if (mExpatParser->parse(data, (int)dataLen, end) != XML_STATUS_OK) {
172 //printf ("Expat error: %s\n", XML_ErrorString(XML_GetErrorCode(mExpat)));
173 return WBXML_STATUS_ERROR;
174 }
175 return getErrorCode() == NO_ERROR ? WBXML_STATUS_OK : WBXML_STATUS_ERROR;
176 }
177
178