1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fde/xml/cfx_saxreader.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "third_party/base/ptr_util.h"
13 #include "xfa/fxfa/xfa_checksum.h"
14
15 enum class CFX_SaxMode {
16 Text = 0,
17 NodeStart,
18 DeclOrComment,
19 DeclNode,
20 Comment,
21 CommentContent,
22 TagName,
23 TagAttributeName,
24 TagAttributeEqual,
25 TagAttributeValue,
26 TagMaybeClose,
27 TagClose,
28 TagEnd,
29 TargetData,
30 MAX
31 };
32
33 class CFX_SAXCommentContext {
34 public:
CFX_SAXCommentContext()35 CFX_SAXCommentContext() : m_iHeaderCount(0), m_iTailCount(0) {}
36 int32_t m_iHeaderCount;
37 int32_t m_iTailCount;
38 };
39
40 namespace {
41
42 const uint32_t kSaxFileBufSize = 32768;
43
44 typedef void (CFX_SAXReader::*FX_SAXReader_LPFParse)();
45 static const FX_SAXReader_LPFParse
46 g_FX_SAXReader_LPFParse[static_cast<int>(CFX_SaxMode::MAX)] = {
47 &CFX_SAXReader::ParseText,
48 &CFX_SAXReader::ParseNodeStart,
49 &CFX_SAXReader::ParseDeclOrComment,
50 &CFX_SAXReader::ParseDeclNode,
51 &CFX_SAXReader::ParseComment,
52 &CFX_SAXReader::ParseCommentContent,
53 &CFX_SAXReader::ParseTagName,
54 &CFX_SAXReader::ParseTagAttributeName,
55 &CFX_SAXReader::ParseTagAttributeEqual,
56 &CFX_SAXReader::ParseTagAttributeValue,
57 &CFX_SAXReader::ParseMaybeClose,
58 &CFX_SAXReader::ParseTagClose,
59 &CFX_SAXReader::ParseTagEnd,
60 &CFX_SAXReader::ParseTargetData,
61 };
62
63 } // namespace
64
CFX_SAXFile()65 CFX_SAXFile::CFX_SAXFile()
66 : m_dwStart(0),
67 m_dwEnd(0),
68 m_dwCur(0),
69 m_pBuf(nullptr),
70 m_dwBufSize(0),
71 m_dwBufIndex(0) {}
72
~CFX_SAXFile()73 CFX_SAXFile::~CFX_SAXFile() {}
74
StartFile(const CFX_RetainPtr<IFX_SeekableReadStream> & pFile,uint32_t dwStart,uint32_t dwLen)75 bool CFX_SAXFile::StartFile(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
76 uint32_t dwStart,
77 uint32_t dwLen) {
78 ASSERT(!m_pFile && pFile);
79 uint32_t dwSize = pFile->GetSize();
80 if (dwStart >= dwSize)
81 return false;
82
83 if (dwLen == static_cast<uint32_t>(-1) || dwStart + dwLen > dwSize)
84 dwLen = dwSize - dwStart;
85
86 if (dwLen == 0)
87 return false;
88
89 m_dwBufSize = std::min(dwLen, kSaxFileBufSize);
90 m_pBuf = FX_Alloc(uint8_t, m_dwBufSize);
91 if (!pFile->ReadBlock(m_pBuf, dwStart, m_dwBufSize))
92 return false;
93
94 m_dwStart = dwStart;
95 m_dwEnd = dwStart + dwLen;
96 m_dwCur = dwStart;
97 m_pFile = pFile;
98 m_dwBufIndex = 0;
99 return true;
100 }
101
ReadNextBlock()102 bool CFX_SAXFile::ReadNextBlock() {
103 ASSERT(m_pFile);
104 uint32_t dwSize = m_dwEnd - m_dwCur;
105 if (dwSize == 0) {
106 return false;
107 }
108 m_dwBufSize = std::min(dwSize, kSaxFileBufSize);
109 if (!m_pFile->ReadBlock(m_pBuf, m_dwCur, m_dwBufSize)) {
110 return false;
111 }
112 m_dwBufIndex = 0;
113 return true;
114 }
115
Reset()116 void CFX_SAXFile::Reset() {
117 if (m_pBuf) {
118 FX_Free(m_pBuf);
119 m_pBuf = nullptr;
120 }
121 m_pFile = nullptr;
122 }
123
CFX_SAXReader()124 CFX_SAXReader::CFX_SAXReader()
125 : m_File(),
126 m_pHandler(nullptr),
127 m_iState(-1),
128 m_dwItemID(0),
129 m_iDataSize(256),
130 m_iNameSize(256),
131 m_dwParseMode(0),
132 m_pCommentContext(nullptr) {
133 m_pszData = FX_Alloc(uint8_t, m_iDataSize);
134 m_pszName = FX_Alloc(uint8_t, m_iNameSize);
135 }
~CFX_SAXReader()136 CFX_SAXReader::~CFX_SAXReader() {
137 Reset();
138 if (m_pszData) {
139 FX_Free(m_pszData);
140 m_pszData = nullptr;
141 }
142 if (m_pszName) {
143 FX_Free(m_pszName);
144 m_pszName = nullptr;
145 }
146 }
147
Reset()148 void CFX_SAXReader::Reset() {
149 m_File.Reset();
150 while (!m_Stack.empty())
151 m_Stack.pop();
152
153 m_dwItemID = 0;
154 m_SkipStack.RemoveAll();
155 m_SkipChar = 0;
156 m_iDataLength = 0;
157 m_iEntityStart = -1;
158 m_iNameLength = 0;
159 m_iDataPos = 0;
160 delete m_pCommentContext;
161 m_pCommentContext = nullptr;
162 }
163
Push()164 void CFX_SAXReader::Push() {
165 std::unique_ptr<CFX_SAXItem> pNew =
166 pdfium::MakeUnique<CFX_SAXItem>(++m_dwItemID);
167 if (!m_Stack.empty())
168 pNew->m_bSkip = m_Stack.top()->m_bSkip;
169 m_Stack.push(std::move(pNew));
170 }
171
Pop()172 void CFX_SAXReader::Pop() {
173 if (!m_Stack.empty())
174 m_Stack.pop();
175 }
176
GetCurrentItem() const177 CFX_SAXItem* CFX_SAXReader::GetCurrentItem() const {
178 return m_Stack.empty() ? nullptr : m_Stack.top().get();
179 }
180
AppendData(uint8_t ch)181 void CFX_SAXReader::AppendData(uint8_t ch) {
182 ReallocDataBuffer();
183 m_pszData[m_iDataPos++] = ch;
184 }
185
AppendName(uint8_t ch)186 void CFX_SAXReader::AppendName(uint8_t ch) {
187 ReallocNameBuffer();
188 m_pszName[m_iDataPos++] = ch;
189 }
190
ReallocDataBuffer()191 void CFX_SAXReader::ReallocDataBuffer() {
192 if (m_iDataPos < m_iDataSize) {
193 return;
194 }
195 if (m_iDataSize <= 1024 * 1024) {
196 m_iDataSize *= 2;
197 } else {
198 m_iDataSize += 1024 * 1024;
199 }
200 m_pszData = (uint8_t*)FX_Realloc(uint8_t, m_pszData, m_iDataSize);
201 }
202
ReallocNameBuffer()203 void CFX_SAXReader::ReallocNameBuffer() {
204 if (m_iDataPos < m_iNameSize) {
205 return;
206 }
207 if (m_iNameSize <= 1024 * 1024) {
208 m_iNameSize *= 2;
209 } else {
210 m_iNameSize += 1024 * 1024;
211 }
212 m_pszName = (uint8_t*)FX_Realloc(uint8_t, m_pszName, m_iNameSize);
213 }
214
SkipSpace(uint8_t ch)215 bool CFX_SAXReader::SkipSpace(uint8_t ch) {
216 return (m_dwParseMode & CFX_SaxParseMode_NotSkipSpace) == 0 && ch < 0x21;
217 }
218
StartParse(const CFX_RetainPtr<IFX_SeekableReadStream> & pFile,uint32_t dwStart,uint32_t dwLen,uint32_t dwParseMode)219 int32_t CFX_SAXReader::StartParse(
220 const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
221 uint32_t dwStart,
222 uint32_t dwLen,
223 uint32_t dwParseMode) {
224 m_iState = -1;
225 Reset();
226 if (!m_File.StartFile(pFile, dwStart, dwLen))
227 return -1;
228
229 m_iState = 0;
230 m_eMode = CFX_SaxMode::Text;
231 m_ePrevMode = CFX_SaxMode::Text;
232 m_bCharData = false;
233 m_dwDataOffset = 0;
234 m_dwParseMode = dwParseMode;
235 m_Stack.emplace(new CFX_SAXItem(++m_dwItemID));
236 return 0;
237 }
238
ContinueParse(IFX_Pause * pPause)239 int32_t CFX_SAXReader::ContinueParse(IFX_Pause* pPause) {
240 if (m_iState < 0 || m_iState > 99) {
241 return m_iState;
242 }
243 while (m_File.m_dwCur < m_File.m_dwEnd) {
244 uint32_t& index = m_File.m_dwBufIndex;
245 uint32_t size = m_File.m_dwBufSize;
246 const uint8_t* pBuf = m_File.m_pBuf;
247 while (index < size) {
248 m_CurByte = pBuf[index];
249 (this->*g_FX_SAXReader_LPFParse[static_cast<int>(m_eMode)])();
250 index++;
251 }
252 m_File.m_dwCur += index;
253 m_iState = (m_File.m_dwCur - m_File.m_dwStart) * 100 /
254 (m_File.m_dwEnd - m_File.m_dwStart);
255 if (m_File.m_dwCur >= m_File.m_dwEnd) {
256 break;
257 }
258 if (!m_File.ReadNextBlock()) {
259 m_iState = -2;
260 break;
261 }
262 m_dwDataOffset = 0;
263 if (pPause && pPause->NeedToPauseNow()) {
264 break;
265 }
266 }
267 return m_iState;
268 }
ParseChar(uint8_t ch)269 void CFX_SAXReader::ParseChar(uint8_t ch) {
270 ReallocDataBuffer();
271 m_pszData[m_iDataPos] = ch;
272 if (m_iEntityStart > -1 && ch == ';') {
273 int32_t iSaveEntityStart = m_iEntityStart;
274 CFX_ByteString csEntity(m_pszData + m_iEntityStart + 1,
275 m_iDataPos - m_iEntityStart - 1);
276 int32_t iLen = csEntity.GetLength();
277 if (iLen > 0) {
278 if (csEntity[0] == '#') {
279 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_sharp) == 0) {
280 ch = 0;
281 uint8_t w;
282 if (iLen > 1 && csEntity[1] == 'x') {
283 for (int32_t i = 2; i < iLen; i++) {
284 w = csEntity[i];
285 if (w >= '0' && w <= '9') {
286 ch = (ch << 4) + w - '0';
287 } else if (w >= 'A' && w <= 'F') {
288 ch = (ch << 4) + w - 55;
289 } else if (w >= 'a' && w <= 'f') {
290 ch = (ch << 4) + w - 87;
291 } else {
292 break;
293 }
294 }
295 } else {
296 for (int32_t i = 1; i < iLen; i++) {
297 w = csEntity[i];
298 if (w < '0' || w > '9') {
299 break;
300 }
301 ch = ch * 10 + w - '0';
302 }
303 }
304 if (ch != 0) {
305 m_pszData[m_iEntityStart++] = ch;
306 }
307 }
308 } else {
309 if (csEntity.Compare("amp") == 0) {
310 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_amp) == 0) {
311 m_pszData[m_iEntityStart++] = '&';
312 }
313 } else if (csEntity.Compare("lt") == 0) {
314 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_lt) == 0) {
315 m_pszData[m_iEntityStart++] = '<';
316 }
317 } else if (csEntity.Compare("gt") == 0) {
318 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_gt) == 0) {
319 m_pszData[m_iEntityStart++] = '>';
320 }
321 } else if (csEntity.Compare("apos") == 0) {
322 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_apos) == 0) {
323 m_pszData[m_iEntityStart++] = '\'';
324 }
325 } else if (csEntity.Compare("quot") == 0) {
326 if ((m_dwParseMode & CFX_SaxParseMode_NotConvert_quot) == 0) {
327 m_pszData[m_iEntityStart++] = '\"';
328 }
329 }
330 }
331 }
332 if (iSaveEntityStart != m_iEntityStart) {
333 m_iDataPos = m_iEntityStart;
334 m_iEntityStart = -1;
335 } else {
336 m_iDataPos++;
337 m_iEntityStart = -1;
338 }
339 } else {
340 if (m_iEntityStart < 0 && ch == '&') {
341 m_iEntityStart = m_iDataPos;
342 }
343 m_iDataPos++;
344 }
345 }
346
ParseText()347 void CFX_SAXReader::ParseText() {
348 if (m_CurByte == '<') {
349 if (m_iDataPos > 0) {
350 m_iDataLength = m_iDataPos;
351 m_iDataPos = 0;
352 if (m_pHandler) {
353 NotifyData();
354 }
355 }
356 Push();
357 m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
358 m_eMode = CFX_SaxMode::NodeStart;
359 return;
360 }
361 if (m_iDataPos < 1 && SkipSpace(m_CurByte)) {
362 return;
363 }
364 ParseChar(m_CurByte);
365 }
366
ParseNodeStart()367 void CFX_SAXReader::ParseNodeStart() {
368 if (m_CurByte == '?') {
369 GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Instruction;
370 m_eMode = CFX_SaxMode::TagName;
371 return;
372 }
373 if (m_CurByte == '!') {
374 m_eMode = CFX_SaxMode::DeclOrComment;
375 return;
376 }
377 if (m_CurByte == '/') {
378 m_eMode = CFX_SaxMode::TagEnd;
379 return;
380 }
381 if (m_CurByte == '>') {
382 Pop();
383 m_eMode = CFX_SaxMode::Text;
384 return;
385 }
386 if (m_CurByte > 0x20) {
387 m_dwDataOffset = m_File.m_dwBufIndex;
388 GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Tag;
389 m_eMode = CFX_SaxMode::TagName;
390 AppendData(m_CurByte);
391 }
392 }
393
ParseDeclOrComment()394 void CFX_SAXReader::ParseDeclOrComment() {
395 if (m_CurByte == '-') {
396 m_eMode = CFX_SaxMode::Comment;
397 GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Comment;
398 if (!m_pCommentContext)
399 m_pCommentContext = new CFX_SAXCommentContext;
400
401 m_pCommentContext->m_iHeaderCount = 1;
402 m_pCommentContext->m_iTailCount = 0;
403 } else {
404 m_eMode = CFX_SaxMode::DeclNode;
405 m_dwDataOffset = m_File.m_dwBufIndex;
406 m_SkipChar = '>';
407 m_SkipStack.Add('>');
408 SkipNode();
409 }
410 }
ParseComment()411 void CFX_SAXReader::ParseComment() {
412 m_pCommentContext->m_iHeaderCount = 2;
413 m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
414 m_eMode = CFX_SaxMode::CommentContent;
415 }
ParseCommentContent()416 void CFX_SAXReader::ParseCommentContent() {
417 if (m_CurByte == '-') {
418 m_pCommentContext->m_iTailCount++;
419 } else if (m_CurByte == '>' && m_pCommentContext->m_iTailCount == 2) {
420 m_iDataLength = m_iDataPos;
421 m_iDataPos = 0;
422 if (m_pHandler) {
423 NotifyTargetData();
424 }
425 Pop();
426 m_eMode = CFX_SaxMode::Text;
427 } else {
428 while (m_pCommentContext->m_iTailCount > 0) {
429 AppendData('-');
430 m_pCommentContext->m_iTailCount--;
431 }
432 AppendData(m_CurByte);
433 }
434 }
ParseDeclNode()435 void CFX_SAXReader::ParseDeclNode() {
436 SkipNode();
437 }
ParseTagName()438 void CFX_SAXReader::ParseTagName() {
439 if (m_CurByte < 0x21 || m_CurByte == '/' || m_CurByte == '>' ||
440 m_CurByte == '?') {
441 m_iDataLength = m_iDataPos;
442 m_iDataPos = 0;
443 if (m_pHandler) {
444 NotifyEnter();
445 }
446 if (m_CurByte < 0x21) {
447 m_eMode = CFX_SaxMode::TagAttributeName;
448 } else if (m_CurByte == '/' || m_CurByte == '?') {
449 m_ePrevMode = m_eMode;
450 m_eMode = CFX_SaxMode::TagMaybeClose;
451 } else {
452 if (m_pHandler) {
453 NotifyBreak();
454 }
455 m_eMode = CFX_SaxMode::Text;
456 }
457 } else {
458 AppendData(m_CurByte);
459 }
460 }
ParseTagAttributeName()461 void CFX_SAXReader::ParseTagAttributeName() {
462 if (m_CurByte < 0x21 || m_CurByte == '=') {
463 if (m_iDataPos < 1 && m_CurByte < 0x21) {
464 return;
465 }
466 m_iNameLength = m_iDataPos;
467 m_iDataPos = 0;
468 m_SkipChar = 0;
469 m_eMode = m_CurByte == '=' ? CFX_SaxMode::TagAttributeValue
470 : CFX_SaxMode::TagAttributeEqual;
471 return;
472 }
473 if (m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') {
474 if (m_CurByte == '/' || m_CurByte == '?') {
475 m_ePrevMode = m_eMode;
476 m_eMode = CFX_SaxMode::TagMaybeClose;
477 } else {
478 if (m_pHandler) {
479 NotifyBreak();
480 }
481 m_eMode = CFX_SaxMode::Text;
482 }
483 return;
484 }
485 if (m_iDataPos < 1) {
486 m_dwDataOffset = m_File.m_dwBufIndex;
487 }
488 AppendName(m_CurByte);
489 }
490
ParseTagAttributeEqual()491 void CFX_SAXReader::ParseTagAttributeEqual() {
492 if (m_CurByte == '=') {
493 m_SkipChar = 0;
494 m_eMode = CFX_SaxMode::TagAttributeValue;
495 return;
496 }
497 if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) {
498 m_iDataPos = m_iNameLength;
499 AppendName(0x20);
500 m_eMode = CFX_SaxMode::TargetData;
501 ParseTargetData();
502 }
503 }
504
ParseTagAttributeValue()505 void CFX_SAXReader::ParseTagAttributeValue() {
506 if (m_SkipChar) {
507 if (m_SkipChar == m_CurByte) {
508 {
509 m_iDataLength = m_iDataPos;
510 m_iDataPos = 0;
511 if (m_pHandler) {
512 NotifyAttribute();
513 }
514 }
515 m_SkipChar = 0;
516 m_eMode = CFX_SaxMode::TagAttributeName;
517 return;
518 }
519 ParseChar(m_CurByte);
520 return;
521 }
522 if (m_CurByte < 0x21) {
523 return;
524 }
525 if (m_iDataPos < 1) {
526 if (m_CurByte == '\'' || m_CurByte == '\"') {
527 m_SkipChar = m_CurByte;
528 }
529 }
530 }
531
ParseMaybeClose()532 void CFX_SAXReader::ParseMaybeClose() {
533 if (m_CurByte == '>') {
534 if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) {
535 m_iNameLength = m_iDataPos;
536 m_iDataPos = 0;
537 if (m_pHandler) {
538 NotifyTargetData();
539 }
540 }
541 ParseTagClose();
542 m_eMode = CFX_SaxMode::Text;
543 } else if (m_ePrevMode == CFX_SaxMode::TagName) {
544 AppendData('/');
545 m_eMode = CFX_SaxMode::TagName;
546 m_ePrevMode = CFX_SaxMode::Text;
547 ParseTagName();
548 } else if (m_ePrevMode == CFX_SaxMode::TagAttributeName) {
549 AppendName('/');
550 m_eMode = CFX_SaxMode::TagAttributeName;
551 m_ePrevMode = CFX_SaxMode::Text;
552 ParseTagAttributeName();
553 } else if (m_ePrevMode == CFX_SaxMode::TargetData) {
554 AppendName('?');
555 m_eMode = CFX_SaxMode::TargetData;
556 m_ePrevMode = CFX_SaxMode::Text;
557 ParseTargetData();
558 }
559 }
ParseTagClose()560 void CFX_SAXReader::ParseTagClose() {
561 m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
562 if (m_pHandler) {
563 NotifyClose();
564 }
565 Pop();
566 }
ParseTagEnd()567 void CFX_SAXReader::ParseTagEnd() {
568 if (m_CurByte < 0x21) {
569 return;
570 }
571 if (m_CurByte == '>') {
572 Pop();
573 m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
574 m_iDataLength = m_iDataPos;
575 m_iDataPos = 0;
576 if (m_pHandler) {
577 NotifyEnd();
578 }
579 Pop();
580 m_eMode = CFX_SaxMode::Text;
581 } else {
582 ParseChar(m_CurByte);
583 }
584 }
ParseTargetData()585 void CFX_SAXReader::ParseTargetData() {
586 if (m_CurByte == '?') {
587 m_ePrevMode = m_eMode;
588 m_eMode = CFX_SaxMode::TagMaybeClose;
589 } else {
590 AppendName(m_CurByte);
591 }
592 }
SkipNode()593 void CFX_SAXReader::SkipNode() {
594 int32_t iLen = m_SkipStack.GetSize();
595 if (m_SkipChar == '\'' || m_SkipChar == '\"') {
596 if (m_CurByte != m_SkipChar) {
597 return;
598 }
599 iLen--;
600 ASSERT(iLen > -1);
601 m_SkipStack.RemoveAt(iLen, 1);
602 m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
603 return;
604 }
605 switch (m_CurByte) {
606 case '<':
607 m_SkipChar = '>';
608 m_SkipStack.Add('>');
609 break;
610 case '[':
611 m_SkipChar = ']';
612 m_SkipStack.Add(']');
613 break;
614 case '(':
615 m_SkipChar = ')';
616 m_SkipStack.Add(')');
617 break;
618 case '\'':
619 m_SkipChar = '\'';
620 m_SkipStack.Add('\'');
621 break;
622 case '\"':
623 m_SkipChar = '\"';
624 m_SkipStack.Add('\"');
625 break;
626 default:
627 if (m_CurByte == m_SkipChar) {
628 iLen--;
629 m_SkipStack.RemoveAt(iLen, 1);
630 m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
631 if (iLen == 0 && m_CurByte == '>') {
632 m_iDataLength = m_iDataPos;
633 m_iDataPos = 0;
634 if (m_iDataLength >= 9 &&
635 FXSYS_memcmp(m_pszData, "[CDATA[", 7 * sizeof(uint8_t)) == 0 &&
636 FXSYS_memcmp(m_pszData + m_iDataLength - 2, "]]",
637 2 * sizeof(uint8_t)) == 0) {
638 Pop();
639 m_iDataLength -= 9;
640 m_dwDataOffset += 7;
641 FXSYS_memmove(m_pszData, m_pszData + 7,
642 m_iDataLength * sizeof(uint8_t));
643 m_bCharData = true;
644 if (m_pHandler) {
645 NotifyData();
646 }
647 m_bCharData = false;
648 } else {
649 Pop();
650 }
651 m_eMode = CFX_SaxMode::Text;
652 }
653 }
654 break;
655 }
656 if (iLen > 0) {
657 ParseChar(m_CurByte);
658 }
659 }
660
NotifyData()661 void CFX_SAXReader::NotifyData() {
662 CFX_SAXItem* pItem = GetCurrentItem();
663 if (!pItem)
664 return;
665
666 if (pItem->m_eNode == CFX_SAXItem::Type::Tag)
667 m_pHandler->OnTagData(
668 pItem->m_pNode,
669 m_bCharData ? CFX_SAXItem::Type::CharData : CFX_SAXItem::Type::Text,
670 CFX_ByteStringC(m_pszData, m_iDataLength),
671 m_File.m_dwCur + m_dwDataOffset);
672 }
673
NotifyEnter()674 void CFX_SAXReader::NotifyEnter() {
675 CFX_SAXItem* pItem = GetCurrentItem();
676 if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
677 pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
678 pItem->m_pNode = m_pHandler->OnTagEnter(
679 CFX_ByteStringC(m_pszData, m_iDataLength), pItem->m_eNode, m_dwNodePos);
680 }
681 }
682
NotifyAttribute()683 void CFX_SAXReader::NotifyAttribute() {
684 CFX_SAXItem* pItem = GetCurrentItem();
685 if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
686 pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
687 m_pHandler->OnTagAttribute(pItem->m_pNode,
688 CFX_ByteStringC(m_pszName, m_iNameLength),
689 CFX_ByteStringC(m_pszData, m_iDataLength));
690 }
691 }
692
NotifyBreak()693 void CFX_SAXReader::NotifyBreak() {
694 CFX_SAXItem* pItem = GetCurrentItem();
695 if (pItem->m_eNode == CFX_SAXItem::Type::Tag)
696 m_pHandler->OnTagBreak(pItem->m_pNode);
697 }
698
NotifyClose()699 void CFX_SAXReader::NotifyClose() {
700 CFX_SAXItem* pItem = GetCurrentItem();
701 if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
702 pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
703 m_pHandler->OnTagClose(pItem->m_pNode, m_dwNodePos);
704 }
705 }
706
NotifyEnd()707 void CFX_SAXReader::NotifyEnd() {
708 CFX_SAXItem* pItem = GetCurrentItem();
709 if (!pItem || pItem->m_eNode != CFX_SAXItem::Type::Tag)
710 return;
711
712 m_pHandler->OnTagEnd(pItem->m_pNode,
713 CFX_ByteStringC(m_pszData, m_iDataLength), m_dwNodePos);
714 }
715
NotifyTargetData()716 void CFX_SAXReader::NotifyTargetData() {
717 CFX_SAXItem* pItem = GetCurrentItem();
718 if (pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
719 m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode,
720 CFX_ByteStringC(m_pszName, m_iNameLength),
721 m_dwNodePos);
722 } else if (pItem->m_eNode == CFX_SAXItem::Type::Comment) {
723 m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode,
724 CFX_ByteStringC(m_pszData, m_iDataLength),
725 m_dwNodePos);
726 }
727 }
728
SkipCurrentNode()729 void CFX_SAXReader::SkipCurrentNode() {
730 CFX_SAXItem* pItem = GetCurrentItem();
731 if (!pItem)
732 return;
733
734 pItem->m_bSkip = true;
735 }
736
SetHandler(CXFA_SAXReaderHandler * pHandler)737 void CFX_SAXReader::SetHandler(CXFA_SAXReaderHandler* pHandler) {
738 m_pHandler = pHandler;
739 }
740