1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "js_xml_dynamic.h" 17 #include "securec.h" 18 #include "tools/ets_error.h" 19 20 using namespace OHOS::Tools; 21 namespace OHOS::xml { DealNapiStrValue(napi_env env,const napi_value napiStr,std::string & result)22 napi_status XmlDynamicSerializer::DealNapiStrValue(napi_env env, const napi_value napiStr, std::string &result) 23 { 24 std::string buffer = ""; 25 size_t bufferSize = 0; 26 napi_status status = napi_get_value_string_utf8(env, napiStr, nullptr, -1, &bufferSize); 27 if (status != napi_ok) { 28 HILOG_ERROR("XmlDynamicSerializer:: can not get buffer size"); 29 return status; 30 } 31 buffer.reserve(bufferSize + 1); 32 buffer.resize(bufferSize); 33 if (bufferSize > 0) { 34 status = napi_get_value_string_utf8(env, napiStr, buffer.data(), bufferSize + 1, &bufferSize); 35 if (status != napi_ok) { 36 HILOG_ERROR("XmlDynamicSerializer:: can not get buffer value"); 37 return status; 38 } 39 } 40 if (buffer.data() != nullptr) { 41 result = buffer; 42 } 43 return status; 44 } 45 SplicNsp()46 void XmlDynamicSerializer::SplicNsp() 47 { 48 elementStack_[depth_ * 3] = elementStack_[(depth_ - 1) * 3]; // 3: number of args 49 elementStack_[depth_ * 3 + 1] = elementStack_[(depth_ - 1) * 3 + 1]; // 3: number of args 50 if (multNsp_[depth_ - 1].size() == 0) { 51 return; 52 } 53 if (type_ == "isAttri" || type_ == "isStart") { 54 for (int i = 0; i < curNspNum; ++i) { 55 out_.append(" xmlns:"); 56 out_.append(multNsp_[depth_ - 1][i * 2]); // 2: number of args 57 out_.append("=\""); 58 out_.append(multNsp_[depth_ - 1][i * 2 + 1]); // 2: number of args 59 out_.append("\""); 60 } 61 multNsp_[depth_ - 1].clear(); 62 curNspNum = 0; 63 } 64 } 65 NextItem()66 void XmlDynamicSerializer::NextItem() 67 { 68 out_.append("\r\n"); 69 for (size_t i = 0; i < depth_; i++) { 70 out_.append(" "); 71 } 72 } 73 Replace(std::string str,const std::string & subStr,const std::string & repStr)74 std::string XmlDynamicSerializer::Replace(std::string str, const std::string &subStr, const std::string &repStr) 75 { 76 size_t iPos = 0; 77 size_t subLen = subStr.length(); 78 size_t step = repStr.length(); 79 while ((iPos = str.find(subStr, iPos)) != std::string::npos) { 80 str = str.substr(0, iPos) + repStr + str.substr(iPos + subLen); 81 iPos += step; 82 } 83 return str; 84 } 85 BufferCopy()86 void XmlDynamicSerializer::BufferCopy() 87 { 88 if (strXml_.length() + out_.length() <= MAX_XML_LENGTH) { 89 strXml_.append(out_); 90 } else { 91 errorCode_ = ErrorCodeEnum::BUFFER_OVERFLOW; 92 xmlSerializerError_ = "The cumulative length of xml has exceeded the upper limit 100000."; 93 ErrorHelper::ThrowError(env_, errorCode_, xmlSerializerError_.c_str()); 94 } 95 } 96 SetDeclaration()97 void XmlDynamicSerializer::SetDeclaration() 98 { 99 if (strXml_.length() > 0) { 100 xmlSerializerError_ = "illegal position for xml."; 101 errorCode_ = ErrorCodeEnum::ILLEGAL_POSITION; 102 ErrorHelper::ThrowError(env_, errorCode_, xmlSerializerError_.c_str()); 103 return; 104 } 105 out_ = ""; 106 out_.append("<?xml version=\"1.0\""); 107 out_.append(" encoding=\""); 108 out_.append(encoding_); 109 out_.append("\"?>"); 110 type_ = "isDecl"; 111 BufferCopy(); 112 } 113 SetNamespace(std::string prefix,const std::string & nsTemp)114 void XmlDynamicSerializer::SetNamespace(std::string prefix, const std::string &nsTemp) 115 { 116 out_ = ""; 117 if (type_ == "isStart" || type_ == "isAttri") { 118 SplicNsp(); 119 out_.append(">"); 120 } 121 elementStack_[depth_ * 3] = prefix; // 3: number of args 122 elementStack_[depth_ * 3 + 1] = nsTemp; // 3: number of args 123 multNsp_[depth_][curNspNum * 2] = elementStack_[depth_ * 3]; // 3: number of args 2: number of args 124 multNsp_[depth_][curNspNum * 2 + 1] = elementStack_[depth_ * 3 + 1]; // 3: number of args 2: number of args 125 ++curNspNum; 126 type_ = "isNsp"; 127 BufferCopy(); 128 } 129 StartElement(const std::string & name)130 void XmlDynamicSerializer::StartElement(const std::string &name) 131 { 132 out_ = ""; 133 if (type_ == "isStart" || type_ == "isAttri") { 134 SplicNsp(); 135 out_.append(">"); 136 } 137 if (type_ != "") { 138 NextItem(); 139 } 140 elementStack_[depth_ * 3 + 2] = name; // 3: number of args 2: number of args 141 out_.append("<"); 142 if (elementStack_[depth_ * 3] != "") { // 3: number of args 143 out_.append(elementStack_[depth_ * 3]); // 3: number of args 144 out_.append(":"); 145 } else if (depth_ != 0) { 146 if (elementStack_[(depth_ - 1) * 3] != "") { // 3: number of args 147 elementStack_[depth_ * 3] = elementStack_[(depth_ - 1) * 3]; // 3: number of args 148 out_.append(elementStack_[depth_ * 3]); // 3: number of args 149 out_.append(":"); 150 } 151 } 152 out_.append(elementStack_[depth_ * 3 + 2]); // 3: number of args 2: number of args 153 type_ = "isStart"; 154 ++depth_; 155 elementNum_++; 156 elementStack_.push_back(""); 157 elementStack_.push_back(""); 158 elementStack_.push_back(""); 159 BufferCopy(); 160 } 161 SetAttributes(const std::string & name,const std::string & value)162 void XmlDynamicSerializer::SetAttributes(const std::string &name, const std::string &value) 163 { 164 out_ = ""; 165 if (type_ != "isStart" && type_ != "isAttri") { 166 xmlSerializerError_ = "illegal position for xml."; 167 errorCode_ = ErrorCodeEnum::ILLEGAL_POSITION; 168 ErrorHelper::ThrowError(env_, errorCode_, xmlSerializerError_.c_str()); 169 return; 170 } 171 out_.append(" "); 172 out_.append(name); 173 out_.append("=\""); 174 WriteEscaped(value); 175 out_.append("\""); 176 type_ = "isAttri"; 177 BufferCopy(); 178 } 179 EndElement()180 void XmlDynamicSerializer::EndElement() 181 { 182 if (elementNum_ < 1) { 183 xmlSerializerError_ = "There is no match between the startElement and the endElement."; 184 errorCode_ = ErrorCodeEnum::NO_ELEMENT_MATCH; 185 ErrorHelper::ThrowError(env_, errorCode_, xmlSerializerError_.c_str()); 186 return; 187 } 188 elementNum_--; 189 out_ = ""; 190 if (type_ == "isStart" || type_ == "isAttri") { 191 SplicNsp(); 192 out_.append("/>"); 193 type_ = "isEndTag"; 194 --depth_; 195 BufferCopy(); 196 return; 197 } 198 --depth_; 199 if (type_ != "isText") { 200 NextItem(); 201 } 202 out_.append("</"); 203 if (elementStack_[depth_ * 3] != "") { // 3: number of args 204 out_.append(elementStack_[depth_ * 3]); // 3: number of args 205 out_.append(":"); 206 } 207 out_.append(elementStack_[depth_ * 3 + 2]); // 3: number of args 2: number of args 208 elementStack_[depth_ * 3] = ""; // 3: number of args 209 elementStack_[depth_ * 3 + 1] = ""; // 3: number of args 210 type_ = "isEndTag"; 211 out_.append(">"); 212 BufferCopy(); 213 } 214 AddEmptyElement(std::string name)215 void XmlDynamicSerializer::AddEmptyElement(std::string name) 216 { 217 out_ = ""; 218 if (type_ == "isStart" || type_ == "isAttri") { 219 SplicNsp(); 220 out_.append(">"); 221 } 222 if (type_ != "") { 223 NextItem(); 224 } 225 out_.append("<"); 226 out_.append(name); 227 out_.append("/>"); 228 type_ = "isAddEmpElem"; 229 BufferCopy(); 230 } 231 SetText(const std::string & text)232 void XmlDynamicSerializer::SetText(const std::string &text) 233 { 234 out_ = ""; 235 if (type_ == "isStart" || type_ == "isAttri") { 236 SplicNsp(); 237 out_.append(">"); 238 } 239 WriteEscaped(text); 240 type_ = "isText"; 241 BufferCopy(); 242 } 243 SetComment(const std::string & comment)244 void XmlDynamicSerializer::SetComment(const std::string &comment) 245 { 246 out_ = ""; 247 if (type_ == "isStart" || type_ == "isAttri") { 248 SplicNsp(); 249 out_.append(">"); 250 } 251 if (type_ != "") { 252 NextItem(); 253 } 254 out_ += "<!--" + comment + "-->"; 255 type_ = "isCom"; 256 BufferCopy(); 257 } 258 SetCData(std::string data)259 void XmlDynamicSerializer::SetCData(std::string data) 260 { 261 out_ = ""; 262 if (type_ == "isStart" || type_ == "isAttri") { 263 SplicNsp(); 264 out_.append(">"); 265 } 266 if (type_ != "") { 267 NextItem(); 268 } 269 data = Replace(data, "]]>", "]]]]><![CDATA[>"); 270 out_ += "<![CDATA[" + data + "]]>"; 271 type_ = "isCData"; 272 BufferCopy(); 273 } 274 SetDocType(const std::string & text)275 void XmlDynamicSerializer::SetDocType(const std::string &text) 276 { 277 out_ = ""; 278 if (type_ == "isStart" || type_ == "isAttri") { 279 SplicNsp(); 280 out_.append(">"); 281 } 282 if (type_ != "") { 283 NextItem(); 284 } 285 out_ += "<!DOCTYPE " + text + ">"; 286 type_ = "isDocType"; 287 BufferCopy(); 288 } 289 WriteEscaped(std::string s)290 void XmlDynamicSerializer::WriteEscaped(std::string s) 291 { 292 size_t len = s.length(); 293 for (size_t i = 0; i < len; ++i) { 294 char c = s[i]; 295 switch (c) { 296 case '\'': 297 out_.append("'"); 298 break; 299 case '\"': 300 out_.append("""); 301 break; 302 case '&': 303 out_.append("&"); 304 break; 305 case '>': 306 out_.append(">"); 307 break; 308 case '<': 309 out_.append("<"); 310 break; 311 default: 312 out_ += c; 313 } 314 } 315 } 316 GetXmlBufferLength()317 size_t XmlDynamicSerializer::GetXmlBufferLength() 318 { 319 return strXml_.length(); 320 } 321 GetXmlBuffer(void * data,uint32_t length)322 bool XmlDynamicSerializer::GetXmlBuffer(void *data, uint32_t length) 323 { 324 if (data == nullptr) { 325 HILOG_ERROR("XmlDynamicSerializer:: GetXmlBuffer data is NULL"); 326 return false; 327 } 328 if (memcpy_s(data, length, reinterpret_cast<const void*>(strXml_.data()), strXml_.length()) != EOK) { 329 HILOG_ERROR("XmlDynamicSerializer:: GetXmlBuffer copy xml buffer error"); 330 return false; 331 } 332 return true; 333 } 334 } // namespace OHOS::Xml