| /* |
| * Copyright (C) 2007 Esmertec AG. |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "xml2wbxml.h" |
| #include "wbxml_stl.h" |
| #include "imps_encoder.h" |
| |
| struct PublicIdData { |
| const char * pubid; |
| const char * xmlns; |
| PublicId idVal; |
| }; |
| |
| // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm |
| static const PublicIdData knownPublicId[] = { |
| { "-//OMA//DTD IMPS-CSP 1.3//EN", |
| "http://www.openmobilealliance.org/DTD/IMPS-CSP1.3", |
| PUBLICID_IMPS_1_3 }, |
| { "-//OMA//DTD WV-CSP 1.2//EN", |
| "http://www.openmobilealliance.org/DTD/WV-CSP1.2", |
| PUBLICID_IMPS_1_2 }, |
| { "-//WIRELESSVILLAGE//DTD CSP 1.1//EN", |
| "http://www.wireless-village.org/CSP1.1", |
| PUBLICID_IMPS_1_1 }, |
| /* |
| { "-//OMA//DRM 2.1//EN", XXX, 0x13 }, |
| { "-//OMA//DTD DRMREL 1.0//EN", XXX, 0x0e }, |
| { "-//SYNCML//DTD DevInf 1.2//EN", XXX, 0x1203 }, |
| { "-//SYNCML//DTD MetaInf 1.2//EN", XXX,0x1202 }, |
| { "-//SYNCML//DTD SyncML 1.2//EN", XXX, 0x1201 } |
| */ |
| }; |
| |
| static WbxmlEncoder * makeEncoder(int publicid) |
| { |
| switch (publicid) { |
| case PUBLICID_IMPS_1_3: |
| case PUBLICID_IMPS_1_2: |
| case PUBLICID_IMPS_1_1: |
| return new ImpsWbxmlEncoder(publicid); |
| |
| default: |
| return NULL; |
| } |
| } |
| |
| Xml2WbxmlEncoder::Xml2WbxmlEncoder() : |
| mWbxmlHandler(NULL), |
| mEncoder(NULL), |
| mPublicId(-1), |
| mDepth(0), |
| mErrorCode(NO_ERROR) |
| { |
| mExpatParser = new ExpatParser(); |
| mExpatParser->setContentHandler(this); |
| } |
| |
| Xml2WbxmlEncoder::~Xml2WbxmlEncoder() |
| { |
| delete(mExpatParser); |
| delete(mEncoder); |
| } |
| |
| void Xml2WbxmlEncoder::setWbxmlHandler(WbxmlHandler * handler) |
| { |
| mWbxmlHandler = handler; |
| } |
| |
| void Xml2WbxmlEncoder::startElement(const char *name, const char **atts) |
| { |
| if (getErrorCode() != NO_ERROR) |
| return; |
| |
| if (!mDepth) { |
| if (!isPublicIdSet()) { |
| for (int i = 0; atts[i]; i += 2) { |
| // TODO: for now we don't handle xmlns:<prefix> yet |
| if (strcmp(atts[i], "xmlns") == 0) { |
| if (detectPublicIdByXmlns(atts[i + 1])) |
| break; |
| } |
| } |
| } |
| if (isPublicIdSet()) { |
| // TODO: at present fixed to WBXML 1.3, UTF-8, no string table |
| mEncoder = makeEncoder(mPublicId); |
| if (mEncoder == NULL) { |
| setError(ERROR_UNSUPPORTED_DOCTYPE); |
| return; |
| } |
| mEncoder->setWbxmlHandler(mWbxmlHandler); |
| } else { |
| setError(ERROR_NO_PUBLIC_ID); |
| return; |
| } |
| } |
| setError(mEncoder->startElement(name, atts)); |
| mDepth++; |
| } |
| |
| void Xml2WbxmlEncoder::endElement(const char *name) |
| { |
| if (getErrorCode() != NO_ERROR) |
| return; |
| |
| setError(mEncoder->endElement()); |
| mDepth--; |
| } |
| |
| void Xml2WbxmlEncoder::characters(const char *data, int len) |
| { |
| if (getErrorCode() != NO_ERROR) |
| return; |
| |
| setError(mEncoder->characters(data, len)); |
| } |
| |
| void Xml2WbxmlEncoder::startDoctype(const char *doctypeName, |
| const char *sysid, |
| const char *pubid, |
| int has_internal_subset) |
| { |
| if (!isPublicIdSet()) { |
| detectPublicId(pubid); |
| } |
| } |
| |
| bool Xml2WbxmlEncoder::detectPublicId(const char * pubid) |
| { |
| for (size_t i = 0; i < sizeof(knownPublicId) / sizeof(knownPublicId[0]); i++) { |
| if (strcmp(pubid, knownPublicId[i].pubid) == 0) { |
| //printf ("pubid %s => 0x%x\n", pubid, knownPublicId[i].idVal); |
| setPublicId(knownPublicId[i].idVal); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool Xml2WbxmlEncoder::detectPublicIdByXmlns(const char * xmlnsUri) |
| { |
| for (size_t i = 0; i < sizeof(knownPublicId) / sizeof(knownPublicId[0]); i++) { |
| if (strcmp(xmlnsUri, knownPublicId[i].xmlns) == 0) { |
| //printf ("xmlns %s => 0x%x\n", xmlnsUri, knownPublicId[i].idVal); |
| setPublicId(knownPublicId[i].idVal); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| int Xml2WbxmlEncoder::encode(const char * data, uint32_t dataLen, bool end) |
| { |
| if (data == NULL) { |
| return WBXML_STATUS_ERROR; |
| } |
| if (mExpatParser->parse(data, (int)dataLen, end) != XML_STATUS_OK) { |
| //printf ("Expat error: %s\n", XML_ErrorString(XML_GetErrorCode(mExpat))); |
| return WBXML_STATUS_ERROR; |
| } |
| return getErrorCode() == NO_ERROR ? WBXML_STATUS_OK : WBXML_STATUS_ERROR; |
| } |
| |