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: 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 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 73 CFX_SAXFile::~CFX_SAXFile() {} 74 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 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 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 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 } 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 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 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 172 void CFX_SAXReader::Pop() { 173 if (!m_Stack.empty()) 174 m_Stack.pop(); 175 } 176 177 CFX_SAXItem* CFX_SAXReader::GetCurrentItem() const { 178 return m_Stack.empty() ? nullptr : m_Stack.top().get(); 179 } 180 181 void CFX_SAXReader::AppendData(uint8_t ch) { 182 ReallocDataBuffer(); 183 m_pszData[m_iDataPos++] = ch; 184 } 185 186 void CFX_SAXReader::AppendName(uint8_t ch) { 187 ReallocNameBuffer(); 188 m_pszName[m_iDataPos++] = ch; 189 } 190 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 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 215 bool CFX_SAXReader::SkipSpace(uint8_t ch) { 216 return (m_dwParseMode & CFX_SaxParseMode_NotSkipSpace) == 0 && ch < 0x21; 217 } 218 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 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 } 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 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 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 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 } 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 } 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 } 435 void CFX_SAXReader::ParseDeclNode() { 436 SkipNode(); 437 } 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 } 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 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 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 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 } 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 } 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 } 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 } 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 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 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 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 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 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 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 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 729 void CFX_SAXReader::SkipCurrentNode() { 730 CFX_SAXItem* pItem = GetCurrentItem(); 731 if (!pItem) 732 return; 733 734 pItem->m_bSkip = true; 735 } 736 737 void CFX_SAXReader::SetHandler(CXFA_SAXReaderHandler* pHandler) { 738 m_pHandler = pHandler; 739 } 740