Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "SyncML_DM_WBXMLWriter.H"
     18 #include "SyncML_DM_WBXMLArchive.H"
     19 
     20 #ifdef LOB_SUPPORT
     21 #include "dm_tree_default_ESN_class.H" //header file for class defn
     22 #endif
     23 
     24 #include "dm_uri_utils.h"
     25 const int SyncML_DM_WBXMLWriter::MAX_OPAQUE_STRING_LENGTH = 255;
     26 
     27 /*==================================================================================================
     28 
     29 Function:    SyncML_DM_WBXMLWriter::writeByte
     30 
     31 Description: Write a byte of data to the file handle
     32 
     33 ==================================================================================================*/
     34 SYNCML_DM_RET_STATUS_T
     35 SyncML_DM_WBXMLWriter::writeByte(UINT8 byte) {
     36     return this->fileHandle->write(&byte, 1);
     37 }
     38 
     39 /*==================================================================================================
     40 
     41 Function:    SyncML_DM_WBXMLWriter::writeString
     42 
     43 Description: Writes a string of data as opaque data. The null terminator will
     44              not be written, as opaque data has a length stored with it. If the
     45              string is NULL, that will be written as an opaque data with length 0.
     46 
     47 ==================================================================================================*/
     48 SYNCML_DM_RET_STATUS_T
     49 SyncML_DM_WBXMLWriter::writeString(CPCHAR string) {
     50     UINT32 len = 0;
     51 
     52     if (string != NULL)
     53         len = DmStrlen(string);
     54     return writeOpaque((UINT8*)string, len);
     55 }
     56 
     57 /*==================================================================================================
     58 
     59 Function:    SyncML_DM_WBXMLWriter::writeData
     60 
     61 Description: Writes a given amount of raw data (without WBXML formatting or special encodings)
     62 
     63 ==================================================================================================*/
     64 SYNCML_DM_RET_STATUS_T
     65 SyncML_DM_WBXMLWriter::writeData(const UINT8* data, UINT8 len) {
     66     return this->fileHandle->write(data, len);
     67 }
     68 
     69 /*==================================================================================================
     70 
     71 Function:    SyncML_DM_WBXMLWriter::writeOpaque
     72 
     73 Description:
     74             Write opaque data of a given length.
     75             The data better be less than 128 bytes in length,
     76             as this service does not handle encoding the mb_u_int32 format.
     77 
     78             The service returns the success/fail code from the lower level I/O, or
     79             may also return SYNCML_DM_IO_FAILURE if the data was too long.
     80 
     81             A length of 0 and/or a NULL data buffer is handled.
     82 
     83 ==================================================================================================*/
     84 SYNCML_DM_RET_STATUS_T
     85 SyncML_DM_WBXMLWriter::writeOpaque(const UINT8* data, UINT32 len) {
     86     SYNCML_DM_RET_STATUS_T ret_stat;
     87 
     88     ret_stat = writeByte(SyncML_DM_WBXMLArchive::OPAQUE_CODE);
     89 
     90     if (ret_stat != SYNCML_DM_SUCCESS)
     91         return ret_stat;
     92 
     93     if((data != NULL) && (len != 0)) {
     94 
     95         UINT8 result, bits;
     96         int continuation=0;
     97         for(int shift = 28; shift > 0; shift -= 7) {
     98             bits = (len >> shift) & 0x7F;
     99             if ((bits!=0) ||(continuation != 0)) {
    100                 result = 0x80 | bits;
    101                 ret_stat = writeByte((UINT8)result);
    102                 if (ret_stat != SYNCML_DM_SUCCESS)
    103                     return SYNCML_DM_IO_FAILURE;
    104             }
    105             if (bits != 0)
    106                 continuation = 1;
    107         }
    108         result = len & 0x7F;
    109         ret_stat = writeByte((UINT8)result);
    110         if (ret_stat != SYNCML_DM_SUCCESS)
    111             return SYNCML_DM_IO_FAILURE;
    112 
    113         ret_stat = this->fileHandle->write(data, (UINT16)len);
    114 
    115     } else {
    116         /* Since the pointer to the byte is NULL, then there is no opaque data
    117          * for this node to be written, so the length field is zero. Zero encoded
    118          * in the mb_u_int32 format takes one byte, 0.
    119          */
    120         ret_stat = writeByte((UINT8)0);
    121     }
    122 
    123     return ret_stat;
    124 }
    125 
    126 
    127 /*==================================================================================================
    128 
    129 Function:    SyncML_DM_WBXMLWriter::writeNode
    130 
    131 Description: Write a SYNCML_DM_NODE_PROPERTIES_T type node of data to the WBXML file
    132     Note! This service does not write the END_TAG for the whole node; the next byte that can occur
    133     is a NODE_START_TAG (indicating the start of a new sub-node) or an END_TAG, (indicating the end
    134     of the current node, and parhaps the end of the current branch of the tree). The caller must
    135     decide what to write next.
    136 
    137 ==================================================================================================*/
    138 SYNCML_DM_RET_STATUS_T
    139 SyncML_DM_WBXMLWriter::writeNode(const DMNode* node) {
    140     /* Write the start tag */
    141     if(writeByte(SyncML_DM_WBXMLArchive::NODE_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS)
    142         return SYNCML_DM_IO_FAILURE;
    143 
    144     /* Write node properties */
    145     CPCHAR tmpStr;
    146     tmpStr = node->getName();
    147 
    148     if ( DmStrcmp(tmpStr,"") != 0 )  /* If there a NodeName to write... */
    149     {
    150         if(writeByte(SyncML_DM_WBXMLArchive::NAME_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    151                 writeString(tmpStr) != SYNCML_DM_SUCCESS ||
    152                 writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    153             return SYNCML_DM_IO_FAILURE;
    154     }
    155     UINT8 nodeFormat = (const UINT8) node->getFormat();
    156 
    157     if ( node->IsOverlayPIData() && nodeFormat == SYNCML_DM_FORMAT_NODE )
    158       nodeFormat = SYNCML_DM_FORMAT_NODE_PDATA;
    159 
    160     if ( nodeFormat != SYNCML_DM_FORMAT_NODE ) {
    161       if(writeByte(SyncML_DM_WBXMLArchive::FORMAT_NEW_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    162               writeOpaque((const UINT8*)&nodeFormat, sizeof(nodeFormat)) != SYNCML_DM_SUCCESS ||
    163               writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    164           return SYNCML_DM_IO_FAILURE;
    165     }
    166 #ifdef LOB_SUPPORT
    167     if(node->IsESN())
    168     {
    169 	 DMString tempESNName;
    170 
    171   	 // Get ESN pointer
    172 	 const DMDefaultESN *tempESN = reinterpret_cast<const DMDefaultESN *>(node);
    173 	// Get original storage file name
    174 	 tmpStr = tempESN->GetOriginalInternalFileName();
    175 
    176 	// Storage file changed ?
    177 	if(tempESN->IsDirty())
    178 	{
    179 		if(tempESN->IsSetComplete())
    180 		{
    181 			// Newly created node
    182 			if(tmpStr == NULL)
    183 			{	tempESNName.RemoveSufix(tempESN->GetInternalStorageFileName(), SYNCML_DM_DOT);
    184 				tmpStr = tempESNName.c_str();
    185 			}
    186 		}
    187 		else
    188 			 return SYNCML_DM_INCOMPLETE_COMMAND;
    189 	}
    190 	if(DmStrlen(tmpStr) != 0)   /* If there a file name  to write... */
    191 	 {
    192 	        if(writeByte(SyncML_DM_WBXMLArchive::ESN_File_NAME_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    193 	                writeString(tmpStr) != SYNCML_DM_SUCCESS ||
    194 	                writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    195 	            return SYNCML_DM_IO_FAILURE;
    196 	  }
    197     }
    198 #endif
    199     if ( node->IsOverlayPIData() && node->getOverlayPIData() && node->getOverlayPIData()->size() > 0 )
    200     {
    201       if(writeByte(SyncML_DM_WBXMLArchive::OPI_DATA_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    202               writeOpaque(node->getOverlayPIData()->get_data(), node->getOverlayPIData()->size()) != SYNCML_DM_SUCCESS ||
    203               writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    204           return SYNCML_DM_IO_FAILURE;
    205     }
    206     UINT16 flag = node->getFlags(); flag &= ~DMNode::enum_NodeNotPersisted;
    207         /* Guarantee Big Endian storage of a UINT16 */
    208     UINT8 flagNo[2] = { static_cast<UINT8>(flag >> 8),
    209                         static_cast<UINT8>(flag & 0xFF) };
    210     if ( flag ){
    211       if(writeByte(SyncML_DM_WBXMLArchive::FLAGS_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    212               writeOpaque(flagNo, sizeof(flagNo)) != SYNCML_DM_SUCCESS ||
    213               writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    214           return SYNCML_DM_IO_FAILURE;
    215     }
    216 
    217     tmpStr = node->getType();
    218     if (DmStrcmp(tmpStr,"") != 0)  /* If there are any mimetype to write... */
    219     {
    220         if(writeByte(SyncML_DM_WBXMLArchive::TYPE_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    221                 writeString(tmpStr) != SYNCML_DM_SUCCESS ||
    222                 writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    223             return SYNCML_DM_IO_FAILURE;
    224     }
    225 
    226     const DMBuffer * psData = node->getData();
    227 
    228     if ( psData && psData->getSize() )  /* If there are any ACLs to write... */
    229     {
    230         if(writeByte(SyncML_DM_WBXMLArchive::DATA_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    231                 writeOpaque(psData->getBuffer(), psData->getSize()) != SYNCML_DM_SUCCESS ||
    232                 writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    233             return SYNCML_DM_IO_FAILURE;
    234     }
    235 
    236     tmpStr = node->getTitle();
    237     if (DmStrcmp(tmpStr,"") != 0) {
    238         if(writeByte(SyncML_DM_WBXMLArchive::TITLE_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    239                 writeString(tmpStr) != SYNCML_DM_SUCCESS ||
    240                 writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    241             return SYNCML_DM_IO_FAILURE;
    242     }
    243 
    244 #ifndef DM_IGNORE_TSTAMP_AND_VERSION
    245     {
    246         DMNode * pNode = (DMNode*)node;
    247 
    248         UINT8 timeStamp[ sizeof(XPL_CLK_CLOCK_T) ];
    249 
    250         XPL_CLK_CLOCK_T tStamp = pNode->GetTStamp(NULL);
    251 
    252         for ( UINT32 i = 0; i < sizeof(XPL_CLK_CLOCK_T); i++ )
    253           timeStamp[i] = (UINT8)(tStamp >> (i*8));
    254 
    255         if(writeByte(SyncML_DM_WBXMLArchive::TSTAMP_INT_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS ||
    256                 writeOpaque(timeStamp, sizeof(timeStamp) ) != SYNCML_DM_SUCCESS ||
    257                 writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    258             return SYNCML_DM_IO_FAILURE;
    259 
    260         if(writeByte(SyncML_DM_WBXMLArchive::VERSION_START_TAG | SyncML_DM_WBXMLArchive::TAG_CONTENT_MASK) != SYNCML_DM_SUCCESS)
    261            return SYNCML_DM_IO_FAILURE;
    262         /* Guarantee Big Endian storage of a UINT16 */
    263         UINT16 wVerNo = pNode->GetVerNo(NULL);
    264         UINT8 verNo[2] = { static_cast<UINT8>(wVerNo >> 8),
    265                            static_cast<UINT8>(wVerNo & 0xFF) };
    266         if(writeOpaque(verNo, sizeof(verNo)) != SYNCML_DM_SUCCESS ||
    267            writeByte(SyncML_DM_WBXMLArchive::END_TAG) != SYNCML_DM_SUCCESS)
    268            return SYNCML_DM_IO_FAILURE;
    269    }
    270 
    271 #endif
    272 
    273     return SYNCML_DM_SUCCESS;
    274 }
    275 /*==================================================================================================
    276 
    277 Function:    SyncML_DM_WBXMLWriter::operator new
    278 
    279 Description: Allocate memory for this object
    280 
    281 Memory policy: The caller is responsible to delete (free) the new object (alloc'd memory)
    282 
    283 ==================================================================================================*/
    284 void *
    285 SyncML_DM_WBXMLWriter::operator new(size_t sz) {
    286     return (DmAllocMem(sz));
    287 }
    288 
    289 /*==================================================================================================
    290 
    291 Function:    SyncML_DM_WBXMLWriter::operator delete
    292 
    293 Description: De-allocate memory for this object
    294 
    295 ==================================================================================================*/
    296 void
    297 SyncML_DM_WBXMLWriter::operator delete (void *buf) {
    298     DmFreeMem(buf);
    299 }
    300