diff options
Diffstat (limited to 'xmloff/source/script')
-rw-r--r-- | xmloff/source/script/XMLEventExport.cxx | 320 | ||||
-rw-r--r-- | xmloff/source/script/XMLEventImportHelper.cxx | 145 | ||||
-rw-r--r-- | xmloff/source/script/XMLEventsImportContext.cxx | 178 | ||||
-rw-r--r-- | xmloff/source/script/XMLScriptContextFactory.cxx | 69 | ||||
-rw-r--r-- | xmloff/source/script/XMLScriptExportHandler.cxx | 75 | ||||
-rw-r--r-- | xmloff/source/script/XMLStarBasicContextFactory.cxx | 101 | ||||
-rw-r--r-- | xmloff/source/script/XMLStarBasicExportHandler.cxx | 95 | ||||
-rw-r--r-- | xmloff/source/script/xmlbasicscript.cxx | 317 | ||||
-rw-r--r-- | xmloff/source/script/xmlbasicscript.hxx | 111 | ||||
-rw-r--r-- | xmloff/source/script/xmlscripti.cxx | 130 |
10 files changed, 1541 insertions, 0 deletions
diff --git a/xmloff/source/script/XMLEventExport.cxx b/xmloff/source/script/XMLEventExport.cxx new file mode 100644 index 0000000000..c8c63e7f10 --- /dev/null +++ b/xmloff/source/script/XMLEventExport.cxx @@ -0,0 +1,320 @@ +/* -*- 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 <xmloff/XMLEventExport.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <com/sun/star/document/XEventsSupplier.hpp> + +#include <com/sun/star/container/XNameReplace.hpp> +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <xmloff/xmlexp.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/namespacemap.hxx> + + +using namespace ::com::sun::star::uno; + +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::document::XEventsSupplier; +using ::com::sun::star::container::XNameReplace; +using ::com::sun::star::container::XNameAccess; +using ::xmloff::token::XML_EVENT_LISTENERS; + +constexpr OUStringLiteral gsEventType(u"EventType"); + +XMLEventExport::XMLEventExport(SvXMLExport& rExp) : + m_rExport(rExp), + m_bExtNamespace(false) +{ +} + +XMLEventExport::~XMLEventExport() +{ + // delete all handlers + m_aHandlerMap.clear(); +} + +void XMLEventExport::AddHandler( const OUString& rName, + std::unique_ptr<XMLEventExportHandler> pHandler ) +{ + assert(pHandler); + m_aHandlerMap[rName] = std::move(pHandler); +} + +void XMLEventExport::AddTranslationTable( + const XMLEventNameTranslation* pTransTable ) +{ + if (nullptr != pTransTable) + { + // put translation table into map + for(const XMLEventNameTranslation* pTrans = pTransTable; + pTrans->sAPIName != nullptr; + pTrans++) + { + m_aNameTranslationMap[OUString::createFromAscii(pTrans->sAPIName)] = + XMLEventName(pTrans->nPrefix, pTrans->sXMLName); + } + } + // else? ignore! +} + +void XMLEventExport::Export( Reference<XEventsSupplier> const & rSupplier, + bool bWhitespace) +{ + if (rSupplier.is()) + { + Export(rSupplier->getEvents(), bWhitespace); + } + // else: no supplier, no export -> ignore! +} + +void XMLEventExport::Export( Reference<XNameReplace> const & rReplace, + bool bWhitespace) +{ + Reference<XNameAccess> xAccess(rReplace); + Export(xAccess, bWhitespace); +} + +void XMLEventExport::Export( Reference<XNameAccess> const & rAccess, + bool bWhitespace) +{ + // early out if we don't actually get any events + if (!rAccess.is()) + { + return; + } + + // have we already processed an element? + bool bStarted = false; + + // iterate over all event types + const Sequence<OUString> aNames = rAccess->getElementNames(); + for(const auto& rName : aNames) + { + // translate name + NameMap::iterator aIter = m_aNameTranslationMap.find(rName); + if (aIter != m_aNameTranslationMap.end()) + { + const XMLEventName& rXmlName = aIter->second; + + // get PropertyValues for this event + Any aAny = rAccess->getByName( rName ); + Sequence<PropertyValue> aValues; + aAny >>= aValues; + + // now export the current event + ExportEvent( aValues, rXmlName, bWhitespace, bStarted ); + } + else + { + // don't proceed further + SAL_WARN("xmloff", "Unknown event name:" << rName ); + } + } + + // close <script:events> element (if it was opened before) + if (bStarted) + { + EndElement(bWhitespace); + } +} + +void XMLEventExport::ExportExt( Reference<XNameAccess> const & rAccess ) +{ + // set bExtNamespace flag to use XML_NAMESPACE_OFFICE_EXT namespace + // for events element (not for child elements) + m_bExtNamespace = true; + Export(rAccess); + m_bExtNamespace = false; // reset for future Export calls +} + +/// export a singular event and write <office:events> container +void XMLEventExport::ExportSingleEvent( + const Sequence<PropertyValue>& rEventValues, + const OUString& rApiEventName, + bool bUseWhitespace ) +{ + // translate the name + NameMap::iterator aIter = m_aNameTranslationMap.find(rApiEventName); + if (aIter != m_aNameTranslationMap.end()) + { + const XMLEventName& rXmlName = aIter->second; + + // export the event ... + bool bStarted = false; + ExportEvent( rEventValues, rXmlName, bUseWhitespace, bStarted ); + + // ... and close the container element (if necessary) + if (bStarted) + { + EndElement(bUseWhitespace); + } + } + else + { + // don't proceed further + SAL_WARN("xmloff", "Unknown event name:" << rApiEventName ); + } +} + + +/// export a single event +void XMLEventExport::ExportEvent( + const Sequence<PropertyValue>& rEventValues, + const XMLEventName& rXmlEventName, + bool bUseWhitespace, + bool& rExported ) +{ + // search for EventType value and then delegate to EventHandler + const PropertyValue* pValue = std::find_if(rEventValues.begin(), rEventValues.end(), + [](const PropertyValue& rValue) { return gsEventType == rValue.Name; }); + + if (pValue == rEventValues.end()) + return; + + // found! Now find handler and delegate + OUString sType; + pValue->Value >>= sType; + + if (m_aHandlerMap.count(sType)) + { + if (! rExported) + { + // OK, we have't yet exported the enclosing + // element. So we do that now. + rExported = true; + StartElement(bUseWhitespace); + } + + OUString aEventQName( + m_rExport.GetNamespaceMap().GetQNameByKey( + rXmlEventName.m_nPrefix, rXmlEventName.m_aName ) ); + + // delegate to proper ExportEventHandler + m_aHandlerMap[sType]->Export(m_rExport, aEventQName, + rEventValues, bUseWhitespace); + } + else + { + if ( sType != "None" ) + { + OSL_FAIL("unknown event type returned by API"); + // unknown type -> error (ignore) + } + // else: we ignore None fields + } +} + + +void XMLEventExport::StartElement(bool bWhitespace) +{ + if (bWhitespace) + { + m_rExport.IgnorableWhitespace(); + } + sal_uInt16 nNamespace = m_bExtNamespace ? XML_NAMESPACE_OFFICE_EXT + : XML_NAMESPACE_OFFICE; + m_rExport.StartElement( nNamespace, XML_EVENT_LISTENERS, + bWhitespace); +} + +void XMLEventExport::EndElement(bool bWhitespace) +{ + sal_uInt16 nNamespace = m_bExtNamespace ? XML_NAMESPACE_OFFICE_EXT + : XML_NAMESPACE_OFFICE; + m_rExport.EndElement(nNamespace, XML_EVENT_LISTENERS, bWhitespace); + if (bWhitespace) + { + m_rExport.IgnorableWhitespace(); + } +} + + +// implement aStandardEventTable (defined in xmlevent.hxx) +const XMLEventNameTranslation aStandardEventTable[] = +{ + { "OnSelect", XML_NAMESPACE_DOM, "select" }, // "on-select" + { "OnInsertStart", XML_NAMESPACE_OFFICE, "insert-start" }, // "on-insert-start" + { "OnInsertDone", XML_NAMESPACE_OFFICE, "insert-done" }, // "on-insert-done" + { "OnMailMerge", XML_NAMESPACE_OFFICE, "mail-merge" }, // "on-mail-merge" + { "OnAlphaCharInput", XML_NAMESPACE_OFFICE, "alpha-char-input" }, // "on-alpha-char-input" + { "OnNonAlphaCharInput", XML_NAMESPACE_OFFICE, "non-alpha-char-input" }, // "on-non-alpha-char-input" + { "OnResize", XML_NAMESPACE_DOM, "resize" }, // "on-resize" + { "OnMove", XML_NAMESPACE_OFFICE, "move" }, // "on-move" + { "OnPageCountChange", XML_NAMESPACE_OFFICE, "page-count-change" }, // "on-page-count-change" + { "OnMouseOver", XML_NAMESPACE_DOM, "mouseover" }, // "on-mouse-over" + { "OnClick", XML_NAMESPACE_DOM, "click" }, // "on-click" + { "OnMouseOut", XML_NAMESPACE_DOM, "mouseout" }, // "on-mouse-out" + { "OnLoadError", XML_NAMESPACE_OFFICE, "load-error" }, // "on-load-error" + { "OnLoadCancel", XML_NAMESPACE_OFFICE, "load-cancel" }, // "on-load-cancel" + { "OnLoadDone", XML_NAMESPACE_OFFICE, "load-done" }, // "on-load-done" + { "OnLoad", XML_NAMESPACE_DOM, "load" }, // "on-load" + { "OnUnload", XML_NAMESPACE_DOM, "unload" }, // "on-unload" + { "OnStartApp", XML_NAMESPACE_OFFICE, "start-app" }, // "on-start-app" + { "OnCloseApp", XML_NAMESPACE_OFFICE, "close-app" }, // "on-close-app" + { "OnNew", XML_NAMESPACE_OFFICE, "new" }, // "on-new" + { "OnSave", XML_NAMESPACE_OFFICE, "save" }, // "on-save" + { "OnSaveAs", XML_NAMESPACE_OFFICE, "save-as" }, // "on-save-as" + { "OnFocus", XML_NAMESPACE_DOM, "DOMFocusIn" }, // "on-focus" + { "OnUnfocus", XML_NAMESPACE_DOM, "DOMFocusOut" }, // "on-unfocus" + { "OnPrint", XML_NAMESPACE_OFFICE, "print" }, // "on-print" + { "OnError", XML_NAMESPACE_DOM, "error" }, // "on-error" + { "OnLoadFinished", XML_NAMESPACE_OFFICE, "load-finished" }, // "on-load-finished" + { "OnSaveFinished", XML_NAMESPACE_OFFICE, "save-finished" }, // "on-save-finished" + { "OnModifyChanged", XML_NAMESPACE_OFFICE, "modify-changed" }, // "on-modify-changed" + { "OnPrepareUnload", XML_NAMESPACE_OFFICE, "prepare-unload" }, // "on-prepare-unload" + { "OnNewMail", XML_NAMESPACE_OFFICE, "new-mail" }, // "on-new-mail" + { "OnToggleFullscreen", XML_NAMESPACE_OFFICE, "toggle-fullscreen" }, // "on-toggle-fullscreen" + { "OnSaveDone", XML_NAMESPACE_OFFICE, "save-done" }, // "on-save-done" + { "OnSaveAsDone", XML_NAMESPACE_OFFICE, "save-as-done" }, // "on-save-as-done" + { "OnCopyTo", XML_NAMESPACE_OFFICE, "copy-to" }, + { "OnCopyToDone", XML_NAMESPACE_OFFICE, "copy-to-done" }, + { "OnViewCreated", XML_NAMESPACE_OFFICE, "view-created" }, + { "OnPrepareViewClosing", XML_NAMESPACE_OFFICE, "prepare-view-closing" }, + { "OnViewClosed", XML_NAMESPACE_OFFICE, "view-close" }, + { "OnVisAreaChanged", XML_NAMESPACE_OFFICE, "visarea-changed" }, // "on-visarea-changed" + { "OnCreate", XML_NAMESPACE_OFFICE, "create" }, + { "OnSaveAsFailed", XML_NAMESPACE_OFFICE, "save-as-failed" }, + { "OnSaveFailed", XML_NAMESPACE_OFFICE, "save-failed" }, + { "OnCopyToFailed", XML_NAMESPACE_OFFICE, "copy-to-failed" }, + { "OnTitleChanged", XML_NAMESPACE_OFFICE, "title-changed" }, + { "OnModeChanged", XML_NAMESPACE_OFFICE, "mode-changed" }, + { "OnSaveTo", XML_NAMESPACE_OFFICE, "save-to" }, + { "OnSaveToDone", XML_NAMESPACE_OFFICE, "save-to-done" }, + { "OnSaveToFailed", XML_NAMESPACE_OFFICE, "save-to-failed" }, + { "OnSubComponentOpened", XML_NAMESPACE_OFFICE, "subcomponent-opened" }, + { "OnSubComponentClosed", XML_NAMESPACE_OFFICE, "subcomponent-closed" }, + { "OnStorageChanged", XML_NAMESPACE_OFFICE, "storage-changed" }, + { "OnMailMergeFinished", XML_NAMESPACE_OFFICE, "mail-merge-finished" }, + { "OnFieldMerge", XML_NAMESPACE_OFFICE, "field-merge" }, + { "OnFieldMergeFinished", XML_NAMESPACE_OFFICE, "field-merge-finished" }, + { "OnLayoutFinished", XML_NAMESPACE_OFFICE, "layout-finished" }, + { "OnDoubleClick", XML_NAMESPACE_OFFICE, "dblclick" }, + { "OnRightClick", XML_NAMESPACE_OFFICE, "contextmenu" }, + { "OnChange", XML_NAMESPACE_OFFICE, "content-changed" }, + { "OnCalculate", XML_NAMESPACE_OFFICE, "calculated" }, + + { nullptr, 0, nullptr } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLEventImportHelper.cxx b/xmloff/source/script/XMLEventImportHelper.cxx new file mode 100644 index 0000000000..83662c5ffc --- /dev/null +++ b/xmloff/source/script/XMLEventImportHelper.cxx @@ -0,0 +1,145 @@ +/* -*- 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 <XMLEventImportHelper.hxx> +#include <tools/debug.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmlerror.hxx> + +using ::com::sun::star::uno::Reference; + +XMLEventImportHelper::XMLEventImportHelper() : + pEventNameMap(new NameMap) +{ +} + +XMLEventImportHelper::~XMLEventImportHelper() +{ + // delete factories + aFactoryMap.clear(); + + // delete name map + pEventNameMap.reset(); +} + +void XMLEventImportHelper::RegisterFactory( + const OUString& rLanguage, + std::unique_ptr<XMLEventContextFactory> pFactory ) +{ + assert(pFactory); + aFactoryMap[rLanguage] = std::move(pFactory); +} + +void XMLEventImportHelper::AddTranslationTable( + const XMLEventNameTranslation* pTransTable ) +{ + if (nullptr == pTransTable) + return; + + // put translation table into map + for(const XMLEventNameTranslation* pTrans = pTransTable; + pTrans->sAPIName != nullptr; + pTrans++) + { + XMLEventName aName( pTrans->nPrefix, pTrans->sXMLName ); + + // check for conflicting entries + DBG_ASSERT(pEventNameMap->find(aName) == pEventNameMap->end(), + "conflicting event translations"); + + // assign new translation + (*pEventNameMap)[aName] = + OUString::createFromAscii(pTrans->sAPIName); + } + // else? ignore! +} + +void XMLEventImportHelper::PushTranslationTable() +{ + // save old map and install new one + aEventNameMapVector.push_back(std::move(pEventNameMap)); + pEventNameMap.reset( new NameMap ); +} + +void XMLEventImportHelper::PopTranslationTable() +{ + DBG_ASSERT(!aEventNameMapVector.empty(), + "no translation tables left to pop"); + if ( !aEventNameMapVector.empty() ) + { + // delete current and install old map + pEventNameMap = std::move(aEventNameMapVector.back()); + aEventNameMapVector.pop_back(); + } +} + + +SvXMLImportContext* XMLEventImportHelper::CreateContext( + SvXMLImport& rImport, + const Reference<css::xml::sax::XFastAttributeList> & xAttrList, + XMLEventsImportContext* rEvents, + const OUString& rXmlEventName, + const OUString& rLanguage) +{ + SvXMLImportContext* pContext = nullptr; + + // translate event name from xml to api + OUString sMacroName; + sal_uInt16 nMacroPrefix = + rImport.GetNamespaceMap().GetKeyByAttrValueQName(rXmlEventName, + &sMacroName ); + XMLEventName aEventName( nMacroPrefix, sMacroName ); + NameMap::iterator aNameIter = pEventNameMap->find(aEventName); + if (aNameIter != pEventNameMap->end()) + { + OUString aScriptLanguage; + sal_uInt16 nScriptPrefix = rImport.GetNamespaceMap(). + GetKeyByAttrValueQName(rLanguage, &aScriptLanguage); + if( XML_NAMESPACE_OOO != nScriptPrefix ) + aScriptLanguage = rLanguage ; + + // check for factory + FactoryMap::iterator aFactoryIterator = + aFactoryMap.find(aScriptLanguage); + if (aFactoryIterator != aFactoryMap.end()) + { + // delegate to factory + pContext = aFactoryIterator->second->CreateContext( + rImport, xAttrList, + rEvents, aNameIter->second); + } + } + + // default context (if no context was created above) + if( nullptr == pContext ) + { + pContext = new SvXMLImportContext(rImport); + + rImport.SetError(XMLERROR_FLAG_ERROR | XMLERROR_ILLEGAL_EVENT, + { rXmlEventName, rLanguage }); + + } + + return pContext; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLEventsImportContext.cxx b/xmloff/source/script/XMLEventsImportContext.cxx new file mode 100644 index 0000000000..0b236579f7 --- /dev/null +++ b/xmloff/source/script/XMLEventsImportContext.cxx @@ -0,0 +1,178 @@ +/* -*- 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 <xmloff/XMLEventsImportContext.hxx> + +#include <XMLEventImportHelper.hxx> + +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <comphelper/attributelist.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlerror.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::container::XNameReplace; +using ::com::sun::star::document::XEventsSupplier; +using ::com::sun::star::lang::IllegalArgumentException; + + +XMLEventsImportContext::XMLEventsImportContext(SvXMLImport& rImport) : + SvXMLImportContext(rImport) +{ +} + + +XMLEventsImportContext::XMLEventsImportContext( + SvXMLImport& rImport, + const Reference<XEventsSupplier> & xEventsSupplier) : + SvXMLImportContext(rImport), + m_xEvents(xEventsSupplier->getEvents()) +{ +} + + +XMLEventsImportContext::XMLEventsImportContext( + SvXMLImport& rImport, + const Reference<XNameReplace> & xNameReplace) : + SvXMLImportContext(rImport), + m_xEvents(xNameReplace) +{ +} + +XMLEventsImportContext::~XMLEventsImportContext() +{ +// // if, for whatever reason, the object gets destroyed prematurely, +// // we need to delete the collected events +} + + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLEventsImportContext::createFastChildContext( + sal_Int32 /*nElement*/, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + // a) search for script:language and script:event-name attribute + // b) delegate to factory. The factory will: + // 1) translate XML event name into API event name + // 2) get proper event context factory from import + // 3) instantiate context + + // a) search for script:language and script:event-name attribute + OUString sLanguage; + OUString sEventName; + for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) + { + OUString sValue = aIter.toString(); + + if (aIter.getToken() == XML_ELEMENT(SCRIPT, XML_EVENT_NAME)) + { + sEventName = sValue; + } + else if (aIter.getToken() == XML_ELEMENT(SCRIPT, XML_LANGUAGE)) + { + sLanguage = sValue; + // else: ignore -> let child context handle this + } + // else: ignore -> let child context handle this + } + + // b) delegate to factory + return GetImport().GetEventImport().CreateContext( + GetImport(), xAttrList, this, sEventName, sLanguage); +} + +void XMLEventsImportContext::SetEvents( + const Reference<XEventsSupplier> & xEventsSupplier) +{ + if (xEventsSupplier.is()) + { + SetEvents(xEventsSupplier->getEvents()); + } +} + +void XMLEventsImportContext::SetEvents( + const Reference<XNameReplace> & xNameRepl) +{ + if (xNameRepl.is()) + { + m_xEvents = xNameRepl; + + // now iterate over vector and a) insert b) delete all elements + for(const auto& rEvent : m_aCollectEvents) + { + AddEventValues(rEvent.first, rEvent.second); + } + m_aCollectEvents.clear(); + } +} + +void XMLEventsImportContext::GetEventSequence( + const OUString& rName, + Sequence<PropertyValue> & rSequence ) +{ + // search through the vector + // (This shouldn't take a lot of time, since this method should only get + // called if only one (or few) events are being expected) + + auto aIter = std::find_if(m_aCollectEvents.begin(), m_aCollectEvents.end(), + [&rName](EventNameValuesPair& rEvent) { return rEvent.first == rName; }); + + // if we're not at the end, set the sequence + if (aIter != m_aCollectEvents.end()) + { + rSequence = aIter->second; + } +} + +void XMLEventsImportContext::AddEventValues( + const OUString& rEventName, + const Sequence<PropertyValue> & rValues ) +{ + // if we already have the events, set them; else just collect + if (m_xEvents.is()) + { + // set event (if name is known) + if (m_xEvents->hasByName(rEventName)) + { + try + { + m_xEvents->replaceByName(rEventName, Any(rValues)); + } catch ( const IllegalArgumentException & rException ) + { + Sequence<OUString> aMsgParams { rEventName }; + + GetImport().SetError(XMLERROR_FLAG_ERROR | + XMLERROR_ILLEGAL_EVENT, + aMsgParams, rException.Message, nullptr); + } + } + } + else + { + EventNameValuesPair aPair(rEventName, rValues); + m_aCollectEvents.push_back(aPair); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLScriptContextFactory.cxx b/xmloff/source/script/XMLScriptContextFactory.cxx new file mode 100644 index 0000000000..0e7caa3d69 --- /dev/null +++ b/xmloff/source/script/XMLScriptContextFactory.cxx @@ -0,0 +1,69 @@ +/* -*- 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 <comphelper/propertyvalue.hxx> +#include <XMLScriptContextFactory.hxx> +#include <xmloff/XMLEventsImportContext.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> + +using namespace ::xmloff::token; + +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +constexpr OUString gsEventType(u"EventType"_ustr); +constexpr OUString gsScript(u"Script"_ustr); +constexpr OUString gsURL(u"Script"_ustr); + +XMLScriptContextFactory::XMLScriptContextFactory() {} + +XMLScriptContextFactory::~XMLScriptContextFactory() {} + +SvXMLImportContext* XMLScriptContextFactory::CreateContext( + SvXMLImport& rImport, const Reference<XFastAttributeList>& xAttrList, + XMLEventsImportContext* rEvents, const OUString& rApiEventName) +{ + OUString sURLVal; + + for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList)) + { + if (aIter.getToken() == XML_ELEMENT(XLINK, XML_HREF)) + sURLVal = aIter.toString(); + // else: ignore + } + + if (!sURLVal.isEmpty()) + rImport.NotifyMacroEventRead(); + + Sequence<PropertyValue> aValues{ comphelper::makePropertyValue(gsEventType, gsScript), + comphelper::makePropertyValue(gsURL, sURLVal) }; + + // add values for event now + rEvents->AddEventValues(rApiEventName, aValues); + + // return dummy context + return new SvXMLImportContext(rImport); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLScriptExportHandler.cxx b/xmloff/source/script/XMLScriptExportHandler.cxx new file mode 100644 index 0000000000..6b35a44564 --- /dev/null +++ b/xmloff/source/script/XMLScriptExportHandler.cxx @@ -0,0 +1,75 @@ +/* -*- 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 <XMLScriptExportHandler.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <xmloff/xmlexp.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> + + +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +using ::com::sun::star::beans::PropertyValue; + +constexpr OUStringLiteral gsURL(u"Script"); + +XMLScriptExportHandler::XMLScriptExportHandler() +{ +} + +XMLScriptExportHandler::~XMLScriptExportHandler() +{ +} + +void XMLScriptExportHandler::Export( + SvXMLExport& rExport, + const OUString& rEventQName, + const Sequence<PropertyValue> & rValues, + bool bUseWhitespace) +{ + + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_LANGUAGE, + rExport.GetNamespaceMap().GetQNameByKey( + XML_NAMESPACE_OOO, GetXMLToken(XML_SCRIPT) ) ); + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, rEventQName); + + for(const auto& rValue : rValues) + { + if (gsURL == rValue.Name) + { + OUString sTmp; + rValue.Value >>= sTmp; + rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sTmp); + + // #i110911# xlink:type="simple" is required + rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE); + } + // else: disregard + } + + SvXMLElementExport aEventElemt(rExport, XML_NAMESPACE_SCRIPT, + XML_EVENT_LISTENER, + bUseWhitespace, false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLStarBasicContextFactory.cxx b/xmloff/source/script/XMLStarBasicContextFactory.cxx new file mode 100644 index 0000000000..2a2b76cfb5 --- /dev/null +++ b/xmloff/source/script/XMLStarBasicContextFactory.cxx @@ -0,0 +1,101 @@ +/* -*- 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 <comphelper/propertyvalue.hxx> +#include <XMLStarBasicContextFactory.hxx> +#include <xmloff/XMLEventsImportContext.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <o3tl/string_view.hxx> + + +using namespace ::xmloff::token; + +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + + +constexpr OUString gsEventType(u"EventType"_ustr); +constexpr OUString gsLibrary(u"Library"_ustr); +constexpr OUString gsMacroName(u"MacroName"_ustr); +constexpr OUString gsStarBasic(u"StarBasic"_ustr); + +XMLStarBasicContextFactory::XMLStarBasicContextFactory() +{ +} + +XMLStarBasicContextFactory::~XMLStarBasicContextFactory() +{ +} + +SvXMLImportContext* XMLStarBasicContextFactory::CreateContext( + SvXMLImport& rImport, + const Reference<XFastAttributeList> & xAttrList, + XMLEventsImportContext* rEvents, + const OUString& rApiEventName) +{ + OUString sLibraryVal; + OUString sMacroNameVal; + + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + if (aIter.getToken() == XML_ELEMENT(SCRIPT, XML_MACRO_NAME)) + sMacroNameVal = aIter.toString(); + // else: ignore + } + + const OUString& rApp = GetXMLToken( XML_APPLICATION ); + const OUString& rDoc = GetXMLToken( XML_DOCUMENT ); + if( sMacroNameVal.getLength() > rApp.getLength()+1 && + o3tl::equalsIgnoreAsciiCase(sMacroNameVal.subView(0,rApp.getLength()), rApp ) && + ':' == sMacroNameVal[rApp.getLength()] ) + { + sLibraryVal = "StarOffice"; + sMacroNameVal = sMacroNameVal.copy( rApp.getLength()+1 ); + } + else if( sMacroNameVal.getLength() > rDoc.getLength()+1 && + o3tl::equalsIgnoreAsciiCase(sMacroNameVal.subView(0,rDoc.getLength()), rDoc ) && + ':' == sMacroNameVal[rDoc.getLength()] ) + { + sLibraryVal = rDoc; + sMacroNameVal = sMacroNameVal.copy( rDoc.getLength()+1 ); + } + + if (!sMacroNameVal.isEmpty()) + rImport.NotifyMacroEventRead(); + + Sequence<PropertyValue> aValues + { + comphelper::makePropertyValue(gsEventType, gsStarBasic), + comphelper::makePropertyValue(gsLibrary, sLibraryVal), + comphelper::makePropertyValue(gsMacroName, sMacroNameVal) + }; + + // add values for event now + rEvents->AddEventValues(rApiEventName, aValues); + + // return dummy context + return new SvXMLImportContext(rImport); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/XMLStarBasicExportHandler.cxx b/xmloff/source/script/XMLStarBasicExportHandler.cxx new file mode 100644 index 0000000000..2170d32fdf --- /dev/null +++ b/xmloff/source/script/XMLStarBasicExportHandler.cxx @@ -0,0 +1,95 @@ +/* -*- 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 <XMLStarBasicExportHandler.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <xmloff/xmlexp.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> + + +using namespace ::com::sun::star::uno; +using namespace ::xmloff::token; + +using ::com::sun::star::beans::PropertyValue; + + +constexpr OUStringLiteral gsStarBasic(u"StarBasic"); +constexpr OUStringLiteral gsLibrary(u"Library"); +constexpr OUStringLiteral gsMacroName(u"MacroName"); +constexpr OUStringLiteral gsStarOffice(u"StarOffice"); +constexpr OUStringLiteral gsApplication(u"application"); + +XMLStarBasicExportHandler::XMLStarBasicExportHandler() +{ +} + +XMLStarBasicExportHandler::~XMLStarBasicExportHandler() +{ +} + +void XMLStarBasicExportHandler::Export( + SvXMLExport& rExport, + const OUString& rEventQName, + const Sequence<PropertyValue> & rValues, + bool bUseWhitespace) +{ + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_LANGUAGE, + rExport.GetNamespaceMap().GetQNameByKey( + XML_NAMESPACE_OOO, gsStarBasic ) ); + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_EVENT_NAME, rEventQName); + + OUString sLocation, sName; + for(const auto& rValue : rValues) + { + if (gsLibrary == rValue.Name) + { + OUString sTmp; + rValue.Value >>= sTmp; + sLocation = GetXMLToken( + (sTmp.equalsIgnoreAsciiCase(gsApplication) || + sTmp.equalsIgnoreAsciiCase(gsStarOffice) ) ? XML_APPLICATION + : XML_DOCUMENT ); + } + else if (gsMacroName == rValue.Name) + { + rValue.Value >>= sName; + } + // else: disregard + } + + if( !sLocation.isEmpty() ) + { + OUString sTmp = sLocation + ":" + sName; + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_MACRO_NAME, + sTmp); + } + else + { + rExport.AddAttribute(XML_NAMESPACE_SCRIPT, XML_MACRO_NAME, sName ); + } + + SvXMLElementExport aEventElemt(rExport, XML_NAMESPACE_SCRIPT, + XML_EVENT_LISTENER, + bUseWhitespace, false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/xmlbasicscript.cxx b/xmloff/source/script/xmlbasicscript.cxx new file mode 100644 index 0000000000..3115cdd8d1 --- /dev/null +++ b/xmloff/source/script/xmlbasicscript.cxx @@ -0,0 +1,317 @@ +/* -*- 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 <sal/config.h> + +#include "xmlbasicscript.hxx" +#include <sal/log.hxx> +#include <xmlscript/xmlns.h> +#include <utility> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltkmap.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/diagnose_ex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::xmloff::token; + +namespace xmloff +{ +// BasicElementBase + +BasicElementBase::BasicElementBase(SvXMLImport& rImport) + : SvXMLImportContext(rImport) +{ +} + +bool BasicElementBase::getBoolAttr(bool* pRet, sal_Int32 nToken, + const Reference<XFastAttributeList>& xAttributes) +{ + OUString aValue = xAttributes->getOptionalValue(nToken); + if (!aValue.isEmpty()) + { + if (aValue == "true") + { + *pRet = true; + return true; + } + else if (aValue == "false") + { + *pRet = false; + return true; + } + else + { + throw xml::sax::SAXException(SvXMLImport::getNameFromToken(nToken) + + ": no boolean value (true|false)!", + Reference<XInterface>(), Any()); + } + } + return false; +} + +// BasicLibrariesElement + +BasicLibrariesElement::BasicLibrariesElement(SvXMLImport& rImport, + const css::uno::Reference<css::frame::XModel>& rxModel) + : BasicElementBase(rImport) +{ + // try the XEmbeddedScripts interface + Reference<document::XEmbeddedScripts> xDocumentScripts(rxModel, UNO_QUERY_THROW); + m_xLibContainer = xDocumentScripts->getBasicLibraries(); + + if (!m_xLibContainer.is()) + { + // try the "BasicLibraries" property (old-style, for compatibility) + Reference<beans::XPropertySet> xPSet(rxModel, UNO_QUERY); + if (xPSet.is()) + xPSet->getPropertyValue("BasicLibraries") >>= m_xLibContainer; + } + + SAL_WARN_IF(!m_xLibContainer.is(), "xmlscript.xmlflat", + "BasicImport::startRootElement: nowhere to import to!"); + + if (!m_xLibContainer.is()) + { + throw xml::sax::SAXException("nowhere to import to", Reference<XInterface>(), Any()); + } +} + +// XElement + +Reference<XFastContextHandler> +BasicLibrariesElement::createFastChildContext(sal_Int32 nElement, + const Reference<XFastAttributeList>& xAttributes) +{ + if (!IsTokenInNamespace(nElement, XML_NAMESPACE_OOO)) + { + throw xml::sax::SAXException("illegal namespace!", Reference<XInterface>(), Any()); + } + else if ((nElement & TOKEN_MASK) == XML_LIBRARY_LINKED) + { + OUString aName = xAttributes->getValue(NAMESPACE_TOKEN(XML_NAMESPACE_OOO) | XML_NAME); + + OUString aStorageURL = xAttributes->getValue(XML_ELEMENT(XLINK, XML_HREF)); + + bool bReadOnly = false; + getBoolAttr(&bReadOnly, NAMESPACE_TOKEN(XML_NAMESPACE_OOO) | XML_READONLY, xAttributes); + + if (m_xLibContainer.is()) + { + try + { + Reference<container::XNameAccess> xLib( + m_xLibContainer->createLibraryLink(aName, aStorageURL, bReadOnly)); + if (xLib.is()) + return new BasicElementBase(GetImport()); + } + catch (const container::ElementExistException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", + "BasicLibrariesElement::startChildElement"); + } + catch (const lang::IllegalArgumentException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", + "BasicLibrariesElement::startChildElement"); + } + } + } + else if ((nElement & TOKEN_MASK) == XML_LIBRARY_EMBEDDED) + { + // TODO: create password protected libraries + + OUString aName = xAttributes->getValue(NAMESPACE_TOKEN(XML_NAMESPACE_OOO) | XML_NAME); + + bool bReadOnly = false; + getBoolAttr(&bReadOnly, NAMESPACE_TOKEN(XML_NAMESPACE_OOO) | XML_READONLY, xAttributes); + + if (m_xLibContainer.is()) + { + try + { + Reference<container::XNameContainer> xLib; + if (m_xLibContainer->hasByName(aName)) + { + // Standard library + m_xLibContainer->getByName(aName) >>= xLib; + } + else + { + xLib.set(m_xLibContainer->createLibrary(aName)); + } + + if (xLib.is()) + return new BasicEmbeddedLibraryElement(GetImport(), m_xLibContainer, aName, + bReadOnly); + } + catch (const lang::IllegalArgumentException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", + "BasicLibrariesElement::startChildElement"); + } + } + } + else + { + throw xml::sax::SAXException("expected library-linked or library-embedded element!", + Reference<XInterface>(), Any()); + } + + return nullptr; +} + +// BasicEmbeddedLibraryElement + +BasicEmbeddedLibraryElement::BasicEmbeddedLibraryElement( + SvXMLImport& rImport, const Reference<script::XLibraryContainer2>& rxLibContainer, + OUString aLibName, bool bReadOnly) + : BasicElementBase(rImport) + , m_xLibContainer(rxLibContainer) + , m_aLibName(std::move(aLibName)) + , m_bReadOnly(bReadOnly) +{ + try + { + if (m_xLibContainer.is() && m_xLibContainer->hasByName(m_aLibName)) + m_xLibContainer->getByName(m_aLibName) >>= m_xLib; + } + catch (const lang::WrappedTargetException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", "BasicEmbeddedLibraryElement::CTOR:"); + } +} + +Reference<XFastContextHandler> BasicEmbeddedLibraryElement::createFastChildContext( + sal_Int32 nElement, const Reference<XFastAttributeList>& xAttributes) +{ + if (!IsTokenInNamespace(nElement, XML_NAMESPACE_OOO)) + { + throw xml::sax::SAXException("illegal namespace!", Reference<XInterface>(), Any()); + } + else if ((nElement & TOKEN_MASK) == XML_MODULE) + { + OUString aName = xAttributes->getValue(NAMESPACE_TOKEN(XML_NAMESPACE_OOO) | XML_NAME); + + if (m_xLib.is() && !aName.isEmpty()) + return new BasicModuleElement(GetImport(), m_xLib, aName); + } + else + { + throw xml::sax::SAXException("expected module element!", Reference<XInterface>(), Any()); + } + + return nullptr; +} + +void BasicEmbeddedLibraryElement::endFastElement(sal_Int32) +{ + if (m_xLibContainer.is() && m_xLibContainer->hasByName(m_aLibName) && m_bReadOnly) + m_xLibContainer->setLibraryReadOnly(m_aLibName, m_bReadOnly); +} + +// BasicModuleElement + +BasicModuleElement::BasicModuleElement(SvXMLImport& rImport, + const Reference<container::XNameContainer>& rxLib, + OUString aName) + : BasicElementBase(rImport) + , m_xLib(rxLib) + , m_aName(std::move(aName)) +{ +} + +Reference<XFastContextHandler> +BasicModuleElement::createFastChildContext(sal_Int32 nElement, + const Reference<XFastAttributeList>& xAttributes) +{ + // TODO: <byte-code> + + if (!IsTokenInNamespace(nElement, XML_NAMESPACE_OOO)) + { + throw xml::sax::SAXException("illegal namespace!", Reference<XInterface>(), Any()); + } + else if ((nElement & TOKEN_MASK) == XML_SOURCE_CODE) + { + // TODO: password protected libraries + + if (xAttributes.is()) + { + if (m_xLib.is() && !m_aName.isEmpty()) + return new BasicSourceCodeElement(GetImport(), m_xLib, m_aName); + } + } + else + { + throw xml::sax::SAXException("expected source-code element!", Reference<XInterface>(), + Any()); + } + + return nullptr; +} + +// BasicSourceCodeElement + +BasicSourceCodeElement::BasicSourceCodeElement(SvXMLImport& rImport, + const Reference<container::XNameContainer>& rxLib, + OUString rName) + : BasicElementBase(rImport) + , m_xLib(rxLib) + , m_aName(std::move(rName)) +{ +} + +// XElement + +void BasicSourceCodeElement::characters(const OUString& rChars) { m_aBuffer.append(rChars); } + +void BasicSourceCodeElement::endFastElement(sal_Int32) +{ + try + { + if (m_xLib.is() && !m_aName.isEmpty()) + { + Any aElement; + aElement <<= m_aBuffer.makeStringAndClear(); + m_xLib->insertByName(m_aName, aElement); + } + } + catch (const container::ElementExistException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", "BasicSourceCodeElement::endElement"); + } + catch (const lang::IllegalArgumentException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", "BasicSourceCodeElement::endElement"); + } + catch (const lang::WrappedTargetException&) + { + TOOLS_INFO_EXCEPTION("xmlscript.xmlflat", "BasicSourceCodeElement::endElement"); + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/script/xmlbasicscript.hxx b/xmloff/source/script/xmlbasicscript.hxx new file mode 100644 index 0000000000..04dd31211c --- /dev/null +++ b/xmloff/source/script/xmlbasicscript.hxx @@ -0,0 +1,111 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/script/XLibraryContainer2.hpp> +#include <cppuhelper/implbase.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ref.hxx> +#include <xmloff/xmlimp.hxx> + +namespace xmloff +{ +class BasicElementBase : public SvXMLImportContext +{ +protected: + static bool + getBoolAttr(bool* pRet, sal_Int32 nToken, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttributes); + +public: + BasicElementBase(SvXMLImport& rImport); +}; + +class BasicLibrariesElement : public BasicElementBase +{ +private: + css::uno::Reference<css::script::XLibraryContainer2> m_xLibContainer; + +public: + BasicLibrariesElement(SvXMLImport& rImport, + const css::uno::Reference<css::frame::XModel>& rxModel); + + virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 Element, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& Attribs) override; +}; + +class BasicEmbeddedLibraryElement : public BasicElementBase +{ +private: + css::uno::Reference<css::script::XLibraryContainer2> m_xLibContainer; + css::uno::Reference<css::container::XNameContainer> m_xLib; + OUString const m_aLibName; + bool const m_bReadOnly; + +public: + BasicEmbeddedLibraryElement( + SvXMLImport& rImport, + const css::uno::Reference<css::script::XLibraryContainer2>& rxLibContainer, + OUString aLibName, bool bReadOnly); + + virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 Element, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& Attribs) override; + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +class BasicModuleElement : public BasicElementBase +{ +private: + css::uno::Reference<css::container::XNameContainer> m_xLib; + OUString const m_aName; + +public: + BasicModuleElement(SvXMLImport& rImport, + const css::uno::Reference<css::container::XNameContainer>& rxLib, + OUString aName); + + virtual css::uno::Reference<XFastContextHandler> SAL_CALL createFastChildContext( + sal_Int32 Element, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& Attribs) override; +}; + +class BasicSourceCodeElement : public BasicElementBase +{ +private: + css::uno::Reference<css::container::XNameContainer> m_xLib; + OUString const m_aName; + OUStringBuffer m_aBuffer; + +public: + BasicSourceCodeElement(SvXMLImport& rImport, + const css::uno::Reference<css::container::XNameContainer>& rxLib, + OUString rName); + + virtual void SAL_CALL characters(const OUString& rChars) override; + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; +}; + +} // namespace xmloff + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file diff --git a/xmloff/source/script/xmlscripti.cxx b/xmloff/source/script/xmlscripti.cxx new file mode 100644 index 0000000000..7da3607efa --- /dev/null +++ b/xmloff/source/script/xmlscripti.cxx @@ -0,0 +1,130 @@ +/* -*- 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 <utility> +#include <xmloff/xmlscripti.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/XMLEventsImportContext.hxx> +#include "xmlbasicscript.hxx" + +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <com/sun/star/document/XEmbeddedScripts.hpp> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::frame; +using namespace com::sun::star::document; +using namespace com::sun::star::xml::sax; +using namespace ::xmloff::token; + +// XMLScriptChildContext: context for <office:script> element + +namespace { + +class XMLScriptChildContext : public SvXMLImportContext +{ +private: + css::uno::Reference< css::frame::XModel > m_xModel; + css::uno::Reference< css::document::XEmbeddedScripts > m_xDocumentScripts; + OUString m_aLanguage; + +public: + XMLScriptChildContext( SvXMLImport& rImport, + const css::uno::Reference< css::frame::XModel>& rxModel, + OUString aLanguage ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; +}; + +} + +XMLScriptChildContext::XMLScriptChildContext( SvXMLImport& rImport, + const Reference< frame::XModel >& rxModel, OUString aLanguage ) + :SvXMLImportContext( rImport ) + ,m_xModel( rxModel ) + ,m_xDocumentScripts( rxModel, UNO_QUERY ) + ,m_aLanguage(std::move( aLanguage )) +{ +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLScriptChildContext::createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ ) +{ + if ( m_xDocumentScripts.is() ) + { // document supports embedding scripts/macros + OUString aBasic( GetImport().GetNamespaceMap().GetPrefixByKey( XML_NAMESPACE_OOO ) + ":Basic" ); + + if ( m_aLanguage == aBasic && nElement == XML_ELEMENT(OOO, XML_LIBRARIES) ) + { + return new xmloff::BasicLibrariesElement( GetImport(), m_xModel ); + } + } + + return nullptr; +} + +// XMLScriptContext: context for <office:scripts> element + +XMLScriptContext::XMLScriptContext( SvXMLImport& rImport, + const Reference<XModel>& rDocModel ) + :SvXMLImportContext( rImport ) + ,m_xModel( rDocModel ) +{ +} + +XMLScriptContext::~XMLScriptContext() +{ +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLScriptContext::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + if ( nElement == XML_ELEMENT(OFFICE, XML_SCRIPT) ) + { + if ( m_xModel.is() ) + { + OUString aLanguage = xAttrList->getValue( XML_ELEMENT(SCRIPT, XML_LANGUAGE) ); + + uno::Sequence< beans::PropertyValue > aMedDescr = m_xModel->getArgs(); + sal_Int32 nNewLen = aMedDescr.getLength() + 1; + aMedDescr.realloc( nNewLen ); + auto pMedDescr = aMedDescr.getArray(); + pMedDescr[nNewLen-1].Name = "BreakMacroSignature"; + pMedDescr[nNewLen-1].Value <<= true; + m_xModel->attachResource( m_xModel->getURL(), aMedDescr ); + + return new XMLScriptChildContext( GetImport(), m_xModel, aLanguage ); + } + } + else if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) ) + { + Reference< XEventsSupplier> xSupplier( GetImport().GetModel(), UNO_QUERY ); + return new XMLEventsImportContext( GetImport(), xSupplier ); + } + + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |