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 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 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 72 Xml2WbxmlEncoder::~Xml2WbxmlEncoder() 73 { 74 delete(mExpatParser); 75 delete(mEncoder); 76 } 77 78 void Xml2WbxmlEncoder::setWbxmlHandler(WbxmlHandler * handler) 79 { 80 mWbxmlHandler = handler; 81 } 82 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 115 void Xml2WbxmlEncoder::endElement(const char *name) 116 { 117 if (getErrorCode() != NO_ERROR) 118 return; 119 120 setError(mEncoder->endElement()); 121 mDepth--; 122 } 123 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 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 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 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 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