• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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("&apos;");
298                     break;
299                 case '\"':
300                     out_.append("&quot;");
301                     break;
302                 case '&':
303                     out_.append("&amp;");
304                     break;
305                 case '>':
306                     out_.append("&gt;");
307                     break;
308                 case '<':
309                     out_.append("&lt;");
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