• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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