// // SAXParserTest.cpp // // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // SPDX-License-Identifier: BSL-1.0 // #include "SAXParserTest.h" #include "CppUnit/TestCaller.h" #include "CppUnit/TestSuite.h" #include "Poco/SAX/SAXParser.h" #include "Poco/SAX/InputSource.h" #include "Poco/SAX/EntityResolver.h" #include "Poco/SAX/SAXException.h" #include "Poco/SAX/WhitespaceFilter.h" #include "Poco/XML/XMLWriter.h" #include "Poco/Latin9Encoding.h" #include "Poco/FileStream.h" #include using Poco::XML::SAXParser; using Poco::XML::XMLWriter; using Poco::XML::XMLReader; using Poco::XML::InputSource; using Poco::XML::EntityResolver; using Poco::XML::XMLString; using Poco::XML::SAXParseException; using Poco::XML::WhitespaceFilter; class TestEntityResolver: public EntityResolver { public: InputSource* resolveEntity(const XMLString* publicId, const XMLString& systemId) { if (systemId == "include.xml") { std::istringstream* istr = new std::istringstream(SAXParserTest::INCLUDE); InputSource* pIS = new InputSource(*istr); pIS->setSystemId(systemId); return pIS; } else if (systemId == "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent") { std::istringstream* istr = new std::istringstream(SAXParserTest::XHTML_LATIN1_ENTITIES); InputSource* pIS = new InputSource(*istr); pIS->setSystemId(systemId); return pIS; } return 0; } void releaseInputSource(InputSource* pSource) { delete pSource->getByteStream(); delete pSource; } }; SAXParserTest::SAXParserTest(const std::string& name): CppUnit::TestCase(name) { } SAXParserTest::~SAXParserTest() { } void SAXParserTest::testSimple1() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, SIMPLE1); assertTrue (xml == ""); } void SAXParserTest::testSimple2() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, SIMPLE2); assertTrue (xml == ""); } void SAXParserTest::testAttributes() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, ATTRIBUTES); assertTrue (xml == ATTRIBUTES); } void SAXParserTest::testCDATA() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, CDATA); assertTrue (xml == CDATA); } void SAXParserTest::testComment() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, COMMENT); assertTrue (xml == COMMENT); } void SAXParserTest::testPI() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, PROCESSING_INSTRUCTION); assertTrue (xml == PROCESSING_INSTRUCTION); } void SAXParserTest::testDTD() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, DTD); assertTrue (xml == ""); } void SAXParserTest::testInternalEntity() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, INTERNAL_ENTITY); assertTrue (xml == "\n\tApplied Informatics\n"); } void SAXParserTest::testNotation() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, NOTATION); assertTrue (xml == "" "]>" ""); } void SAXParserTest::testExternalUnparsed() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, EXTERNAL_UNPARSED); assertTrue (xml == "" "]>" ""); } void SAXParserTest::testExternalParsed() { SAXParser parser; TestEntityResolver resolver; parser.setEntityResolver(&resolver); parser.setFeature(XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES, true); std::string xml = parse(parser, XMLWriter::CANONICAL, EXTERNAL_PARSED); assertTrue (xml == "\n\t\n\tAn external entity.\n\n\n"); } void SAXParserTest::testDefaultNamespace() { SAXParser parser; std::string xml = parse(parser, XMLWriter::CANONICAL, DEFAULT_NAMESPACE); assertTrue (xml == DEFAULT_NAMESPACE); } void SAXParserTest::testNamespaces() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, true); parser.setFeature(XMLReader::FEATURE_NAMESPACE_PREFIXES, true); std::string xml = parse(parser, XMLWriter::CANONICAL, NAMESPACES); assertTrue (xml == NAMESPACES); } void SAXParserTest::testNamespacesNoPrefixes() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, true); parser.setFeature(XMLReader::FEATURE_NAMESPACE_PREFIXES, false); std::string xml = parse(parser, XMLWriter::CANONICAL, NAMESPACES); assertTrue (xml == NAMESPACES); } void SAXParserTest::testNoNamespaces() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, false); std::string xml = parse(parser, XMLWriter::CANONICAL, NAMESPACES); assertTrue (xml == NAMESPACES); } void SAXParserTest::testUndeclaredNamespace() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, true); parser.setFeature(XMLReader::FEATURE_NAMESPACE_PREFIXES, true); try { std::string xml = parse(parser, XMLWriter::CANONICAL, UNDECLARED_NAMESPACE); fail("undeclared namespace - must throw exception"); } catch (SAXParseException&) { } } void SAXParserTest::testUndeclaredNamespaceNoPrefixes() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, true); parser.setFeature(XMLReader::FEATURE_NAMESPACE_PREFIXES, false); try { std::string xml = parse(parser, XMLWriter::CANONICAL, UNDECLARED_NAMESPACE); fail("undeclared namespace - must throw exception"); } catch (SAXParseException&) { } } void SAXParserTest::testUndeclaredNoNamespace() { SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, false); std::string xml = parse(parser, XMLWriter::CANONICAL, UNDECLARED_NAMESPACE); assertTrue (xml == UNDECLARED_NAMESPACE); } void SAXParserTest::testRSS() { SAXParser parser; WhitespaceFilter filter(&parser); TestEntityResolver resolver; filter.setEntityResolver(&resolver); parser.setFeature(XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES, true); parser.setFeature(XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES, true); std::istringstream istr(RSS); Poco::FileOutputStream ostr("rss.xml"); XMLWriter writer(ostr, XMLWriter::CANONICAL | XMLWriter::PRETTY_PRINT); filter.setContentHandler(&writer); filter.setDTDHandler(&writer); filter.setProperty(XMLReader::PROPERTY_LEXICAL_HANDLER, static_cast(&writer)); InputSource source(istr); filter.parse(&source); } void SAXParserTest::testEncoding() { SAXParser parser; Poco::Latin9Encoding encoding; parser.addEncoding("ISO-8859-15", &encoding); std::istringstream istr(ENCODING); std::ostringstream ostr; XMLWriter writer(ostr, XMLWriter::WRITE_XML_DECLARATION, "ISO-8859-15", encoding); parser.setContentHandler(&writer); parser.setDTDHandler(&writer); parser.setProperty(XMLReader::PROPERTY_LEXICAL_HANDLER, static_cast(&writer)); InputSource source(istr); parser.parse(&source); std::string xml = ostr.str(); assertTrue (xml == ENCODING); } void SAXParserTest::testCharacters() { static const XMLString xml(" TEXT & AMPERSAND "); SAXParser parser; parser.setFeature(XMLReader::FEATURE_NAMESPACES, false); std::string result = parse(parser, XMLWriter::CANONICAL, xml); assertTrue (result == xml); } void SAXParserTest::testParseMemory() { SAXParser parser; std::string xml = parseMemory(parser, XMLWriter::CANONICAL | XMLWriter::PRETTY_PRINT, WSDL); assertTrue (xml == WSDL); } void SAXParserTest::testParsePartialReads() { SAXParser parser; parser.setFeature("http://www.appinf.com/features/enable-partial-reads", true); std::string xml = parse(parser, XMLWriter::CANONICAL | XMLWriter::PRETTY_PRINT, WSDL); assertTrue (xml == WSDL); } void SAXParserTest::setUp() { } void SAXParserTest::tearDown() { } std::string SAXParserTest::parse(XMLReader& reader, int options, const std::string& data) { std::istringstream istr(data); std::ostringstream ostr; XMLWriter writer(ostr, options); writer.setNewLine(XMLWriter::NEWLINE_LF); reader.setContentHandler(&writer); reader.setDTDHandler(&writer); reader.setProperty(XMLReader::PROPERTY_LEXICAL_HANDLER, static_cast(&writer)); InputSource source(istr); reader.parse(&source); return ostr.str(); } std::string SAXParserTest::parseMemory(XMLReader& reader, int options, const std::string& data) { std::ostringstream ostr; XMLWriter writer(ostr, options); writer.setNewLine(XMLWriter::NEWLINE_LF); reader.setContentHandler(&writer); reader.setDTDHandler(&writer); reader.setProperty(XMLReader::PROPERTY_LEXICAL_HANDLER, static_cast(&writer)); reader.parseMemoryNP(data.data(), data.size()); return ostr.str(); } CppUnit::Test* SAXParserTest::suite() { CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SAXParserTest"); CppUnit_addTest(pSuite, SAXParserTest, testSimple1); CppUnit_addTest(pSuite, SAXParserTest, testSimple2); CppUnit_addTest(pSuite, SAXParserTest, testAttributes); CppUnit_addTest(pSuite, SAXParserTest, testCDATA); CppUnit_addTest(pSuite, SAXParserTest, testComment); CppUnit_addTest(pSuite, SAXParserTest, testPI); CppUnit_addTest(pSuite, SAXParserTest, testDTD); CppUnit_addTest(pSuite, SAXParserTest, testInternalEntity); CppUnit_addTest(pSuite, SAXParserTest, testNotation); CppUnit_addTest(pSuite, SAXParserTest, testExternalUnparsed); CppUnit_addTest(pSuite, SAXParserTest, testExternalParsed); CppUnit_addTest(pSuite, SAXParserTest, testDefaultNamespace); CppUnit_addTest(pSuite, SAXParserTest, testNamespaces); CppUnit_addTest(pSuite, SAXParserTest, testNamespacesNoPrefixes); CppUnit_addTest(pSuite, SAXParserTest, testNoNamespaces); CppUnit_addTest(pSuite, SAXParserTest, testUndeclaredNamespace); CppUnit_addTest(pSuite, SAXParserTest, testUndeclaredNamespaceNoPrefixes); CppUnit_addTest(pSuite, SAXParserTest, testUndeclaredNoNamespace); CppUnit_addTest(pSuite, SAXParserTest, testRSS); CppUnit_addTest(pSuite, SAXParserTest, testEncoding); CppUnit_addTest(pSuite, SAXParserTest, testCharacters); CppUnit_addTest(pSuite, SAXParserTest, testParseMemory); CppUnit_addTest(pSuite, SAXParserTest, testParsePartialReads); return pSuite; } const std::string SAXParserTest::SIMPLE1 = "\n"; const std::string SAXParserTest::SIMPLE2 = "\n" "\n"; const std::string SAXParserTest::ATTRIBUTES = "\n" "\t\n" ""; const std::string SAXParserTest::CDATA = "\n" "is inside a CDATA section.\n" "]]>\n" ""; const std::string SAXParserTest::COMMENT = "" "\n" "\t\n" "\t\n" ""; const std::string SAXParserTest::PROCESSING_INSTRUCTION = "\n" "\t\n" "\t\t\n" "\t\ttest\n" "\t\n" "\t\n" "\t\t

this is a test

\n" "\t\n" ""; const std::string SAXParserTest::DTD = "\n" "\n" ""; const std::string SAXParserTest::INTERNAL_ENTITY = "\n" "]>\n" "\n" "\t&appinf;\n" ""; const std::string SAXParserTest::NOTATION = "\n" "\n" "\t\n" "]>\n" ""; const std::string SAXParserTest::EXTERNAL_UNPARSED = "\n" "\n" "\t\n" "]>\n" ""; const std::string SAXParserTest::EXTERNAL_PARSED = "\n" "\n" "]>\n" "\n" "\t&include;\n" "\n"; const std::string SAXParserTest::INCLUDE = "\n" "\tAn external entity.\n" "\n"; const std::string SAXParserTest::DEFAULT_NAMESPACE = "\n" "\tdata\n" ""; const std::string SAXParserTest::NAMESPACES = "\n" "\tdata\n" "\t\n" "\t\tmore data\n" "\t\n" ""; const std::string SAXParserTest::UNDECLARED_NAMESPACE = "\n" "\tdata\n" "\t\n" "\t\tmore data\n" "\t\n" "\t\n" ""; const std::string SAXParserTest::XHTML_LATIN1_ENTITIES = "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n"; const std::string SAXParserTest::RSS = "\n" "\n" "\n" "%HTMLlat1;\n" "]>\n" "\n" " \n" "\n" " \n" " XML.com \n" " http://www.xml.com/\n" " XML.com features a rich mix of information and services for the XML community.\n" " hourly\n" " 2\n" " 2000-01-01T12:00+00:00\n" "\n" " \n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" " \n" "\n" " \n" " Meerkat Powered!\n" " http://meerkat.oreillynet.com/icons/meerkat-powered.jpg\n" " http://meerkat.oreillynet.com\n" " \n" "\n" " \n" " Features: Top 10 XForms Engines\n" " http://www.xml.com/pub/a/2005/02/09/xforms.html\n" " \n" " Micah Dubinko, one of the gurus of XForms, offers a rundown on the state of XForms engines for 2005.\n" " \n" " XML.com\n" " Micah Dubinko\n" " Web, Applications\n" " O'Reilly Media, Inc.\n" " 2005-02-09\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Comparing CSS and XSL: A Reply from Norm Walsh\n" " http://www.xml.com/pub/a/2005/02/09/cssorxsl.html\n" " \n" " Norm Walsh responds to a recent article about CSS and XSL, explaining how and when and why you'd want to use XSLFO or CSS or XSLT.\n" " \n" " XML.com\n" " Norman Walsh\n" " Style\n" " O'Reilly Media, Inc.\n" " 2005-02-09\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Very Dynamic Web Interfaces\n" " http://www.xml.com/pub/a/2005/02/09/xml-http-request.html\n" " \n" " Drew McLellan explains how to use XMLHTTPRequest and Javascript to create web applications with very dynamic, smooth interfaces.\n" " \n" " XML.com\n" " Drew McLellan\n" " Web Development, Instruction\n" " O'Reilly Media, Inc.\n" " 2005-02-09\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Transforming XML: The XPath 2.0 Data Model\n" " http://www.xml.com/pub/a/2005/02/02/xpath2.html\n" " \n" " Bob DuCharme, in his latest Transforming XML column, examines the XPath 2.0, hence the XSLT 2.0, data model.\n" " \n" " XML.com\n" " Bob DuCharme\n" " Style, Style\n" " O'Reilly Media, Inc.\n" " 2005-02-02\n" " Transforming XML\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " XML Tourist: The Silent Soundtrack\n" " http://www.xml.com/pub/a/2005/02/02/silent.html\n" " \n" " In this installation of XML Tourist, John E. Simpson presents an overview of the types of sound-to-text captioning available. Pinpointing closed captioning as the most suitable for use with computerized multimedia, he then explains how XML-based solutions address synchronization issues.\n" " \n" " XML.com\n" " John E. Simpson\n" " Graphics, Vertical Industries\n" " O'Reilly Media, Inc.\n" " 2005-02-02\n" " XML Tourist\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Transforming XML: The XML 2.0 Data Model\n" " http://www.xml.com/pub/a/2005/02/02/xpath2.html\n" " \n" " Bob DuCharme, in his latest Transforming XML column, examines the XPath 2.0, hence the XSLT 2.0, data model.\n" " \n" " XML.com\n" " Bob DuCharme\n" " Style, Style\n" " O'Reilly Media, Inc.\n" " 2005-02-02\n" " Transforming XML\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: An Introduction to TMAPI\n" " http://www.xml.com/pub/a/2005/02/02/tmapi.html\n" " \n" " TMAPI, a Java Topic Map API, is the standard way to interact with XML Topic Maps programmatically from Java. This article provides a tutorial for TMAPI. \n" " \n" " XML.com\n" " Robert Barta, Oliver Leimig\n" " Metadata, Metadata\n" " O'Reilly Media, Inc.\n" " 2005-02-02\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Formal Taxonomies for the U.S. Government\n" " http://www.xml.com/pub/a/2005/01/26/formtax.html\n" " \n" " Mike Daconta, Metadata Program Manager at the Department of Homeland Security, introduces the notion of a formal taxonomy in the context of the Federal Enteriprise Architecture's Data Reference Model.\n" " \n" " XML.com\n" " Michael Daconta\n" " Metadata, Metadata\n" " O'Reilly Media, Inc.\n" " 2005-01-26\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Hacking Open Office\n" " http://www.xml.com/pub/a/2005/01/26/hacking-ooo.html\n" " \n" " Peter Sefton shows us how to use XML tools to hack Open Office file formats.\n" " \n" " XML.com\n" " Peter Sefton\n" " Programming, Tools, Publishing\n" " O'Reilly Media, Inc.\n" " 2005-01-26\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: SIMILE: Practical Metadata for the Semantic Web\n" " http://www.xml.com/pub/a/2005/01/26/simile.html\n" " \n" " Digital libraries and generic metadata form part of the background assumptions and forward-looking goals of the Semantic Web. SIMILE is an interesting project aimed at realizing some of those goals.\n" " \n" " XML.com\n" " Stephen Garland, Ryan Lee, Stefano Mazzocchi\n" " Semantic Web, Metadata\n" " O'Reilly Media, Inc.\n" " 2005-01-26\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Python and XML: Introducing the Amara XML Toolkit\n" " http://www.xml.com/pub/a/2005/01/19/amara.html\n" " \n" " Uche Ogbuji introduces Amara, his new collection of XML tools for Python.\n" " \n" " XML.com\n" " Uche Ogbuji\n" " Programming, Programming\n" " O'Reilly Media, Inc.\n" " 2005-01-19\n" " Python and XML\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Printing XML: Why CSS Is Better than XSL\n" " http://www.xml.com/pub/a/2005/01/19/print.html\n" " \n" " One of the old school debates among XML developers is "CSS versus XSLT." Håkun Wium Lie and Michael Day revive that debate with a shot across XSL's bow.\n" " \n" " XML.com\n" " Michael Day, Håkon Wium Lie\n" " Style, Publishing\n" " O'Reilly Media, Inc.\n" " 2005-01-19\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Reviewing the Architecture of the World Wide Web\n" " http://www.xml.com/pub/a/2005/01/19/review.html\n" " \n" " Harry Halpin reviews the final published edition of the W3C TAG's Architecture of the World Wide Web document.\n" " \n" " XML.com\n" " Harry Halpin\n" " Web, Perspectives\n" " O'Reilly Media, Inc.\n" " 2005-01-19\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: SAML 2: The Building Blocks of Federated Identity\n" " http://www.xml.com/pub/a/2005/01/12/saml2.html\n" " \n" " Paul Madsen reports on the developments in web services security, including a new major release of SAML, which provides the basis for building federated identity.\n" " \n" " XML.com\n" " Paul Madsen\n" " Web Services, Specifications\n" " O'Reilly Media, Inc.\n" " 2005-01-12\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" " \n" " Features: Introducing Comega\n" " http://www.xml.com/pub/a/2005/01/12/comega.html\n" " \n" " Dare Obasanjo explains some of the ways in which Cω--a new language from Microsoft Research--makes XML processing easier and more natural.\n" " \n" " XML.com\n" " Dare Obasanjo\n" " Programming, Instruction\n" " O'Reilly Media, Inc.\n" " 2005-01-12\n" " Features\n" " text/html\n" " en-us\n" " Copyright 2005, O'Reilly Media, Inc.\n" " \n" "\n" "\n" " \n" " Search\n" " Search Meerkat...\n" " s\n" " http://meerkat.oreillynet.com/\n" " \n" "\n" "\n"; const std::string SAXParserTest::ENCODING = "" "\244"; const std::string SAXParserTest::WSDL = "\n" "\n" "\n" "\t\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t\n" "\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\t\n" "\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\t\n" "\t\t\t\t\n" "\t\t\t\n" "\t\t\n" "\t\n" "\t\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\n" "\n";