/* -*- 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 #include #include #include #include #include #include #include "swhtml.hxx" #include "wrthtml.hxx" #include "htmlfly.hxx" #include "swcss1.hxx" #include "htmlreqifreader.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; #define HTML_DFLT_EMBED_WIDTH ((MM50*5)/2) #define HTML_DFLT_EMBED_HEIGHT ((MM50*5)/2) #define HTML_DFLT_APPLET_WIDTH ((MM50*5)/2) #define HTML_DFLT_APPLET_HEIGHT ((MM50*5)/2) const HtmlFrmOpts HTML_FRMOPTS_EMBED_ALL = HtmlFrmOpts::Alt | HtmlFrmOpts::Size | HtmlFrmOpts::Name; const HtmlFrmOpts HTML_FRMOPTS_EMBED_CNTNR = HTML_FRMOPTS_EMBED_ALL | HtmlFrmOpts::AbsSize; const HtmlFrmOpts HTML_FRMOPTS_EMBED = HTML_FRMOPTS_EMBED_ALL | HtmlFrmOpts::Align | HtmlFrmOpts::Space | HtmlFrmOpts::BrClear | HtmlFrmOpts::Name; const HtmlFrmOpts HTML_FRMOPTS_HIDDEN_EMBED = HtmlFrmOpts::Alt | HtmlFrmOpts::Name; const HtmlFrmOpts HTML_FRMOPTS_APPLET_ALL = HtmlFrmOpts::Alt | HtmlFrmOpts::Size; const HtmlFrmOpts HTML_FRMOPTS_APPLET_CNTNR = HTML_FRMOPTS_APPLET_ALL | HtmlFrmOpts::AbsSize; const HtmlFrmOpts HTML_FRMOPTS_APPLET = HTML_FRMOPTS_APPLET_ALL | HtmlFrmOpts::Align | HtmlFrmOpts::Space | HtmlFrmOpts::BrClear; const HtmlFrmOpts HTML_FRMOPTS_IFRAME_ALL = HtmlFrmOpts::Alt | HtmlFrmOpts::Size; const HtmlFrmOpts HTML_FRMOPTS_IFRAME_CNTNR = HTML_FRMOPTS_IFRAME_ALL | HtmlFrmOpts::AbsSize; const HtmlFrmOpts HTML_FRMOPTS_IFRAME = HTML_FRMOPTS_IFRAME_ALL | HtmlFrmOpts::Align | HtmlFrmOpts::Space | HtmlFrmOpts::Border | HtmlFrmOpts::BrClear; const HtmlFrmOpts HTML_FRMOPTS_OLE_CSS1 = HtmlFrmOpts::SAlign | HtmlFrmOpts::SSpace; namespace { /** * Calculates a filename for an image, provided the HTML file name, the image * itself and a wanted extension. */ OUString lcl_CalculateFileName(const OUString* pOrigFileName, const Graphic& rGraphic, std::u16string_view rExtension) { OUString aFileName; if (pOrigFileName) aFileName = *pOrigFileName; INetURLObject aURL(aFileName); OUString aName = aURL.getBase() + "_" + aURL.getExtension() + "_" + OUString::number(rGraphic.GetChecksum(), 16); aURL.setBase(aName); aURL.setExtension(rExtension); aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); return aFileName; } } void SwHTMLParser::SetFixSize( const Size& rPixSize, const Size& rTwipDfltSize, bool bPercentWidth, bool bPercentHeight, SvxCSS1PropertyInfo const & rCSS1PropInfo, SfxItemSet& rFlyItemSet ) { // convert absolute size values into Twip sal_uInt8 nPercentWidth = 0, nPercentHeight = 0; Size aTwipSz( bPercentWidth || USHRT_MAX==rPixSize.Width() ? 0 : rPixSize.Width(), bPercentHeight || USHRT_MAX==rPixSize.Height() ? 0 : rPixSize.Height() ); if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() ) { aTwipSz = Application::GetDefaultDevice()->PixelToLogic( aTwipSz, MapMode(MapUnit::MapTwip) ); } // process width if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eWidthType ) { nPercentWidth = static_cast(rCSS1PropInfo.m_nWidth); aTwipSz.setWidth( rTwipDfltSize.Width() ); } else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eWidthType ) { aTwipSz.setWidth( rCSS1PropInfo.m_nWidth ); } else if( bPercentWidth && rPixSize.Width() ) { nPercentWidth = static_cast(rPixSize.Width()); if( nPercentWidth > 100 ) nPercentWidth = 100; aTwipSz.setWidth( rTwipDfltSize.Width() ); } else if( USHRT_MAX==rPixSize.Width() ) { aTwipSz.setWidth( rTwipDfltSize.Width() ); } if( aTwipSz.Width() < MINFLY ) { aTwipSz.setWidth( MINFLY ); } // process height if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eHeightType ) { nPercentHeight = static_cast(rCSS1PropInfo.m_nHeight); aTwipSz.setHeight( rTwipDfltSize.Height() ); } else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eHeightType ) { aTwipSz.setHeight( rCSS1PropInfo.m_nHeight ); } else if( bPercentHeight && rPixSize.Height() ) { nPercentHeight = static_cast(rPixSize.Height()); if( nPercentHeight > 100 ) nPercentHeight = 100; aTwipSz.setHeight( rTwipDfltSize.Height() ); } else if( USHRT_MAX==rPixSize.Height() ) { aTwipSz.setHeight( rTwipDfltSize.Height() ); } if( aTwipSz.Height() < MINFLY ) { aTwipSz.setHeight( MINFLY ); } // set size SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, aTwipSz.Width(), aTwipSz.Height() ); aFrameSize.SetWidthPercent( nPercentWidth ); aFrameSize.SetHeightPercent( nPercentHeight ); rFlyItemSet.Put( aFrameSize ); } void SwHTMLParser::SetSpace( const Size& rPixSpace, SfxItemSet& rCSS1ItemSet, SvxCSS1PropertyInfo& rCSS1PropInfo, SfxItemSet& rFlyItemSet ) { sal_Int32 nLeftSpace = 0, nRightSpace = 0; sal_uInt16 nUpperSpace = 0, nLowerSpace = 0; if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() ) { Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() ); aTwipSpc = Application::GetDefaultDevice()->PixelToLogic( aTwipSpc, MapMode(MapUnit::MapTwip) ); nLeftSpace = nRightSpace = aTwipSpc.Width(); nUpperSpace = nLowerSpace = o3tl::narrowing(aTwipSpc.Height()); } // set left/right margin const SfxPoolItem *pItem; if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, &pItem ) ) { // if applicable remove the first line indent const SvxLRSpaceItem *pLRItem = static_cast(pItem); SvxLRSpaceItem aLRItem( *pLRItem ); aLRItem.SetTextFirstLineOffset( 0 ); if( rCSS1PropInfo.m_bLeftMargin ) { nLeftSpace = aLRItem.GetLeft(); rCSS1PropInfo.m_bLeftMargin = false; } if( rCSS1PropInfo.m_bRightMargin ) { nRightSpace = aLRItem.GetRight(); rCSS1PropInfo.m_bRightMargin = false; } rCSS1ItemSet.ClearItem( RES_LR_SPACE ); } if( nLeftSpace > 0 || nRightSpace > 0 ) { SvxLRSpaceItem aLRItem( RES_LR_SPACE ); aLRItem.SetLeft( std::max(nLeftSpace, 0) ); aLRItem.SetRight( std::max(nRightSpace, 0) ); rFlyItemSet.Put( aLRItem ); if( nLeftSpace ) { const SwFormatHoriOrient& rHoriOri = rFlyItemSet.Get( RES_HORI_ORIENT ); if( text::HoriOrientation::NONE == rHoriOri.GetHoriOrient() ) { SwFormatHoriOrient aHoriOri( rHoriOri ); aHoriOri.SetPos( aHoriOri.GetPos() + nLeftSpace ); rFlyItemSet.Put( aHoriOri ); } } } // set top/bottom margin if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, &pItem ) ) { // if applicable remove the first line indent const SvxULSpaceItem *pULItem = static_cast(pItem); if( rCSS1PropInfo.m_bTopMargin ) { nUpperSpace = pULItem->GetUpper(); rCSS1PropInfo.m_bTopMargin = false; } if( rCSS1PropInfo.m_bBottomMargin ) { nLowerSpace = pULItem->GetLower(); rCSS1PropInfo.m_bBottomMargin = false; } rCSS1ItemSet.ClearItem( RES_UL_SPACE ); } if( !(nUpperSpace || nLowerSpace) ) return; SvxULSpaceItem aULItem( RES_UL_SPACE ); aULItem.SetUpper( nUpperSpace ); aULItem.SetLower( nLowerSpace ); rFlyItemSet.Put( aULItem ); if( nUpperSpace ) { const SwFormatVertOrient& rVertOri = rFlyItemSet.Get( RES_VERT_ORIENT ); if( text::VertOrientation::NONE == rVertOri.GetVertOrient() ) { SwFormatVertOrient aVertOri( rVertOri ); aVertOri.SetPos( aVertOri.GetPos() + nUpperSpace ); rFlyItemSet.Put( aVertOri ); } } } OUString SwHTMLParser::StripQueryFromPath(const OUString& rBase, const OUString& rPath) { if (!comphelper::isFileUrl(rBase)) return rPath; sal_Int32 nIndex = rPath.indexOf('?'); if (nIndex != -1) return rPath.copy(0, nIndex); return rPath; } bool SwHTMLParser::InsertEmbed() { OUString aURL, aType, aName, aAlt, aId, aStyle, aClass; OUString aData; Size aSize( USHRT_MAX, USHRT_MAX ); Size aSpace( USHRT_MAX, USHRT_MAX ); bool bPercentWidth = false, bPercentHeight = false, bHidden = false; sal_Int16 eVertOri = text::VertOrientation::NONE; sal_Int16 eHoriOri = text::HoriOrientation::NONE; SvCommandList aCmdLst; const HTMLOptions& rHTMLOptions = GetOptions(); // The options are read forwards, because the plug-ins expect them in this // order. Still only the first value of an option may be regarded. for (const auto & rOption : rHTMLOptions) { switch( rOption.GetToken() ) { case HtmlOptionId::ID: aId = rOption.GetString(); break; case HtmlOptionId::STYLE: aStyle = rOption.GetString(); break; case HtmlOptionId::CLASS: aClass = rOption.GetString(); break; case HtmlOptionId::NAME: aName = rOption.GetString(); break; case HtmlOptionId::SRC: if( aURL.isEmpty() ) aURL = rOption.GetString(); break; case HtmlOptionId::ALT: aAlt = rOption.GetString(); break; case HtmlOptionId::TYPE: if( aType.isEmpty() ) aType = rOption.GetString(); break; case HtmlOptionId::ALIGN: if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE ) { eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri ); eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri ); } break; case HtmlOptionId::WIDTH: if( USHRT_MAX==aSize.Width() ) { bPercentWidth = (rOption.GetString().indexOf('%') != -1); aSize.setWidth( static_cast(rOption.GetNumber()) ); } break; case HtmlOptionId::HEIGHT: if( USHRT_MAX==aSize.Height() ) { bPercentHeight = (rOption.GetString().indexOf('%') != -1); aSize.setHeight( static_cast(rOption.GetNumber()) ); } break; case HtmlOptionId::HSPACE: if( USHRT_MAX==aSpace.Width() ) aSpace.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::VSPACE: if( USHRT_MAX==aSpace.Height() ) aSpace.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::DATA: if (m_bXHTML && aURL.isEmpty()) aData = rOption.GetString(); break; case HtmlOptionId::UNKNOWN: if (rOption.GetTokenString().equalsIgnoreAsciiCase( OOO_STRING_SW_HTML_O_Hidden)) { bHidden = !rOption.GetString().equalsIgnoreAsciiCase( "FALSE"); } break; default: break; } // All parameters are passed to the plug-in. aCmdLst.Append( rOption.GetTokenString(), rOption.GetString() ); } if (aType == "image/png" && m_aEmbeds.empty()) // Toplevel for PNG -> that's an image, not an OLE object. return false; SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); SvxCSS1PropertyInfo aPropInfo; if( HasStyleOptions( aStyle, aId, aClass ) ) ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); // Convert the default values (except height/width, which is done by SetFrameSize()) if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE ) eVertOri = text::VertOrientation::TOP; if( USHRT_MAX==aSpace.Width() ) aSpace.setWidth( 0 ); if( USHRT_MAX==aSpace.Height() ) aSpace.setHeight( 0 ); if( bHidden ) { // Size (0,0) will be changed to (MINFLY, MINFLY) in SetFrameSize() aSize.setWidth( 0 ); aSize.setHeight( 0 ); aSpace.setWidth( 0 ); aSpace.setHeight( 0 ); bPercentWidth = bPercentHeight = false; } // prepare the URL INetURLObject aURLObj; bool bHasURL = !aURL.isEmpty() && aURLObj.SetURL( URIHelper::SmartRel2Abs( INetURLObject(m_sBaseURL), aURL, URIHelper::GetMaybeFileHdl()) ); bool bHasData = !aData.isEmpty(); try { // Strip query and everything after that for file:// URLs, browsers do // the same. aURLObj.SetURL(rtl::Uri::convertRelToAbs( m_sBaseURL, SwHTMLParser::StripQueryFromPath(m_sBaseURL, aData))); } catch (const rtl::MalformedUriException& /*rException*/) { bHasData = false; } // do not insert plugin if it has neither URL nor type bool bHasType = !aType.isEmpty(); if( !bHasURL && !bHasType && !bHasData ) return true; if (!m_aEmbeds.empty()) { // Nested XHTML element: points to replacement graphic. SwOLENode* pOLENode = m_aEmbeds.top(); svt::EmbeddedObjectRef& rObj = pOLENode->GetOLEObj().GetObject(); Graphic aGraphic; if (GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aURLObj) != ERRCODE_NONE) return true; rObj.SetGraphic(aGraphic, aType); // Set the size of the OLE frame to the size of the graphic. OutputDevice* pDevice = Application::GetDefaultDevice(); if (aSize.getHeight() == USHRT_MAX || aSize.getWidth() == USHRT_MAX) { Size aPixelSize = aGraphic.GetSizePixel(pDevice); if (aSize.getWidth() == USHRT_MAX) aSize.setWidth(aPixelSize.getWidth()); if (aSize.getHeight() == USHRT_MAX) aSize.setHeight(aPixelSize.getHeight()); } SwFrameFormat* pFormat = pOLENode->GetFlyFormat(); if (!pFormat) return true; SwAttrSet aAttrSet(pFormat->GetAttrSet()); aAttrSet.ClearItem(RES_CNTNT); Size aTwipSize(pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapTwip))); SwFormatFrameSize aFrameSize(SwFrameSize::Fixed, aTwipSize.Width(), aTwipSize.Height()); aAttrSet.Put(aFrameSize); pOLENode->GetDoc().SetFlyFrameAttr(*pFormat, aAttrSet); return true; } // create the plug-in comphelper::EmbeddedObjectContainer aCnt; OUString aObjName; uno::Reference < embed::XEmbeddedObject > xObj; if (!bHasData) { xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence(), aObjName ); if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) { uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); if ( xSet.is() ) { if( bHasURL ) xSet->setPropertyValue("PluginURL", uno::makeAny( aURL ) ); if( bHasType ) xSet->setPropertyValue("PluginMimeType", uno::makeAny( aType ) ); uno::Sequence < beans::PropertyValue > aProps; aCmdLst.FillSequence( aProps ); xSet->setPropertyValue("PluginCommands", uno::makeAny( aProps ) ); } } } else if (SwDocShell* pDocSh = m_xDoc->GetDocShell()) { // Has non-empty data attribute in XHTML: map that to an OLE object. uno::Reference xStorage = pDocSh->GetStorage(); aCnt.SwitchPersistence(xStorage); aObjName = aCnt.CreateUniqueObjectName(); { SvFileStream aFileStream(aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ); uno::Reference xInStream; SvMemoryStream aMemoryStream; // Allow any MIME type that starts with magic, unless a set of allowed types are // specified. auto it = m_aAllowedRTFOLEMimeTypes.find(aType); if (m_aAllowedRTFOLEMimeTypes.empty() || it != m_aAllowedRTFOLEMimeTypes.end()) { OString aMagic("{\\object"); OString aHeader(read_uInt8s_ToOString(aFileStream, aMagic.getLength())); aFileStream.Seek(0); if (aHeader == aMagic) { // OLE2 wrapped in RTF: either own format or real OLE2 embedding. bool bOwnFormat = false; if (SwReqIfReader::ExtractOleFromRtf(aFileStream, aMemoryStream, bOwnFormat)) { xInStream.set(new utl::OStreamWrapper(aMemoryStream)); } if (bOwnFormat) { uno::Sequence aMedium = comphelper::InitPropertySequence( { { "InputStream", uno::makeAny(xInStream) }, { "URL", uno::makeAny(OUString("private:stream")) }, { "DocumentBaseURL", uno::makeAny(m_sBaseURL) } }); xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &m_sBaseURL); } else { // The type is now an OLE2 container, not the original XHTML type. aType = "application/vnd.sun.star.oleobject"; } } } if (!xInStream.is()) // Non-RTF case. xInStream.set(new utl::OStreamWrapper(aFileStream)); if (!xObj.is()) { uno::Reference xOutStream = xStorage->openStreamElement(aObjName, embed::ElementModes::READWRITE); if (aFileStream.IsOpen()) comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream->getOutputStream()); if (!aType.isEmpty()) { // Set media type of the native data. uno::Reference xOutStreamProps(xOutStream, uno::UNO_QUERY); if (xOutStreamProps.is()) xOutStreamProps->setPropertyValue("MediaType", uno::makeAny(aType)); } } xObj = aCnt.GetEmbeddedObject(aObjName); } } SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), svl::Items{} ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); // set the anchor if( !bHidden ) { SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet ); } else { SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA ); aAnchor.SetAnchor( m_pPam->GetPoint() ); aFrameSet.Put( aAnchor ); aFrameSet.Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME) ); aFrameSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) ); aFrameSet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) ); } // and the size of the frame Size aDfltSz( HTML_DFLT_EMBED_WIDTH, HTML_DFLT_EMBED_HEIGHT ); SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet ); SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet ); // and insert into the document uno::Reference xObjInitialization(xObj, uno::UNO_QUERY); if (xObjInitialization.is()) { // Request that the native data of the embedded object is not modified // during parsing. uno::Sequence aValues{ comphelper::makePropertyValue("StreamReadOnly", true) }; uno::Sequence aArguments{ uno::makeAny(aValues) }; xObjInitialization->initialize(aArguments); } SwFrameFormat* pFlyFormat = m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam, ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT), &aFrameSet); if (xObjInitialization.is()) { uno::Sequence aValues{ comphelper::makePropertyValue("StreamReadOnly", false) }; uno::Sequence aArguments{ uno::makeAny(aValues) }; xObjInitialization->initialize(aArguments); } // set name at FrameFormat if( !aName.isEmpty() ) pFlyFormat->SetName( aName ); // set the alternative text SwNoTextNode *pNoTextNd = m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx() ->GetIndex()+1 ]->GetNoTextNode(); pNoTextNd->SetTitle( aAlt ); // if applicable create frames and register auto-bound frames if( !bHidden ) { // HIDDEN plug-ins should stay paragraph-bound. Since RegisterFlyFrame() // will change paragraph-bound frames with wrap-through into a // character-bound frame, here we must create the frames by hand. RegisterFlyFrame( pFlyFormat ); } if (!bHasData) return true; SwOLENode* pOLENode = pNoTextNd->GetOLENode(); if (!pOLENode) return true; m_aEmbeds.push(pOLENode); return true; } #if HAVE_FEATURE_JAVA void SwHTMLParser::NewObject() { OUString aClassID; OUString aStandBy, aId, aStyle, aClass; Size aSize( USHRT_MAX, USHRT_MAX ); Size aSpace( 0, 0 ); sal_Int16 eVertOri = text::VertOrientation::TOP; sal_Int16 eHoriOri = text::HoriOrientation::NONE; bool bPercentWidth = false, bPercentHeight = false, bDeclare = false; // create a new Command list m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() )); const HTMLOptions& rHTMLOptions = GetOptions(); for (size_t i = rHTMLOptions.size(); i; ) { const HTMLOption& rOption = rHTMLOptions[--i]; switch( rOption.GetToken() ) { case HtmlOptionId::ID: aId = rOption.GetString(); break; case HtmlOptionId::STYLE: aStyle = rOption.GetString(); break; case HtmlOptionId::CLASS: aClass = rOption.GetString(); break; case HtmlOptionId::DECLARE: bDeclare = true; break; case HtmlOptionId::CLASSID: aClassID = rOption.GetString(); break; case HtmlOptionId::CODEBASE: break; case HtmlOptionId::DATA: break; case HtmlOptionId::TYPE: break; case HtmlOptionId::CODETYPE: break; case HtmlOptionId::ARCHIVE: case HtmlOptionId::UNKNOWN: break; case HtmlOptionId::STANDBY: aStandBy = rOption.GetString(); break; case HtmlOptionId::WIDTH: bPercentWidth = (rOption.GetString().indexOf('%') != -1); aSize.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::HEIGHT: bPercentHeight = (rOption.GetString().indexOf('%') != -1); aSize.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::ALIGN: eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri ); eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri ); break; case HtmlOptionId::USEMAP: break; case HtmlOptionId::NAME: break; case HtmlOptionId::HSPACE: aSpace.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::VSPACE: aSpace.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::BORDER: break; case HtmlOptionId::SDONCLICK: case HtmlOptionId::ONCLICK: case HtmlOptionId::SDONMOUSEOVER: case HtmlOptionId::ONMOUSEOVER: case HtmlOptionId::SDONMOUSEOUT: case HtmlOptionId::ONMOUSEOUT: break; default: break; } // All parameters are passed to the applet. m_pAppletImpl->AppendParam( rOption.GetTokenString(), rOption.GetString() ); } // Objects that are declared only are not evaluated. Moreover, only // Java applets are supported. bool bIsApplet = false; if( !bDeclare && aClassID.getLength() == 42 && aClassID.startsWith("clsid:") ) { aClassID = aClassID.copy(6); SvGlobalName aCID; if( aCID.MakeId( aClassID ) ) { SvGlobalName aJavaCID( 0x8AD9C840UL, 0x044EU, 0x11D1U, 0xB3U, 0xE9U, 0x00U, 0x80U, 0x5FU, 0x49U, 0x9DU, 0x93U ); bIsApplet = aJavaCID == aCID; } } if( !bIsApplet ) { m_pAppletImpl.reset(); return; } m_pAppletImpl->SetAltText( aStandBy ); SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); SvxCSS1PropertyInfo aPropInfo; if( HasStyleOptions( aStyle, aId, aClass ) ) ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet(); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( rFrameSet ); // set the anchor and the adjustment SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet ); // and still the size of the frame Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT ); SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet ); SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet ); } #endif void SwHTMLParser::EndObject() { #if HAVE_FEATURE_JAVA if( !m_pAppletImpl ) return; if( !m_pAppletImpl->CreateApplet( m_sBaseURL ) ) return; m_pAppletImpl->FinishApplet(); // and insert into the document SwFrameFormat* pFlyFormat = m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam, ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ), &m_pAppletImpl->GetItemSet() ); // set the alternative name SwNoTextNode *pNoTextNd = m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx() ->GetIndex()+1 ]->GetNoTextNode(); pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() ); // if applicable create frames and register auto-bound frames RegisterFlyFrame( pFlyFormat ); m_pAppletImpl.reset(); #else (void) this; // Silence loplugin:staticmethods #endif } #if HAVE_FEATURE_JAVA void SwHTMLParser::InsertApplet() { OUString aCodeBase, aCode, aName, aAlt, aId, aStyle, aClass; Size aSize( USHRT_MAX, USHRT_MAX ); Size aSpace( 0, 0 ); bool bPercentWidth = false, bPercentHeight = false, bMayScript = false; sal_Int16 eVertOri = text::VertOrientation::TOP; sal_Int16 eHoriOri = text::HoriOrientation::NONE; // create a new Command list m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() )); const HTMLOptions& rHTMLOptions = GetOptions(); for (size_t i = rHTMLOptions.size(); i; ) { const HTMLOption& rOption = rHTMLOptions[--i]; switch( rOption.GetToken() ) { case HtmlOptionId::ID: aId = rOption.GetString(); break; case HtmlOptionId::STYLE: aStyle = rOption.GetString(); break; case HtmlOptionId::CLASS: aClass = rOption.GetString(); break; case HtmlOptionId::CODEBASE: aCodeBase = rOption.GetString(); break; case HtmlOptionId::CODE: aCode = rOption.GetString(); break; case HtmlOptionId::NAME: aName = rOption.GetString(); break; case HtmlOptionId::ALT: aAlt = rOption.GetString(); break; case HtmlOptionId::ALIGN: eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri ); eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri ); break; case HtmlOptionId::WIDTH: bPercentWidth = (rOption.GetString().indexOf('%') != -1); aSize.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::HEIGHT: bPercentHeight = (rOption.GetString().indexOf('%') != -1); aSize.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::HSPACE: aSpace.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::VSPACE: aSpace.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::MAYSCRIPT: bMayScript = true; break; default: break; } // All parameters are passed to the applet. m_pAppletImpl->AppendParam( rOption.GetTokenString(), rOption.GetString() ); } if( aCode.isEmpty() ) { m_pAppletImpl.reset(); return; } if ( !aCodeBase.isEmpty() ) aCodeBase = INetURLObject::GetAbsURL( m_sBaseURL, aCodeBase ); m_pAppletImpl->CreateApplet( aCode, aName, bMayScript, aCodeBase, m_sBaseURL );//, aAlt ); m_pAppletImpl->SetAltText( aAlt ); SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); SvxCSS1PropertyInfo aPropInfo; if( HasStyleOptions( aStyle, aId, aClass ) ) ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet(); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( rFrameSet ); // set the anchor and the adjustment SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet ); // and still the size or the frame Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT ); SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet ); SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet ); } #endif void SwHTMLParser::EndApplet() { #if HAVE_FEATURE_JAVA if( !m_pAppletImpl ) return; m_pAppletImpl->FinishApplet(); // and insert into the document SwFrameFormat* pFlyFormat = m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam, ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ), &m_pAppletImpl->GetItemSet()); // set the alternative name SwNoTextNode *pNoTextNd = m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx() ->GetIndex()+1 ]->GetNoTextNode(); pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() ); // if applicable create frames and register auto-bound frames RegisterFlyFrame( pFlyFormat ); m_pAppletImpl.reset(); #else (void) this; #endif } void SwHTMLParser::InsertParam() { #if HAVE_FEATURE_JAVA if( !m_pAppletImpl ) return; OUString aName, aValue; const HTMLOptions& rHTMLOptions = GetOptions(); for (size_t i = rHTMLOptions.size(); i; ) { const HTMLOption& rOption = rHTMLOptions[--i]; switch( rOption.GetToken() ) { case HtmlOptionId::NAME: aName = rOption.GetString(); break; case HtmlOptionId::VALUE: aValue = rOption.GetString(); break; default: break; } } if( aName.isEmpty() ) return; m_pAppletImpl->AppendParam( aName, aValue ); #else (void) this; #endif } void SwHTMLParser::InsertFloatingFrame() { OUString aAlt, aId, aStyle, aClass; Size aSize( USHRT_MAX, USHRT_MAX ); Size aSpace( 0, 0 ); bool bPercentWidth = false, bPercentHeight = false; sal_Int16 eVertOri = text::VertOrientation::TOP; sal_Int16 eHoriOri = text::HoriOrientation::NONE; const HTMLOptions& rHTMLOptions = GetOptions(); // First fetch the options of the Writer-Frame-Format for (const auto & rOption : rHTMLOptions) { switch( rOption.GetToken() ) { case HtmlOptionId::ID: aId = rOption.GetString(); break; case HtmlOptionId::STYLE: aStyle = rOption.GetString(); break; case HtmlOptionId::CLASS: aClass = rOption.GetString(); break; case HtmlOptionId::ALT: aAlt = rOption.GetString(); break; case HtmlOptionId::ALIGN: eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri ); eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri ); break; case HtmlOptionId::WIDTH: bPercentWidth = (rOption.GetString().indexOf('%') != -1); aSize.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::HEIGHT: bPercentHeight = (rOption.GetString().indexOf('%') != -1); aSize.setHeight( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::HSPACE: aSpace.setWidth( static_cast(rOption.GetNumber()) ); break; case HtmlOptionId::VSPACE: aSpace.setHeight( static_cast(rOption.GetNumber()) ); break; default: break; } } // and now the ones for the SfxFrame SfxFrameDescriptor aFrameDesc; SfxFrameHTMLParser::ParseFrameOptions( &aFrameDesc, rHTMLOptions, m_sBaseURL ); // create a floating frame comphelper::EmbeddedObjectContainer aCnt; OUString aObjName; uno::Reference < embed::XEmbeddedObject > xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence(), aObjName ); try { // TODO/MBA: testing if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) ) { uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); if ( xSet.is() ) { const OUString& aName = aFrameDesc.GetName(); ScrollingMode eScroll = aFrameDesc.GetScrollingMode(); bool bHasBorder = aFrameDesc.HasFrameBorder(); Size aMargin = aFrameDesc.GetMargin(); xSet->setPropertyValue("FrameURL", uno::makeAny( aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); xSet->setPropertyValue("FrameName", uno::makeAny( aName ) ); if ( eScroll == ScrollingMode::Auto ) xSet->setPropertyValue("FrameIsAutoScroll", uno::makeAny( true ) ); else xSet->setPropertyValue("FrameIsScrollingMode", uno::makeAny( eScroll == ScrollingMode::Yes ) ); xSet->setPropertyValue("FrameIsBorder", uno::makeAny( bHasBorder ) ); xSet->setPropertyValue("FrameMarginWidth", uno::makeAny( sal_Int32( aMargin.Width() ) ) ); xSet->setPropertyValue("FrameMarginHeight", uno::makeAny( sal_Int32( aMargin.Height() ) ) ); } } } catch ( uno::Exception& ) { } SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); SvxCSS1PropertyInfo aPropInfo; if( HasStyleOptions( aStyle, aId, aClass ) ) ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); // fetch the ItemSet SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), svl::Items{} ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); // set the anchor and the adjustment SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet ); // and still the size of the frame Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT ); SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet ); SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet ); // and insert into the document SwFrameFormat* pFlyFormat = m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam, ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT), &aFrameSet); // set the alternative name SwNoTextNode *pNoTextNd = m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx() ->GetIndex()+1 ]->GetNoTextNode(); pNoTextNd->SetTitle( aAlt ); // if applicable create frames and register auto-bound frames RegisterFlyFrame( pFlyFormat ); m_bInFloatingFrame = true; } sal_uInt16 SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode ) { SwOLEObj& rObj = const_cast(rNode.GetOLENode())->GetOLEObj(); SwHTMLFrameType eType = HTML_FRMTYPE_OLE; uno::Reference < embed::XClassifiedObject > xClass = rObj.GetOleRef(); SvGlobalName aClass( xClass->getClassID() ); if( aClass == SvGlobalName( SO3_PLUGIN_CLASSID ) ) { eType = HTML_FRMTYPE_PLUGIN; } else if( aClass == SvGlobalName( SO3_IFRAME_CLASSID ) ) { eType = HTML_FRMTYPE_IFRAME; } #if HAVE_FEATURE_JAVA else if( aClass == SvGlobalName( SO3_APPLET_CLASSID ) ) { eType = HTML_FRMTYPE_APPLET; } #endif return static_cast< sal_uInt16 >(eType); } Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFormat, bool bInCntnr ) { SwHTMLWriter& rHTMLWrt = static_cast(rWrt); const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); OSL_ENSURE( pOLENd, "OLE-Node expected" ); if( !pOLENd ) return rWrt; SwOLEObj &rObj = pOLENd->GetOLEObj(); uno::Reference < embed::XEmbeddedObject > xObj( rObj.GetOleRef() ); if ( !svt::EmbeddedObjectRef::TryRunningState( xObj ) ) return rWrt; uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY ); bool bHiddenEmbed = false; if( !xSet.is() ) { OSL_FAIL("Unknown Object" ); return rWrt; } HtmlFrmOpts nFrameOpts; // if possible output a line break before the "object" if( rHTMLWrt.m_bLFPossible ) rHTMLWrt.OutNewLine( true ); if( !rFrameFormat.GetName().isEmpty() ) rHTMLWrt.OutImplicitMark( rFrameFormat.GetName(), "ole" ); uno::Any aAny; SvGlobalName aGlobName( xObj->getClassID() ); OStringBuffer sOut; sOut.append('<'); if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) ) { // first the plug-in specifics sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed); OUString aStr; OUString aURL; aAny = xSet->getPropertyValue("PluginURL"); if( (aAny >>= aStr) && !aStr.isEmpty() ) { aURL = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), aStr); } if( !aURL.isEmpty() ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\""); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), aURL, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sOut.append('\"'); } OUString aType; aAny = xSet->getPropertyValue("PluginMimeType"); if( (aAny >>= aType) && !aType.isEmpty() ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_type "=\""); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), aType, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sOut.append('\"'); } if ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) && css::text::WrapTextMode_THROUGH == rFrameFormat.GetSurround().GetSurround() ) { // A HIDDEN plug-in sOut.append(' ').append(OOO_STRING_SW_HTML_O_Hidden); nFrameOpts = HTML_FRMOPTS_HIDDEN_EMBED; bHiddenEmbed = true; } else { nFrameOpts = bInCntnr ? HTML_FRMOPTS_EMBED_CNTNR : HTML_FRMOPTS_EMBED; } } else if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) ) { // or the applet specifics sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet); // CODEBASE OUString aCd; aAny = xSet->getPropertyValue("AppletCodeBase"); if( (aAny >>= aCd) && !aCd.isEmpty() ) { OUString sCodeBase( URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aCd) ); if( !sCodeBase.isEmpty() ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\""); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sOut.append('\"'); } } // CODE OUString aClass; aAny = xSet->getPropertyValue("AppletCode"); aAny >>= aClass; sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_code "=\""); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sOut.append('\"'); // NAME OUString aAppletName; aAny = xSet->getPropertyValue("AppletName"); aAny >>= aAppletName; if( !aAppletName.isEmpty() ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sOut.append('\"'); } bool bScript = false; aAny = xSet->getPropertyValue("AppletIsScript"); aAny >>= bScript; if( bScript ) sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_mayscript); nFrameOpts = bInCntnr ? HTML_FRMOPTS_APPLET_CNTNR : HTML_FRMOPTS_APPLET; } else { // or the Floating-Frame specifics sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe); rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); SfxFrameHTMLWriter::Out_FrameDescriptor( rWrt.Strm(), rWrt.GetBaseURL(), xSet, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); nFrameOpts = bInCntnr ? HTML_FRMOPTS_IFRAME_CNTNR : HTML_FRMOPTS_IFRAME; } rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); // ALT, WIDTH, HEIGHT, HSPACE, VSPACE, ALIGN if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) nFrameOpts |= HTML_FRMOPTS_OLE_CSS1; OString aEndTags = rHTMLWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts ); if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts ); if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) ) { // output the parameters of applets as separate tags // and write a uno::Sequence < beans::PropertyValue > aProps; aAny = xSet->getPropertyValue("AppletCommands"); aAny >>= aProps; SvCommandList aCommands; aCommands.FillFromSequence( aProps ); std::vector aParams; size_t i = aCommands.size(); while( i > 0 ) { const SvCommand& rCommand = aCommands[ --i ]; const OUString& rName = rCommand.GetCommand(); SwHtmlOptType nType = SwApplet_Impl::GetOptionType( rName, true ); if( SwHtmlOptType::TAG == nType ) { const OUString& rValue = rCommand.GetArgument(); rWrt.Strm().WriteChar( ' ' ); HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); rWrt.Strm().WriteCharPtr( "=\"" ); HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' ); } else if( SwHtmlOptType::PARAM == nType ) { aParams.push_back( i ); } } rHTMLWrt.Strm().WriteChar( '>' ); rHTMLWrt.IncIndentLevel(); // indent the applet content size_t ii = aParams.size(); while( ii > 0 ) { const SvCommand& rCommand = aCommands[ aParams[--ii] ]; const OUString& rName = rCommand.GetCommand(); const OUString& rValue = rCommand.GetArgument(); rHTMLWrt.OutNewLine(); OStringBuffer sBuf; sBuf.append("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param " " OOO_STRING_SVTOOLS_HTML_O_name "=\""); rWrt.Strm().WriteOString( sBuf.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); sBuf.append("\" " OOO_STRING_SVTOOLS_HTML_O_value "=\""); rWrt.Strm().WriteOString( sBuf.makeStringAndClear() ); HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteCharPtr( "\">" ); } rHTMLWrt.DecIndentLevel(); // indent the applet content if( aCommands.size() ) rHTMLWrt.OutNewLine(); HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet), false ); } else if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) ) { // write plug-ins parameters as options uno::Sequence < beans::PropertyValue > aProps; aAny = xSet->getPropertyValue("PluginCommands"); aAny >>= aProps; SvCommandList aCommands; aCommands.FillFromSequence( aProps ); for( size_t i = 0; i < aCommands.size(); i++ ) { const SvCommand& rCommand = aCommands[ i ]; const OUString& rName = rCommand.GetCommand(); if( SwApplet_Impl::GetOptionType( rName, false ) == SwHtmlOptType::TAG ) { const OUString& rValue = rCommand.GetArgument(); rWrt.Strm().WriteChar( ' ' ); HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); rWrt.Strm().WriteCharPtr( "=\"" ); HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' ); } } rHTMLWrt.Strm().WriteChar( '>' ); } else { // and for Floating-Frames just output another rHTMLWrt.Strm().WriteChar( '>' ); HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe), false ); } if( !aEndTags.isEmpty() ) rWrt.Strm().WriteOString( aEndTags ); return rWrt; } Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrameFormat, bool bInCntnr ) { SwHTMLWriter& rHTMLWrt = static_cast(rWrt); const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); OSL_ENSURE( pOLENd, "OLE-Node expected" ); if( !pOLENd ) return rWrt; if (rHTMLWrt.mbSkipImages) { // If we skip images, embedded objects would be completely lost. // Instead, try to use the HTML export of the embedded object. uno::Reference xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rHTMLWrt.m_pDoc, const_cast(&rFrameFormat)); uno::Reference xEmbeddedObjectSupplier(xTextContent, uno::UNO_QUERY); uno::Reference xStorable(xEmbeddedObjectSupplier->getEmbeddedObject(), uno::UNO_QUERY); SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrameFormatOLENodeGrf: no embedded object"); // Figure out what is the filter name of the embedded object. uno::Reference xServiceInfo(xStorable, uno::UNO_QUERY); OUString aFilter; if (xServiceInfo.is()) { if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument")) aFilter = "HTML (StarCalc)"; else if (xServiceInfo->supportsService("com.sun.star.text.TextDocument")) aFilter = "HTML (StarWriter)"; } if (xStorable.is() && !aFilter.isEmpty()) { try { // FIXME: exception for the simplest test document, too SvMemoryStream aStream; uno::Reference xOutputStream(new utl::OStreamWrapper(aStream)); utl::MediaDescriptor aMediaDescriptor; aMediaDescriptor["FilterName"] <<= aFilter; aMediaDescriptor["FilterOptions"] <<= OUString("SkipHeaderFooter"); aMediaDescriptor["OutputStream"] <<= xOutputStream; xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList()); SAL_WARN_IF(aStream.GetSize()>=o3tl::make_unsigned(SAL_MAX_INT32), "sw.html", "Stream can't fit in OString"); OString aData(static_cast(aStream.GetData()), static_cast(aStream.GetSize())); // Wrap output in a tag to avoid 'HTML parser error: Unexpected end tag: p' HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span)); rWrt.Strm().WriteOString(aData); HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); } catch ( uno::Exception& ) { } } return rWrt; } if ( !pOLENd->GetGraphic() ) { SAL_WARN("sw.html", "Unexpected missing OLE fallback graphic"); return rWrt; } Graphic aGraphic( *pOLENd->GetGraphic() ); SwDocShell* pDocSh = rHTMLWrt.m_pDoc->GetDocShell(); bool bObjectOpened = false; OUString aRTFType = "text/rtf"; if (!rHTMLWrt.m_aRTFOLEMimeType.isEmpty()) { aRTFType = rHTMLWrt.m_aRTFOLEMimeType; } if (rHTMLWrt.mbXHTML && pDocSh) { // Map native data to an outer element. // Calculate the file name, which is meant to be the same as the // replacement image, just with a .ole extension. OUString aFileName = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"ole"); // Write the data. SwOLEObj& rOLEObj = pOLENd->GetOLEObj(); uno::Reference xEmbeddedObject = rOLEObj.GetOleRef(); OUString aFileType; SvFileStream aOutStream(aFileName, StreamMode::WRITE); uno::Reference xStreamProvider; uno::Reference xOwnEmbedded; if (xEmbeddedObject.is()) { xStreamProvider.set(xEmbeddedObject, uno::UNO_QUERY); xOwnEmbedded.set(xEmbeddedObject, uno::UNO_QUERY); } if (xStreamProvider.is()) { // Real OLE2 case: OleEmbeddedObject. uno::Reference xStream(xStreamProvider->getStream(), uno::UNO_QUERY); if (xStream.is()) { std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xStream)); if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd, rFrameFormat)) { // Data always wrapped in RTF. aFileType = aRTFType; } } } else if (xOwnEmbedded.is()) { // Our own embedded object: OCommonEmbeddedObject. SvxMSExportOLEObjects aOLEExp(0); // Trigger the load of the OLE object if needed, otherwise we can't // export it. pOLENd->GetTwipSize(); SvMemoryStream aMemory; tools::SvRef pStorage = new SotStorage(aMemory); aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage); pStorage->Commit(); aMemory.Seek(0); if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd, rFrameFormat)) { // Data always wrapped in RTF. aFileType = aRTFType; } } else { // Otherwise the native data is just a grab-bag: ODummyEmbeddedObject. const OUString& aStreamName = rOLEObj.GetCurrentPersistName(); uno::Reference xStorage = pDocSh->GetStorage(); uno::Reference xInStream; try { // Even the native data may be missing. xInStream = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ); } catch (const uno::Exception&) { TOOLS_WARN_EXCEPTION("sw.html", "OutHTML_FrameFormatOLENodeGrf: failed to open stream element"); } if (xInStream.is()) { uno::Reference xOutStream(new utl::OStreamWrapper(aOutStream)); comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(), xOutStream->getOutputStream()); } uno::Reference xOutStreamProps(xInStream, uno::UNO_QUERY); if (xOutStreamProps.is()) xOutStreamProps->getPropertyValue("MediaType") >>= aFileType; if (!aRTFType.isEmpty()) { aFileType = aRTFType; } } aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName); // Refer to this data. if (rHTMLWrt.m_bLFPossible) rHTMLWrt.OutNewLine(); rWrt.Strm().WriteOString(OString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object)); rWrt.Strm().WriteOString(OString(" data=\"" + aFileName.toUtf8() + "\"")); if (!aFileType.isEmpty()) rWrt.Strm().WriteOString(OString(" type=\"" + aFileType.toUtf8() + "\"")); rWrt.Strm().WriteOString(">"); bObjectOpened = true; rHTMLWrt.m_bLFPossible = true; } OUString aGraphicURL; OUString aMimeType; if(!rHTMLWrt.mbEmbedImages) { const OUString* pTempFileName = rHTMLWrt.GetOrigFileName(); if(pTempFileName) aGraphicURL = *pTempFileName; OUString aFilterName("JPG"); XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible; if (bObjectOpened) { aFilterName = "PNG"; nFlags = XOutFlags::NONE; aMimeType = "image/png"; if (aGraphic.GetType() == GraphicType::NONE) { // The OLE Object has no replacement image, write a stub. aGraphicURL = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"png"); osl::File aFile(aGraphicURL); aFile.open(osl_File_OpenFlag_Create); aFile.close(); } } ErrCode nErr = XOutBitmap::WriteGraphic( aGraphic, aGraphicURL, aFilterName, nFlags ); if( nErr ) // error, don't write anything { rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; return rWrt; } aGraphicURL = URIHelper::SmartRel2Abs( INetURLObject(rWrt.GetBaseURL()), aGraphicURL, URIHelper::GetMaybeFileHdl() ); } HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask : HtmlFrmOpts::GenImgMask; if (bObjectOpened) nFlags |= HtmlFrmOpts::Replacement; HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace); OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic, pOLENd->GetTitle(), pOLENd->GetTwipSize(), nFlags, "ole", nullptr, aMimeType ); OutHTML_ImageEnd(aHtml, rWrt); if (bObjectOpened) // Close native data. rWrt.Strm().WriteOString(OString("")); return rWrt; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */