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