Home | History | Annotate | Download | only in src
      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