
TinyXML 2.6.2, CVE-2021-42260 और CVE-2023-34194 के लिए फिक्स के साथ
/** @mainpage
TinyXML एक सरल, छोटा, C++ XML पार्सर है जिसे अन्य प्रोग्रामों में आसानी से एकीकृत किया जा सकता है।
संक्षेप में, TinyXML एक XML दस्तावेज़ को पार्स करता है, और उससे एक Document Object Model (DOM) बनाता है जिसे पढ़ा, संशोधित और सहेजा जा सकता है।
XML का अर्थ है "eXtensible Markup Language"। यह आपको अपना स्वयं का दस्तावेज़ मार्कअप बनाने की अनुमति देता है। जहाँ HTML ब्राउज़रों के लिए दस्तावेज़ों को चिह्नित करने का बहुत अच्छा काम करता है, वहीं XML आपको किसी भी प्रकार का दस्तावेज़ मार्कअप परिभाषित करने की अनुमति देता है, उदाहरण के लिए एक दस्तावेज़ जो किसी आयोजक अनुप्रयोग के लिए "to do" सूची का वर्णन करता है। XML एक अत्यंत संरचित और सुविधाजनक प्रारूप है। अनुप्रयोग डेटा संग्रहीत करने के लिए बनाए गए वे सभी यादृच्छिक फ़ाइल प्रारूप सभी XML द्वारा प्रतिस्थापित किए जा सकते हैं। सब कुछ के लिए एक पार्सर।
पूर्ण, सही, और स्पष्ट रूप से कहें तो पढ़ने में कठिन स्पेक के लिए सबसे अच्छी जगह है http://www.w3.org/TR/2004/REC-xml-20040204/। XML का एक परिचय (जो मुझे वास्तव में पसंद है) http://skew.org/xml/tutorial पर पाया जा सकता है।
XML डेटा तक पहुँचने और उसके साथ बातचीत करने के विभिन्न तरीके हैं। TinyXML एक Document Object Model (DOM) का उपयोग करता है, जिसका अर्थ है कि XML डेटा को C++ ऑब्जेक्ट्स में पार्स किया जाता है जिन्हें ब्राउज़ और हेरफेर किया जा सकता है, और फिर डिस्क या किसी अन्य आउटपुट स्ट्रीम पर लिखा जा सकता है। आप C++ ऑब्जेक्ट्स के साथ शुरू से एक XML दस्तावेज़ भी बना सकते हैं और इसे डिस्क या किसी अन्य आउटपुट स्ट्रीम पर लिख सकते हैं।
TinyXML को आसान और तेज़ी से सीखने योग्य बनाने के लिए डिज़ाइन किया गया है। यह दो हेडर और चार cpp फ़ाइलें हैं। बस इन्हें अपने प्रोजेक्ट में जोड़ें और आप शुरू कर सकते हैं। आरंभ करने के लिए एक उदाहरण फ़ाइल - xmltest.cpp - है।
TinyXML ZLib लाइसेंस के अंतर्गत जारी किया गया है, इसलिए आप इसे ओपन सोर्स या व्यावसायिक कोड में उपयोग कर सकते हैं। लाइसेंस का विवरण हर स्रोत फ़ाइल के शीर्ष पर है।
TinyXML एक लचीला पार्सर बनने का प्रयास करता है, लेकिन वास्तव में सही और अनुरूप XML आउटपुट के साथ। TinyXML को किसी भी उचित रूप से C++ संगत प्रणाली पर संकलित होना चाहिए। यह एक्सेप्शन या RTTI पर निर्भर नहीं करता है। इसे STL समर्थन के साथ या बिना संकलित किया जा सकता है। TinyXML पूरी तरह से UTF-8 एन्कोडिंग और पहले 64k वर्ण संस्थाओं का समर्थन करता है।
TinyXML DTDs (Document Type Definitions) या XSLs (eXtensible Stylesheet Language) को पार्स या उपयोग नहीं करता है। वहाँ अन्य पार्सर मौजूद हैं (www.sourceforge.org देखें, XML खोजें) जो बहुत अधिक पूर्ण रूप से सुविधा संपन्न हैं। लेकिन वे बहुत बड़े भी हैं, आपके प्रोजेक्ट में सेट अप करने में अधिक समय लेते हैं, उनकी सीखने की अवस्था (learning curve) अधिक कठिन होती है, और अक्सर अधिक प्रतिबंधात्मक लाइसेंस होता है। यदि आप ब्राउज़रों के साथ काम कर रहे हैं या आपकी अधिक पूर्ण XML आवश्यकताएँ हैं, तो TinyXML आपके लिए पार्सर नहीं है।
निम्नलिखित DTD सिंटैक्स इस समय TinyXML में पार्स नहीं होगा:
@verbatim ]> @endverbatim
क्योंकि TinyXML इसे एक !DOCTYPE नोड के रूप में देखता है जिसमें अवैध रूप से एम्बेडेड !ELEMENT नोड है। इस पर भविष्य में ध्यान दिया जा सकता है।
अधीर लोगों के लिए, यहाँ एक ट्यूटोरियल है जो आपको आरंभ कराएगा। शुरू करने का एक शानदार तरीका, लेकिन इस (अत्यंत छोटे) मैनुअल को पूरी तरह पढ़ना आपके समय के लायक है।
TinyXML परिपक्व, परीक्षित कोड है। यह अत्यंत स्थिर है। यदि आपको बग मिलते हैं, तो कृपया sourceforge वेब साइट (www.sourceforge.net/projects/tinyxml) पर बग रिपोर्ट दर्ज करें। हम उन्हें जल्द से जल्द ठीक कर देंगे।
सुधार के कुछ क्षेत्र हैं; यदि आप TinyXML पर काम करने में रुचि रखते हैं तो कृपया sourceforge देखें।
TinyXML परियोजनाएँ जो आपको उपयोगी लग सकती हैं! (विवरण परियोजनाओं द्वारा प्रदान किए गए हैं।)
TinyXML को STL का उपयोग करने या न करने के लिए संकलित किया जा सकता है। STL का उपयोग करते समय, TinyXML std::string क्लास का उपयोग करता है, और std::istream, std::ostream, operator<<, और operator>> का पूर्ण समर्थन करता है। कई API विधियों में 'const char*' और 'const std::string&' दोनों रूप होते हैं।
जब STL समर्थन को संकलित नहीं किया जाता है, तो कोई भी STL फ़ाइल शामिल नहीं की जाती है। सभी स्ट्रिंग क्लासें TinyXML द्वारा स्वयं कार्यान्वित की जाती हैं। API विधियाँ इनपुट के लिए सभी 'const char*' रूप का उपयोग करती हैं।
कंपाइल-टाइम #define का उपयोग करें:
TIXML_USE_STL
एक या दूसरे संस्करण को संकलित करने के लिए। इसे कंपाइलर द्वारा पारित किया जा सकता है, या "tinyxml.h" की पहली पंक्ति के रूप में सेट किया जा सकता है।
नोट: Linux में परीक्षण कोड संकलित करते समय, पर्यावरण चर TINYXML_USE_STL=YES/NO सेट करने से STL संकलन नियंत्रित होगा। Windows प्रोजेक्ट फ़ाइल में, STL और गैर-STL लक्ष्य प्रदान किए गए हैं। आपके प्रोजेक्ट में, संभवतः tinyxml.h की पहली पंक्ति के रूप में "#define TIXML_USE_STL" पंक्ति जोड़ना सबसे आसान है।
TinyXML UTF-8 का समर्थन करता है जो किसी भी भाषा में XML फ़ाइलों को हेरफेर करने की अनुमति देता है। TinyXML "लेगेसी मोड" का भी समर्थन करता है - UTF-8 समर्थन से पहले उपयोग की जाने वाली एन्कोडिंग और संभवतः "विस्तारित ascii" के रूप में सबसे अच्छा वर्णित है।
सामान्यतः, TinyXML सही एन्कोडिंग का पता लगाने और उसका उपयोग करने का प्रयास करेगा। हालाँकि, हेडर फ़ाइल में TIXML_DEFAULT_ENCODING का मान सेट करके, TinyXML को हमेशा एक एन्कोडिंग का उपयोग करने के लिए बाध्य किया जा सकता है।
TinyXML निम्नलिखित में से एक होने तक लेगेसी मोड मान लेगा:
क्या होता है यदि एन्कोडिंग गलत तरीके से सेट या पहचानी जाती है? TinyXML अनुचित रूप से एन्कोडेड के रूप में देखे गए पाठ को पढ़ने और पास करने का प्रयास करेगा। आपको कुछ अजीब परिणाम या विकृत वर्ण मिल सकते हैं। आप TinyXML को सही मोड में जाने के लिए बाध्य करना चाह सकते हैं।
आप LoadFile( TIXML_ENCODING_LEGACY ) या LoadFile( filename, TIXML_ENCODING_LEGACY ) का उपयोग करके TinyXML को लेगेसी मोड में बाध्य कर सकते हैं। आप TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY सेट करके इसे हमेशा लेगेसी मोड का उपयोग करने के लिए बाध्य कर सकते हैं। इसी तरह, आप उसी तकनीक के साथ इसे TIXML_ENCODING_UTF8 पर बाध्य कर सकते हैं।
अंग्रेज़ी उपयोगकर्ताओं के लिए, अंग्रेज़ी XML का उपयोग करते हुए, UTF-8 लो-ASCII के समान है। आपको UTF-8 के बारे में जागरूक होने या अपना कोड किसी भी तरह से बदलने की आवश्यकता नहीं है। आप UTF-8 को ASCII के "सुपरसेट" के रूप में सोच सकते हैं।
UTF-8 एक डबल बाइट प्रारूप नहीं है - लेकिन यह यूनिकोड की एक मानक एन्कोडिंग है! TinyXML इस समय wchar, TCHAR, या Microsoft के _UNICODE का उपयोग या सीधे समर्थन नहीं करता है। "Unicode" शब्द को अक्सर अनुचित रूप से UTF-16, यूनिकोड की एक चौड़ी बाइट एन्कोडिंग, के संदर्भ में देखना आम है। यह भ्रम का एक स्रोत है।
"उच्च-ascii" भाषाओं के लिए - बहुत कुछ अंग्रेज़ी को छोड़कर सब कुछ - TinyXML सभी भाषाओं को एक ही समय में संभाल सकता है, जब तक XML UTF-8 में एन्कोडेड है। यह थोड़ा मुश्किल हो सकता है, पुराने प्रोग्राम और ऑपरेटिंग सिस्टम "डिफ़ॉल्ट" या "पारंपरिक" कोड पेज का उपयोग करते हैं। कई ऐप्स (और लगभग सभी आधुनिक) UTF-8 आउटपुट कर सकते हैं, लेकिन पुराने या जिद्दी (या केवल टूटे हुए) अभी भी डिफ़ॉल्ट कोड पेज में पाठ आउटपुट करते हैं।
उदाहरण के लिए, जापानी प्रणालियाँ पारंपरिक रूप से SHIFT-JIS एन्कोडिंग का उपयोग करती हैं। SHIFT-JIS के रूप में एन्कोडेड पाठ TinyXML द्वारा नहीं पढ़ा जा सकता है। एक अच्छा टेक्स्ट एडिटर SHIFT-JIS आयात कर सकता है और फिर UTF-8 के रूप में सहेज सकता है।
Skew.org लिंक एन्कोडिंग मुद्दे को कवर करने का बहुत अच्छा काम करता है।
परीक्षण फ़ाइल "utf8test.xml" एक XML है जिसमें अंग्रेज़ी, स्पेनिश, रूसी और सरलीकृत चीनी शामिल हैं। (उम्मीद है कि उनका सही अनुवाद किया गया है)। फ़ाइल "utf8test.gif" IE में प्रस्तुत XML फ़ाइल का एक स्क्रीन कैप्चर है। ध्यान दें कि यदि आपके सिस्टम पर सही फ़ॉन्ट (सरलीकृत चीनी या रूसी) नहीं हैं, तो आप GIF फ़ाइल से मेल खाता आउटपुट नहीं देख पाएंगे, भले ही आप इसे सही ढंग से पार्स कर सकें। यह भी ध्यान दें कि (कम से कम मेरी Windows मशीन पर) कंसोल आउटपुट एक पश्चिमी कोड पेज में है, इसलिए Print() या printf() फ़ाइल को सही ढंग से प्रदर्शित नहीं कर सकते। यह TinyXML में एक बग नहीं है - केवल एक OS मुद्दा है। TinyXML द्वारा कोई डेटा खोया या नष्ट नहीं होता है। कंसोल केवल UTF-8 प्रस्तुत नहीं करता है।
@verbatim & & < < > > " " ' ' @endverbatim
ये XML दस्तावेज़ पढ़े जाने पर पहचाने जाते हैं, और उनके UTF-8 समकक्षों में अनुवादित होते हैं। उदाहरण के लिए, XML वाला पाठ:
@verbatim Far & Away @endverbatim
का TiXmlText ऑब्जेक्ट से पूछताछ करने पर Value() "Far & Away" होगा, और XML स्ट्रीम/फ़ाइल पर एम्परसैंड के रूप में वापस लिखा जाएगा। TinyXML के पुराने संस्करण वर्ण संस्थाओं को "संरक्षित" करते थे, लेकिन नए संस्करण उन्हें वर्णों में अनुवादित करेंगे।
इसके अतिरिक्त, किसी भी वर्ण को उसके यूनिकोड कोड पॉइंट द्वारा निर्दिष्ट किया जा सकता है: सिंटैक्स " " या " " दोनों नॉन-ब्रेकिंग स्पेस वर्ण के लिए हैं।
Print( FILE* ). एक std-C स्ट्रीम पर आउटपुट, जिसमें सभी C फ़ाइलों के साथ-साथ stdout भी शामिल है।
operator<<. एक c++ स्ट्रीम पर आउटपुट।
TiXmlPrinter. std::string या मेमोरी बफ़र पर आउटपुट।
C शैली आउटपुट: - FILE* पर आधारित - Print() और SaveFile() विधियाँ
प्रारूपित आउटपुट उत्पन्न करता है, जिसमें बहुत सारा सफेद स्थान होता है, जिसका उद्देश्य जितना संभव हो उतना मानव-पठनीय होना है। वे बहुत तेज़ हैं, और खराब रूप से निर्मित XML दस्तावेज़ों के प्रति सहिष्णु हैं। उदाहरण के लिए, एक XML दस्तावेज़ जिसमें 2 रूट तत्व और 2 घोषणाएँ हैं, फिर भी प्रिंट होगा।
C शैली इनपुट: - FILE* पर आधारित - Parse() और LoadFile() विधियाँ
एक तेज़, सहिष्णु पठन। जब भी आपको C++ स्ट्रीम्स की आवश्यकता न हो तब उपयोग करें।
C++ शैली आउटपुट: - std::ostream पर आधारित - operator<<
संघनित आउटपुट उत्पन्न करता है, जो पठनीयता के बजाय नेटवर्क ट्रांसमिशन के लिए अभिप्रेत है। आपके सिस्टम के ostream क्लास कार्यान्वयन के आधार पर, ये कुछ धीमे हो सकते हैं। (या नहीं भी।) खराब रूप से निर्मित XML के प्रति सहिष्णु नहीं: एक दस्तावेज़ में सही एक रूट तत्व होना चाहिए। अतिरिक्त रूट स्तर के तत्व स्ट्रीम नहीं किए जाएँगे।
C++ शैली इनपुट: - std::istream पर आधारित - operator>>
स्ट्रीम से XML पढ़ता है, जिससे यह नेटवर्क ट्रांसमिशन के लिए उपयोगी हो जाता है। मुश्किल हिस्सा यह जानना है कि XML दस्तावेज़ कब पूरा होता है, क्योंकि स्ट्रीम में लगभग निश्चित रूप से अन्य डेटा होगा। TinyXML मान लेगा कि XML डेटा रूट तत्व पढ़ने के बाद पूरा हो गया है। दूसरे शब्दों में, एक से अधिक रूट तत्व वाले खराब निर्मित दस्तावेज़ सही ढंग से नहीं पढ़े जाएँगे। यह भी ध्यान दें कि operator>> Parse की तुलना में कुछ धीमा है, दोनों STL के कार्यान्वयन और TinyXML की सीमाओं के कारण।
यह एक मुद्दा है जो मेरी संतुष्टि के लिए हल नहीं हुआ है। TinyXML पहले 2 दृष्टिकोणों का समर्थन करता है। वांछित व्यवहार सेट करने के लिए TiXmlBase::SetCondenseWhiteSpace( bool ) कॉल करें। डिफ़ॉल्ट सफेद स्थान को संघनित करना है।
यदि आप डिफ़ॉल्ट बदलते हैं, तो आपको XML डेटा Parse करने के लिए कोई भी कॉल करने से पहले TiXmlBase::SetCondenseWhiteSpace( bool ) कॉल करना चाहिए, और मैं इसे सेट होने के बाद बदलने की अनुशंसा नहीं करता।
जब एक XML दस्तावेज़ को मजबूत तरीके से ब्राउज़ किया जाता है, तो विधि कॉल से शून्य (null) रिटर्न की जाँच करना महत्वपूर्ण है। एक त्रुटि-सुरक्षित कार्यान्वयन बहुत सारा कोड उत्पन्न कर सकता है जैसे:
@verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // Finally do something useful. @endverbatim
इसे साफ करने के लिए हैंडल्स पेश किए गए हैं। TiXmlHandle क्लास का उपयोग करके, पिछला कोड घटकर:
@verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); if ( child2 ) { // do something useful @endverbatim
जो निपटने में बहुत आसान है। अधिक जानकारी के लिए TiXmlHandle देखें।
TinyXML एक टेक्स्ट फ़ाइल में सभी नोड्स और विशेषताओं की पंक्ति और स्तंभ उत्पत्ति को ट्रैक कर सकता है। TiXmlBase::Row() और TiXmlBase::Column() विधियाँ स्रोत पाठ में नोड की उत्पत्ति लौटाती हैं। सही टैब TiXmlDocument::SetTabSize() में कॉन्फ़िगर किए जा सकते हैं।
xmltest को संकलित और चलाने के लिए:
एक Linux Makefile और एक Windows Visual C++ .dsw फ़ाइल प्रदान की गई है। बस संकलित करें और चलाएँ। यह demotest.xml फ़ाइल को आपकी डिस्क पर लिखेगा और स्क्रीन पर आउटपुट उत्पन्न करेगा। यह विभिन्न तकनीकों का उपयोग करके पाए गए नोड्स की संख्या प्रिंट करके DOM को ट्रैवर्स करने का भी परीक्षण करता है।
Linux makefile बहुत सामान्य है और कई प्रणालियों पर चलता है - यह वर्तमान में mingw और MacOSX पर परीक्षण किया गया है। आपको 'make depend' चलाने की आवश्यकता नहीं है। निर्भरताएँ हार्ड कोडित हैं।
PROFILE, DEBUG, और TINYXML_USE_STL. विवरण (जैसे भी हैं) makefile में हैं।
tinyxml निर्देशिका में, "make clean" फिर "make" टाइप करें। निष्पादन योग्य फ़ाइल 'xmltest' बनाई जाएगी।
अपने प्रोजेक्ट या मेक फ़ाइल में tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, और tinystr.h जोड़ें। बस इतना ही! इसे किसी भी उचित रूप से संगत C++ प्रणाली पर संकलित होना चाहिए। आपको TinyXML के लिए एक्सेप्शन या RTTI सक्षम करने की आवश्यकता नहीं है।
एक उदाहरण शायद आगे बढ़ने का सबसे अच्छा तरीका है। लें: @verbatim <?xml version="1.0" standalone=no> Go to the Toy store! Do bills @endverbatim
यह कोई बड़ी To Do सूची नहीं है, लेकिन यह चलेगी। इस फ़ाइल को पढ़ने के लिए (कहें "demo.xml") आप एक दस्तावेज़ बनाएँगे, और उसमें इसे पार्स करेंगे: @verbatim TiXmlDocument doc( "demo.xml" ); doc.LoadFile(); @endverbatim
और यह जाने के लिए तैयार है। अब कुछ पंक्तियों को देखें और वे DOM से कैसे संबंधित हैं।
@verbatim
@endverbatim पहली पंक्ति एक घोषणा है, और TiXmlDeclaration क्लास में बदल दी जाती है। यह दस्तावेज़ नोड का पहला बच्चा (child) होगा। यह TinyXML द्वारा पार्स किया गया एकमात्र निर्देश/विशेष टैग है। सामान्यतः निर्देश टैग TiXmlUnknown में संग्रहीत किए जाते हैं ताकि डिस्क पर वापस सहेजे जाने पर कमांड खो न जाएँ। @verbatim @endverbatim एक टिप्पणी। एक TiXmlComment ऑब्जेक्ट बन जाएगी। @verbatim @endverbatim "ToDo" टैग एक TiXmlElement ऑब्जेक्ट परिभाषित करता है। इसके पास कोई विशेषता (attribute) नहीं है, लेकिन इसमें 2 अन्य तत्व हैं। @verbatim @endverbatim एक और TiXmlElement बनाता है जो "ToDo" तत्व का बच्चा है। इस तत्व में 1 विशेषता है, जिसका नाम "priority" और मान "1" है। @verbatim Go to the @endverbatim एक TiXmlText. यह एक लीफ नोड है और इसमें अन्य नोड नहीं हो सकते। यह "Item" TiXmlElement का बच्चा है। @verbatim @endverbatim एक और TiXmlElement, यह "Item" तत्व का बच्चा है। वगैरह। पूरे ऑब्जेक्ट ट्री को देखते हुए, आप इसके साथ समाप्त होते हैं: @verbatim TiXmlDocument "demo.xml" TiXmlDeclaration "version='1.0'" "standalone=no" TiXmlComment " Our to do list data" TiXmlElement "ToDo" TiXmlElement "Item" Attribtutes: priority = 1 TiXmlText "Go to the " TiXmlElement "bold" TiXmlText "Toy store!" TiXmlElement "Item" Attributes: priority=2 TiXmlText "Do bills" @endverbatim