From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- sw/source/core/swg/SwXMLTextBlocks1.cxx | 570 ++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 sw/source/core/swg/SwXMLTextBlocks1.cxx (limited to 'sw/source/core/swg/SwXMLTextBlocks1.cxx') diff --git a/sw/source/core/swg/SwXMLTextBlocks1.cxx b/sw/source/core/swg/SwXMLTextBlocks1.cxx new file mode 100644 index 000000000..ba610776e --- /dev/null +++ b/sw/source/core/swg/SwXMLTextBlocks1.cxx @@ -0,0 +1,570 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +constexpr OUStringLiteral XMLN_BLOCKLIST = u"BlockList.xml"; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace css::xml::sax; +using namespace xmloff::token; + +using ::xmloff::token::XML_BLOCK_LIST; +using ::xmloff::token::XML_UNFORMATTED_TEXT; +using ::xmloff::token::GetXMLToken; + +ErrCode SwXMLTextBlocks::GetDoc( sal_uInt16 nIdx ) +{ + OUString aFolderName ( GetPackageName ( nIdx ) ); + + if (!IsOnlyTextBlock ( nIdx ) ) + { + try + { + m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ ); + m_xMedium = new SfxMedium( m_xRoot, GetBaseURL(), "writer8" ); + SwReader aReader( *m_xMedium, aFolderName, m_xDoc.get() ); + ReadXML->SetBlockMode( true ); + aReader.Read( *ReadXML ); + ReadXML->SetBlockMode( false ); + // Ole objects fail to display when inserted into the document, as + // the ObjectReplacement folder and contents are missing + OUString sObjReplacements( "ObjectReplacements" ); + if ( m_xRoot->hasByName( sObjReplacements ) ) + { + uno::Reference< document::XStorageBasedDocument > xDocStor( m_xDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< embed::XStorage > xStr( xDocStor->getDocumentStorage() ); + if ( xStr.is() ) + { + m_xRoot->copyElementTo( sObjReplacements, xStr, sObjReplacements ); + uno::Reference< embed::XTransactedObject > xTrans( xStr, uno::UNO_QUERY ); + if ( xTrans.is() ) + xTrans->commit(); + } + } + } + catch( uno::Exception& ) + { + } + + m_xRoot = nullptr; + } + else + { + OUString aStreamName = aFolderName + ".xml"; + try + { + m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ ); + uno::Reference < io::XStream > xStream = m_xRoot->openStreamElement( aStreamName, embed::ElementModes::READ ); + + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = m_aNames[nIdx]->m_aPackageName; + + aParserInput.aInputStream = xStream->getInputStream(); + + // get filter + uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, m_aCurrentText, true ); + uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLTextBlockTokenHandler(); + + // connect parser and filter + uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext); + xParser->setFastDocumentHandler( xFilter ); + xParser->setTokenHandler( xTokenHandler ); + + xParser->registerNamespace( "http://openoffice.org/2000/text", FastToken::NAMESPACE | XML_NAMESPACE_TEXT ); + xParser->registerNamespace( "http://openoffice.org/2000/office", FastToken::NAMESPACE | XML_NAMESPACE_OFFICE ); + + // parse + try + { + xParser->parseStream( aParserInput ); + } + catch( xml::sax::SAXParseException& ) + { + // re throw ? + } + catch( xml::sax::SAXException& ) + { + // re throw ? + } + catch( io::IOException& ) + { + // re throw ? + } + + m_bInfoChanged = false; + MakeBlockText(m_aCurrentText); + } + catch( uno::Exception& ) + { + } + + m_xRoot = nullptr; + } + return ERRCODE_NONE; +} + +// event description for autotext events; this constant should really be +// taken from unocore/unoevents.cxx or ui/unotxt.cxx +const struct SvEventDescription aAutotextEvents[] = +{ + { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" }, + { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" }, + { SvMacroItemId::NONE, nullptr } +}; + +ErrCode SwXMLTextBlocks::GetMacroTable( sal_uInt16 nIdx, + SvxMacroTableDtor& rMacroTable ) +{ + // set current auto text + m_aShort = m_aNames[nIdx]->m_aShort; + m_aLong = m_aNames[nIdx]->m_aLong; + m_aPackageName = m_aNames[nIdx]->m_aPackageName; + + // open stream in proper sub-storage + CloseFile(); + if ( OpenFile() != ERRCODE_NONE ) + return ERR_SWG_READ_ERROR; + + try + { + m_xRoot = m_xBlkRoot->openStorageElement( m_aPackageName, embed::ElementModes::READ ); + bool bOasis = SotStorage::GetVersion( m_xRoot ) > SOFFICE_FILEFORMAT_60; + + uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement( + "atevent.xml", embed::ElementModes::READ ); + OSL_ENSURE(xDocStream.is(), "Can't create stream"); + if ( !xDocStream.is() ) + return ERR_SWG_READ_ERROR; + + uno::Reference xInputStream = xDocStream->getInputStream(); + + // prepare ParserInputSource + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = m_aName; + aParserInput.aInputStream = xInputStream; + + // get service factory + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + // get parser + uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( xContext ); + + // create descriptor and reference to it. Either + // both or neither must be kept because of the + // reference counting! + rtl::Reference pDescriptor = + new SvMacroTableEventDescriptor(aAutotextEvents); + Sequence aFilterArguments{ Any(uno::Reference(pDescriptor)) }; + + // get filter + OUString sFilterComponent = bOasis + ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter") + : OUString("com.sun.star.comp.Writer.XMLAutotextEventsImporter"); + uno::Reference< xml::sax::XDocumentHandler > xFilter( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + sFilterComponent, aFilterArguments, xContext), + UNO_QUERY ); + OSL_ENSURE( xFilter.is(), "can't instantiate autotext-events filter"); + if ( !xFilter.is() ) + return ERR_SWG_READ_ERROR; + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + // parse the stream + try + { + xParser->parseStream( aParserInput ); + } + catch( xml::sax::SAXParseException& ) + { + // workaround for #83452#: SetSize doesn't work + // nRet = ERR_SWG_READ_ERROR; + } + catch( xml::sax::SAXException& ) + { + TOOLS_WARN_EXCEPTION("sw", ""); + return ERR_SWG_READ_ERROR; + } + catch( io::IOException& ) + { + TOOLS_WARN_EXCEPTION("sw", ""); + return ERR_SWG_READ_ERROR; + } + + // and finally, copy macro into table + pDescriptor->copyMacrosIntoTable(rMacroTable); + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("sw", ""); + return ERR_SWG_READ_ERROR; + } + + // success! + return ERRCODE_NONE; +} + +ErrCode SwXMLTextBlocks::GetBlockText( std::u16string_view rShort, OUString& rText ) +{ + OUString aFolderName = GeneratePackageName ( rShort ); + OUString aStreamName = aFolderName + ".xml"; + rText.clear(); + + try + { + bool bTextOnly = true; + + m_xRoot = m_xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ ); + if ( !m_xRoot->hasByName( aStreamName ) || !m_xRoot->isStreamElement( aStreamName ) ) + { + bTextOnly = false; + aStreamName = "content.xml"; + } + + uno::Reference < io::XStream > xContents = m_xRoot->openStreamElement( aStreamName, embed::ElementModes::READ ); + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = m_aName; + aParserInput.aInputStream = xContents->getInputStream(); + + // get filter + uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, rText, bTextOnly ); + uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLTextBlockTokenHandler(); + + // connect parser and filter + uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext); + xParser->setFastDocumentHandler( xFilter ); + xParser->setTokenHandler( xTokenHandler ); + + xParser->registerNamespace( "urn:oasis:names:tc:opendocument:xmlns:office:1.0", FastToken::NAMESPACE | XML_NAMESPACE_OFFICE ); + xParser->registerNamespace( "urn:oasis:names:tc:opendocument:xmlns:text:1.0", FastToken::NAMESPACE | XML_NAMESPACE_TEXT ); + + // parse + try + { + xParser->parseStream( aParserInput ); + } + catch( xml::sax::SAXParseException& ) + { + // re throw ? + } + catch( xml::sax::SAXException& ) + { + // re throw ? + } + catch( io::IOException& ) + { + // re throw ? + } + + m_xRoot = nullptr; + } + catch ( uno::Exception& ) + { + OSL_FAIL( "Tried to open non-existent folder or stream!"); + } + + return ERRCODE_NONE; +} + +ErrCode SwXMLTextBlocks::PutBlockText( const OUString& rShort, + std::u16string_view rText, const OUString& rPackageName ) +{ + GetIndex ( rShort ); + /* + if (xBlkRoot->IsContained ( rPackageName ) ) + { + xBlkRoot->Remove ( rPackageName ); + xBlkRoot->Commit ( ); + } + */ + OUString aStreamName = rPackageName + ".xml"; + + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext); + ErrCode nRes = ERRCODE_NONE; + + try + { + m_xRoot = m_xBlkRoot->openStorageElement( rPackageName, embed::ElementModes::WRITE ); + uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement( aStreamName, + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); + + uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY ); + xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) ); + uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream(); + xWriter->setOutputStream(xOut); + + rtl::Reference xExp( new SwXMLTextBlockExport( xContext, *this, GetXMLToken ( XML_UNFORMATTED_TEXT ), xWriter) ); + + xExp->exportDoc( rText ); + + uno::Reference < embed::XTransactedObject > xTrans( m_xRoot, uno::UNO_QUERY ); + if ( xTrans.is() ) + xTrans->commit(); + + if (! (m_nFlags & SwXmlFlags::NoRootCommit) ) + { + uno::Reference < embed::XTransactedObject > xTmpTrans( m_xBlkRoot, uno::UNO_QUERY ); + if ( xTmpTrans.is() ) + xTmpTrans->commit(); + } + } + catch ( uno::Exception& ) + { + nRes = ERR_SWG_WRITE_ERROR; + } + + m_xRoot = nullptr; + + //TODO/LATER: error handling + /* + sal_uLong nErr = xBlkRoot->GetError(); + sal_uLong nRes = 0; + if( nErr == SVSTREAM_DISK_FULL ) + nRes = ERR_W4W_WRITE_FULL; + else if( nErr != ERRCODE_NONE ) + nRes = ERR_SWG_WRITE_ERROR; + */ + if( !nRes ) // So that we can access the Doc via GetText & nCur + MakeBlockText( rText ); + + return nRes; +} + +void SwXMLTextBlocks::ReadInfo() +{ + const OUString sDocName( XMLN_BLOCKLIST ); + try + { + if ( !m_xBlkRoot.is() || !m_xBlkRoot->hasByName( sDocName ) || !m_xBlkRoot->isStreamElement( sDocName ) ) + return; + + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = sDocName; + + uno::Reference < io::XStream > xDocStream = m_xBlkRoot->openStreamElement( sDocName, embed::ElementModes::READ ); + aParserInput.aInputStream = xDocStream->getInputStream(); + + // get filter + uno::Reference< xml::sax::XFastDocumentHandler > xFilter = new SwXMLBlockListImport( xContext, *this ); + uno::Reference< xml::sax::XFastTokenHandler > xTokenHandler = new SwXMLBlockListTokenHandler(); + + // connect parser and filter + uno::Reference< xml::sax::XFastParser > xParser = xml::sax::FastParser::create(xContext); + xParser->setFastDocumentHandler( xFilter ); + xParser->registerNamespace( "http://openoffice.org/2001/block-list", FastToken::NAMESPACE | XML_NAMESPACE_BLOCKLIST ); + xParser->setTokenHandler( xTokenHandler ); + + // parse + xParser->parseStream( aParserInput ); + } + catch ( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("sw", "when loading " << sDocName); + // re throw ? + } +} +void SwXMLTextBlocks::WriteInfo() +{ + if ( !(m_xBlkRoot.is() || ERRCODE_NONE == OpenFile ( false )) ) + return; + + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext); + + /* + if ( xBlkRoot->IsContained( sDocName) ) + { + xBlkRoot->Remove ( sDocName ); + xBlkRoot->Commit(); + } + */ + + try + { + uno::Reference < io::XStream > xDocStream = m_xBlkRoot->openStreamElement( XMLN_BLOCKLIST, + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); + + uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY ); + xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) ); + uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream(); + xWriter->setOutputStream(xOut); + + rtl::Reference xExp(new SwXMLBlockListExport( xContext, *this, XMLN_BLOCKLIST, xWriter) ); + + xExp->exportDoc( XML_BLOCK_LIST ); + + uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY ); + if ( xTrans.is() ) + xTrans->commit(); + } + catch ( uno::Exception& ) + { + } + + m_bInfoChanged = false; + return; +} + +ErrCode SwXMLTextBlocks::SetMacroTable( + sal_uInt16 nIdx, + const SvxMacroTableDtor& rMacroTable ) +{ + // set current autotext + m_aShort = m_aNames[nIdx]->m_aShort; + m_aLong = m_aNames[nIdx]->m_aLong; + m_aPackageName = m_aNames[nIdx]->m_aPackageName; + + // start XML autotext event export + ErrCode nRes = ERRCODE_NONE; + + uno::Reference< uno::XComponentContext > xContext = + comphelper::getProcessComponentContext(); + + // Get model + uno::Reference< lang::XComponent > xModelComp = + m_xDoc->GetDocShell()->GetModel(); + OSL_ENSURE( xModelComp.is(), "XMLWriter::Write: got no model" ); + if( !xModelComp.is() ) + return ERR_SWG_WRITE_ERROR; + + // open stream in proper sub-storage + CloseFile(); // close (it may be open in read-only-mode) + nRes = OpenFile ( false ); + + if ( ERRCODE_NONE == nRes ) + { + try + { + m_xRoot = m_xBlkRoot->openStorageElement( m_aPackageName, embed::ElementModes::WRITE ); + bool bOasis = SotStorage::GetVersion( m_xRoot ) > SOFFICE_FILEFORMAT_60; + + uno::Reference < io::XStream > xDocStream = m_xRoot->openStreamElement( "atevent.xml", + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ); + + uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY ); + xSet->setPropertyValue("MediaType", Any(OUString( "text/xml" )) ); + uno::Reference < io::XOutputStream > xOutputStream = xDocStream->getOutputStream(); + + // get XML writer + uno::Reference< xml::sax::XWriter > xSaxWriter = + xml::sax::Writer::create( xContext ); + + // connect XML writer to output stream + xSaxWriter->setOutputStream( xOutputStream ); + + // construct events object + uno::Reference xEvents = + new SvMacroTableEventDescriptor(rMacroTable,aAutotextEvents); + + // prepare arguments (prepend doc handler to given arguments) + Sequence aParams{ Any(xSaxWriter), Any(xEvents) }; + + // get filter component + OUString sFilterComponent = bOasis + ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter") + : OUString("com.sun.star.comp.Writer.XMLAutotextEventsExporter"); + uno::Reference< document::XExporter > xExporter( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + sFilterComponent, aParams, xContext), UNO_QUERY); + OSL_ENSURE( xExporter.is(), + "can't instantiate export filter component" ); + if( xExporter.is() ) + { + // connect model and filter + xExporter->setSourceDocument( xModelComp ); + + // filter! + Sequence aFilterProps( 0 ); + uno::Reference < document::XFilter > xFilter( xExporter, + UNO_QUERY ); + xFilter->filter( aFilterProps ); + } + else + nRes = ERR_SWG_WRITE_ERROR; + + // finally, commit stream, sub-storage and storage + uno::Reference < embed::XTransactedObject > xTmpTrans( m_xRoot, uno::UNO_QUERY ); + if ( xTmpTrans.is() ) + xTmpTrans->commit(); + + uno::Reference < embed::XTransactedObject > xTrans( m_xBlkRoot, uno::UNO_QUERY ); + if ( xTrans.is() ) + xTrans->commit(); + + m_xRoot = nullptr; + } + catch ( uno::Exception& ) + { + nRes = ERR_SWG_WRITE_ERROR; + } + + CloseFile(); + } + else + nRes = ERR_SWG_WRITE_ERROR; + + return nRes; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3