simplify writeBitmapObject
[LibreOffice.git] / sw / source / filter / html / htmlplug.cxx
blob40ccc0c6cb668b7e0d68f0c932499eeeca4cbfdc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_java.h>
22 #include <hintids.hxx>
23 #include <rtl/strbuf.hxx>
24 #include <sal/log.hxx>
25 #include <svl/urihelper.hxx>
26 #include <vcl/svapp.hxx>
27 #include <sfx2/frmhtml.hxx>
28 #include <sfx2/frmhtmlw.hxx>
29 #include <sfx2/frmdescr.hxx>
30 #include <sot/storage.hxx>
31 #include <svx/xoutbmp.hxx>
32 #include <editeng/ulspitem.hxx>
33 #include <editeng/lrspitem.hxx>
34 #include <svtools/htmlout.hxx>
35 #include <svtools/htmlkywd.hxx>
36 #include <svtools/htmltokn.h>
37 #include <comphelper/diagnose_ex.hxx>
38 #include <IDocumentContentOperations.hxx>
39 #include <SwAppletImpl.hxx>
40 #include <fmtornt.hxx>
41 #include <fmtfsize.hxx>
42 #include <fmtsrnd.hxx>
43 #include <fmtanchr.hxx>
44 #include <fmtcntnt.hxx>
45 #include <frmfmt.hxx>
47 #include <svl/ownlist.hxx>
48 #include <unotools/mediadescriptor.hxx>
49 #include <unotools/streamwrap.hxx>
50 #include <pam.hxx>
51 #include <doc.hxx>
52 #include <swerror.h>
53 #include <ndole.hxx>
54 #include <docsh.hxx>
55 #include "swhtml.hxx"
56 #include "wrthtml.hxx"
57 #include "htmlfly.hxx"
58 #include "swcss1.hxx"
59 #include "htmlreqifreader.hxx"
60 #include <unoframe.hxx>
61 #include <com/sun/star/embed/XClassifiedObject.hpp>
62 #include <com/sun/star/embed/Aspects.hpp>
63 #include <com/sun/star/beans/XPropertySet.hpp>
64 #include <com/sun/star/frame/XStorable.hpp>
65 #include <com/sun/star/embed/ElementModes.hpp>
66 #include <com/sun/star/io/XActiveDataStreamer.hpp>
67 #include <com/sun/star/embed/XEmbedPersist2.hpp>
68 #include <com/sun/star/lang/XInitialization.hpp>
70 #include <comphelper/embeddedobjectcontainer.hxx>
71 #include <comphelper/classids.hxx>
72 #include <rtl/uri.hxx>
73 #include <comphelper/storagehelper.hxx>
74 #include <vcl/graphicfilter.hxx>
75 #include <unotools/ucbstreamhelper.hxx>
76 #include <comphelper/propertysequence.hxx>
77 #include <filter/msfilter/msoleexp.hxx>
78 #include <comphelper/fileurl.hxx>
79 #include <o3tl/safeint.hxx>
80 #include <osl/file.hxx>
81 #include <comphelper/propertyvalue.hxx>
82 #include <svtools/HtmlWriter.hxx>
84 using namespace com::sun::star;
87 #define HTML_DFLT_EMBED_WIDTH (o3tl::toTwips(125, o3tl::Length::mm10))
88 #define HTML_DFLT_EMBED_HEIGHT (o3tl::toTwips(125, o3tl::Length::mm10))
90 #define HTML_DFLT_APPLET_WIDTH (o3tl::toTwips(125, o3tl::Length::mm10))
91 #define HTML_DFLT_APPLET_HEIGHT (o3tl::toTwips(125, o3tl::Length::mm10))
94 const HtmlFrmOpts HTML_FRMOPTS_EMBED_ALL =
95 HtmlFrmOpts::Alt |
96 HtmlFrmOpts::Size |
97 HtmlFrmOpts::Name;
98 const HtmlFrmOpts HTML_FRMOPTS_EMBED_CNTNR =
99 HTML_FRMOPTS_EMBED_ALL |
100 HtmlFrmOpts::AbsSize;
101 const HtmlFrmOpts HTML_FRMOPTS_EMBED =
102 HTML_FRMOPTS_EMBED_ALL |
103 HtmlFrmOpts::Align |
104 HtmlFrmOpts::Space |
105 HtmlFrmOpts::BrClear |
106 HtmlFrmOpts::Name;
107 const HtmlFrmOpts HTML_FRMOPTS_HIDDEN_EMBED =
108 HtmlFrmOpts::Alt |
109 HtmlFrmOpts::Name;
111 const HtmlFrmOpts HTML_FRMOPTS_APPLET_ALL =
112 HtmlFrmOpts::Alt |
113 HtmlFrmOpts::Size;
114 const HtmlFrmOpts HTML_FRMOPTS_APPLET_CNTNR =
115 HTML_FRMOPTS_APPLET_ALL |
116 HtmlFrmOpts::AbsSize;
117 const HtmlFrmOpts HTML_FRMOPTS_APPLET =
118 HTML_FRMOPTS_APPLET_ALL |
119 HtmlFrmOpts::Align |
120 HtmlFrmOpts::Space |
121 HtmlFrmOpts::BrClear;
123 const HtmlFrmOpts HTML_FRMOPTS_IFRAME_ALL =
124 HtmlFrmOpts::Alt |
125 HtmlFrmOpts::Size;
126 const HtmlFrmOpts HTML_FRMOPTS_IFRAME_CNTNR =
127 HTML_FRMOPTS_IFRAME_ALL |
128 HtmlFrmOpts::AbsSize;
129 const HtmlFrmOpts HTML_FRMOPTS_IFRAME =
130 HTML_FRMOPTS_IFRAME_ALL |
131 HtmlFrmOpts::Align |
132 HtmlFrmOpts::Space |
133 HtmlFrmOpts::Border |
134 HtmlFrmOpts::BrClear;
136 const HtmlFrmOpts HTML_FRMOPTS_OLE_CSS1 =
137 HtmlFrmOpts::SAlign |
138 HtmlFrmOpts::SSpace;
140 namespace
143 * Calculates a filename for an image, provided the HTML file name, the image
144 * itself and a wanted extension.
146 OUString lcl_CalculateFileName(const OUString* pOrigFileName, const Graphic& rGraphic,
147 std::u16string_view rExtension)
149 OUString aFileName;
151 if (pOrigFileName)
152 aFileName = *pOrigFileName;
153 INetURLObject aURL(aFileName);
154 OUString aName = aURL.getBase() + "_" +
155 aURL.getExtension() + "_" +
156 OUString::number(rGraphic.GetChecksum(), 16);
157 aURL.setBase(aName);
158 aURL.setExtension(rExtension);
159 aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
161 return aFileName;
165 void SwHTMLParser::SetFixSize( const Size& rPixSize,
166 const Size& rTwipDfltSize,
167 bool bPercentWidth, bool bPercentHeight,
168 SvxCSS1PropertyInfo const & rCSS1PropInfo,
169 SfxItemSet& rFlyItemSet )
171 // convert absolute size values into Twip
172 sal_uInt8 nPercentWidth = 0, nPercentHeight = 0;
173 Size aTwipSz( bPercentWidth || USHRT_MAX==rPixSize.Width() ? 0 : rPixSize.Width(),
174 bPercentHeight || USHRT_MAX==rPixSize.Height() ? 0 : rPixSize.Height() );
175 if( aTwipSz.Width() || aTwipSz.Height() )
177 aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip);
180 // process width
181 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eWidthType )
183 nPercentWidth = static_cast<sal_uInt8>(rCSS1PropInfo.m_nWidth);
184 aTwipSz.setWidth( rTwipDfltSize.Width() );
186 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eWidthType )
188 aTwipSz.setWidth( rCSS1PropInfo.m_nWidth );
190 else if( bPercentWidth && rPixSize.Width() )
192 nPercentWidth = static_cast<sal_uInt8>(rPixSize.Width());
193 if (nPercentWidth > 100 && nPercentWidth != SwFormatFrameSize::SYNCED)
194 nPercentWidth = 100;
196 aTwipSz.setWidth( rTwipDfltSize.Width() );
198 else if( USHRT_MAX==rPixSize.Width() )
200 aTwipSz.setWidth( rTwipDfltSize.Width() );
202 if( aTwipSz.Width() < MINFLY )
204 aTwipSz.setWidth( MINFLY );
207 // process height
208 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eHeightType )
210 nPercentHeight = static_cast<sal_uInt8>(rCSS1PropInfo.m_nHeight);
211 aTwipSz.setHeight( rTwipDfltSize.Height() );
213 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eHeightType )
215 aTwipSz.setHeight( rCSS1PropInfo.m_nHeight );
217 else if( bPercentHeight && rPixSize.Height() )
219 nPercentHeight = static_cast<sal_uInt8>(rPixSize.Height());
220 if (nPercentHeight > 100 && nPercentHeight != SwFormatFrameSize::SYNCED)
221 nPercentHeight = 100;
223 aTwipSz.setHeight( rTwipDfltSize.Height() );
225 else if( USHRT_MAX==rPixSize.Height() )
227 aTwipSz.setHeight( rTwipDfltSize.Height() );
229 if( aTwipSz.Height() < MINFLY )
231 aTwipSz.setHeight( MINFLY );
234 // set size
235 SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, aTwipSz.Width(), aTwipSz.Height() );
236 aFrameSize.SetWidthPercent( nPercentWidth );
237 aFrameSize.SetHeightPercent( nPercentHeight );
238 rFlyItemSet.Put( aFrameSize );
241 void SwHTMLParser::SetSpace( const Size& rPixSpace,
242 SfxItemSet& rCSS1ItemSet,
243 SvxCSS1PropertyInfo& rCSS1PropInfo,
244 SfxItemSet& rFlyItemSet )
246 sal_Int32 nLeftSpace = 0, nRightSpace = 0;
247 sal_uInt16 nUpperSpace = 0, nLowerSpace = 0;
248 if( rPixSpace.Width() || rPixSpace.Height() )
250 nLeftSpace = nRightSpace = o3tl::convert(rPixSpace.Width(), o3tl::Length::px, o3tl::Length::twip);
251 nUpperSpace = nLowerSpace = o3tl::convert(rPixSpace.Height(), o3tl::Length::px, o3tl::Length::twip);
254 // set left/right margin
255 // note: parser never creates SvxLeftMarginItem! must be converted
256 if (const SvxTextLeftMarginItem *const pLeft = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT))
258 if( rCSS1PropInfo.m_bLeftMargin )
260 // should be SvxLeftMarginItem... "cast" it
261 nLeftSpace = pLeft->ResolveTextLeft({});
262 rCSS1PropInfo.m_bLeftMargin = false;
264 rCSS1ItemSet.ClearItem(RES_MARGIN_TEXTLEFT);
266 if (const SvxRightMarginItem *const pRight = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_RIGHT))
268 if( rCSS1PropInfo.m_bRightMargin )
270 nRightSpace = pRight->ResolveRight({});
271 rCSS1PropInfo.m_bRightMargin = false;
273 rCSS1ItemSet.ClearItem(RES_MARGIN_RIGHT);
275 if( nLeftSpace > 0 || nRightSpace > 0 )
277 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
278 aLRItem.SetLeft(SvxIndentValue::twips(std::max<sal_Int32>(nLeftSpace, 0)));
279 aLRItem.SetRight(SvxIndentValue::twips(std::max<sal_Int32>(nRightSpace, 0)));
280 rFlyItemSet.Put( aLRItem );
281 if( nLeftSpace )
283 const SwFormatHoriOrient& rHoriOri =
284 rFlyItemSet.Get( RES_HORI_ORIENT );
285 if( text::HoriOrientation::NONE == rHoriOri.GetHoriOrient() )
287 SwFormatHoriOrient aHoriOri( rHoriOri );
288 aHoriOri.SetPos( aHoriOri.GetPos() + nLeftSpace );
289 rFlyItemSet.Put( aHoriOri );
294 // set top/bottom margin
295 if( const SvxULSpaceItem *pULItem = rCSS1ItemSet.GetItemIfSet( RES_UL_SPACE ) )
297 // if applicable remove the first line indent
298 if( rCSS1PropInfo.m_bTopMargin )
300 nUpperSpace = pULItem->GetUpper();
301 rCSS1PropInfo.m_bTopMargin = false;
303 if( rCSS1PropInfo.m_bBottomMargin )
305 nLowerSpace = pULItem->GetLower();
306 rCSS1PropInfo.m_bBottomMargin = false;
308 rCSS1ItemSet.ClearItem( RES_UL_SPACE );
310 if( !(nUpperSpace || nLowerSpace) )
311 return;
313 SvxULSpaceItem aULItem( RES_UL_SPACE );
314 aULItem.SetUpper( nUpperSpace );
315 aULItem.SetLower( nLowerSpace );
316 rFlyItemSet.Put( aULItem );
317 if( nUpperSpace )
319 const SwFormatVertOrient& rVertOri =
320 rFlyItemSet.Get( RES_VERT_ORIENT );
321 if( text::VertOrientation::NONE == rVertOri.GetVertOrient() )
323 SwFormatVertOrient aVertOri( rVertOri );
324 aVertOri.SetPos( aVertOri.GetPos() + nUpperSpace );
325 rFlyItemSet.Put( aVertOri );
330 OUString SwHTMLParser::StripQueryFromPath(std::u16string_view rBase, const OUString& rPath)
332 if (!comphelper::isFileUrl(rBase))
333 return rPath;
335 sal_Int32 nIndex = rPath.indexOf('?');
337 if (nIndex != -1)
338 return rPath.copy(0, nIndex);
340 return rPath;
343 bool SwHTMLParser::InsertEmbed()
345 OUString aURL, aType, aName, aAlt, aId, aStyle, aClass;
346 OUString aData;
347 Size aSize( USHRT_MAX, USHRT_MAX );
348 Size aSpace( USHRT_MAX, USHRT_MAX );
349 bool bPercentWidth = false, bPercentHeight = false, bHidden = false;
350 sal_Int16 eVertOri = text::VertOrientation::NONE;
351 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
352 SvCommandList aCmdLst;
353 const HTMLOptions& rHTMLOptions = GetOptions();
355 // The options are read forwards, because the plug-ins expect them in this
356 // order. Still only the first value of an option may be regarded.
357 for (const auto & rOption : rHTMLOptions)
359 switch( rOption.GetToken() )
361 case HtmlOptionId::ID:
362 aId = rOption.GetString();
363 break;
364 case HtmlOptionId::STYLE:
365 aStyle = rOption.GetString();
366 break;
367 case HtmlOptionId::CLASS:
368 aClass = rOption.GetString();
369 break;
370 case HtmlOptionId::NAME:
371 aName = rOption.GetString();
372 break;
373 case HtmlOptionId::SRC:
374 if( aURL.isEmpty() )
375 aURL = rOption.GetString();
376 break;
377 case HtmlOptionId::ALT:
378 aAlt = rOption.GetString();
379 break;
380 case HtmlOptionId::TYPE:
381 if( aType.isEmpty() )
382 aType = rOption.GetString();
383 break;
384 case HtmlOptionId::ALIGN:
385 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
387 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
388 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
390 break;
391 case HtmlOptionId::WIDTH:
392 if( USHRT_MAX==aSize.Width() )
394 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
395 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
397 break;
398 case HtmlOptionId::HEIGHT:
399 if( USHRT_MAX==aSize.Height() )
401 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
402 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
404 break;
405 case HtmlOptionId::HSPACE:
406 if( USHRT_MAX==aSpace.Width() )
407 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
408 break;
409 case HtmlOptionId::VSPACE:
410 if( USHRT_MAX==aSpace.Height() )
411 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
412 break;
413 case HtmlOptionId::DATA:
414 if (m_bXHTML && aURL.isEmpty())
415 aData = rOption.GetString();
416 break;
417 case HtmlOptionId::UNKNOWN:
418 if (rOption.GetTokenString().equalsIgnoreAsciiCase(
419 OOO_STRING_SW_HTML_O_Hidden))
421 bHidden = !rOption.GetString().equalsIgnoreAsciiCase(
422 "FALSE");
424 break;
425 default: break;
428 // All parameters are passed to the plug-in.
429 aCmdLst.Append( rOption.GetTokenString(), rOption.GetString() );
432 static const std::set<std::u16string_view> vAllowlist = {
433 u"image/png",
434 u"image/gif",
435 u"image/x-MS-bmp",
436 u"image/jpeg",
437 u"image/x-wmf",
438 u"image/svg+xml",
439 u"image/tiff",
440 u"image/x-emf",
441 u"image/bmp",
442 u"image/tif",
443 u"image/wmf",
446 if (vAllowlist.find(aType) != vAllowlist.end() && m_aEmbeds.empty())
448 // Toplevel <object> for an image format -> that's an image, not an OLE object.
449 m_aEmbeds.push(nullptr);
450 return false;
453 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
454 SvxCSS1PropertyInfo aPropInfo;
455 if( HasStyleOptions( aStyle, aId, aClass ) )
456 (void)ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
458 // Convert the default values (except height/width, which is done by SetFrameSize())
459 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
460 eVertOri = text::VertOrientation::TOP;
461 if( USHRT_MAX==aSpace.Width() )
462 aSpace.setWidth( 0 );
463 if( USHRT_MAX==aSpace.Height() )
464 aSpace.setHeight( 0 );
465 if( bHidden )
467 // Size (0,0) will be changed to (MINFLY, MINFLY) in SetFrameSize()
468 aSize.setWidth( 0 ); aSize.setHeight( 0 );
469 aSpace.setWidth( 0 ); aSpace.setHeight( 0 );
470 bPercentWidth = bPercentHeight = false;
473 // prepare the URL
474 INetURLObject aURLObj;
475 bool bHasURL = !aURL.isEmpty() &&
476 aURLObj.SetURL(
477 URIHelper::SmartRel2Abs(
478 INetURLObject(m_sBaseURL), aURL,
479 URIHelper::GetMaybeFileHdl()) );
480 bool bHasData = !aData.isEmpty();
484 // Strip query and everything after that for file:// URLs, browsers do
485 // the same.
486 aURLObj.SetURL(rtl::Uri::convertRelToAbs(
487 m_sBaseURL, SwHTMLParser::StripQueryFromPath(m_sBaseURL, aData)));
489 catch (const rtl::MalformedUriException& /*rException*/)
491 bHasData = false;
494 // do not insert plugin if it has neither URL nor type
495 bool bHasType = !aType.isEmpty();
496 if( !bHasURL && !bHasType && !bHasData )
497 return true;
499 if (!m_aEmbeds.empty())
501 // Nested XHTML <object> element: points to replacement graphic.
502 SwOLENode* pOLENode = m_aEmbeds.top();
503 if (!pOLENode)
505 // <object> is mapped to an image -> ignore replacement graphic.
506 return true;
509 svt::EmbeddedObjectRef& rObj = pOLENode->GetOLEObj().GetObject();
510 Graphic aGraphic;
511 if (GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aURLObj) != ERRCODE_NONE)
512 return true;
514 rObj.SetGraphic(aGraphic, aType);
516 // Set the size of the OLE frame to the size of the graphic.
517 SwFrameFormat* pFormat = pOLENode->GetFlyFormat();
518 if (!pFormat)
519 return true;
520 SwAttrSet aAttrSet(pFormat->GetAttrSet());
521 aAttrSet.ClearItem(RES_CNTNT);
522 Size aDefaultTwipSize(o3tl::convert(aGraphic.GetSizePixel(), o3tl::Length::px, o3tl::Length::twip));
524 if (aSize.Width() == USHRT_MAX && bPercentHeight)
526 // Height is relative, width is not set: keep aspect ratio.
527 aSize.setWidth(SwFormatFrameSize::SYNCED);
528 bPercentWidth = true;
530 if (aSize.Height() == USHRT_MAX && bPercentWidth)
532 // Width is relative, height is not set: keep aspect ratio.
533 aSize.setHeight(SwFormatFrameSize::SYNCED);
534 bPercentHeight = true;
537 SetFixSize(aSize, aDefaultTwipSize, bPercentWidth, bPercentHeight, aPropInfo, aAttrSet);
538 pOLENode->GetDoc().SetFlyFrameAttr(*pFormat, aAttrSet);
539 return true;
542 // create the plug-in
543 comphelper::EmbeddedObjectContainer aCnt;
544 OUString aObjName;
545 uno::Reference < embed::XEmbeddedObject > xObj;
546 if (!bHasData)
548 xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence(), aObjName );
549 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
551 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
552 if ( xSet.is() )
554 if( bHasURL )
555 xSet->setPropertyValue(u"PluginURL"_ustr, uno::Any( aURL ) );
556 if( bHasType )
557 xSet->setPropertyValue(u"PluginMimeType"_ustr, uno::Any( aType ) );
559 uno::Sequence < beans::PropertyValue > aProps;
560 aCmdLst.FillSequence( aProps );
561 xSet->setPropertyValue(u"PluginCommands"_ustr, uno::Any( aProps ) );
566 else if (SwDocShell* pDocSh = m_xDoc->GetDocShell())
568 // Has non-empty data attribute in XHTML: map that to an OLE object.
569 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
570 aCnt.SwitchPersistence(xStorage);
571 aObjName = aCnt.CreateUniqueObjectName();
573 OUString aEmbedURL = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
574 SvFileStream aFileStream(aEmbedURL, StreamMode::READ);
575 uno::Reference<io::XInputStream> xInStream;
576 SvMemoryStream aMemoryStream;
578 // Allow any MIME type that starts with magic, unless a set of allowed types are
579 // specified.
580 auto it = m_aAllowedRTFOLEMimeTypes.find(aType);
581 if (m_aAllowedRTFOLEMimeTypes.empty() || it != m_aAllowedRTFOLEMimeTypes.end())
583 OString aMagic("{\\object"_ostr);
584 OString aHeader(read_uInt8s_ToOString(aFileStream, aMagic.getLength()));
585 aFileStream.Seek(0);
586 if (aHeader == aMagic)
588 // OLE2 wrapped in RTF: either own format or real OLE2 embedding.
589 bool bOwnFormat = false;
590 if (SwReqIfReader::ExtractOleFromRtf(aFileStream, aMemoryStream, bOwnFormat))
592 xInStream.set(new utl::OStreamWrapper(aMemoryStream));
595 if (bOwnFormat)
597 uno::Sequence<beans::PropertyValue> aMedium = comphelper::InitPropertySequence(
598 { { "InputStream", uno::Any(xInStream) },
599 { "URL", uno::Any(u"private:stream"_ustr) },
600 { "DocumentBaseURL", uno::Any(m_sBaseURL) } });
601 xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &m_sBaseURL);
603 else
605 // The type is now an OLE2 container, not the original XHTML type.
606 aType = "application/vnd.sun.star.oleobject";
611 if (!xInStream.is())
613 // Object data is neither OLE2 in RTF, nor an image. Then map this to an URL that
614 // will be set on the inner image.
615 m_aEmbedURL = aEmbedURL;
616 // Signal success, so the outer object won't fall back to the image handler.
617 return true;
620 if (!xObj.is())
622 uno::Reference<io::XStream> xOutStream
623 = xStorage->openStreamElement(aObjName, embed::ElementModes::READWRITE);
624 if (aFileStream.IsOpen())
625 comphelper::OStorageHelper::CopyInputToOutput(xInStream,
626 xOutStream->getOutputStream());
628 if (!aType.isEmpty())
630 // Set media type of the native data.
631 uno::Reference<beans::XPropertySet> xOutStreamProps(xOutStream, uno::UNO_QUERY);
632 if (xOutStreamProps.is())
633 xOutStreamProps->setPropertyValue(u"MediaType"_ustr, uno::Any(aType));
636 xObj = aCnt.GetEmbeddedObject(aObjName);
640 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() );
641 if( !IsNewDoc() )
642 Reader::ResetFrameFormatAttrs( aFrameSet );
644 // set the anchor
645 if( !bHidden )
647 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
649 else
651 SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA );
652 aAnchor.SetAnchor( m_pPam->GetPoint() );
653 aFrameSet.Put( aAnchor );
654 aFrameSet.Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME) );
655 aFrameSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
656 aFrameSet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) );
659 // and the size of the frame
660 Size aDfltSz( HTML_DFLT_EMBED_WIDTH, HTML_DFLT_EMBED_HEIGHT );
661 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
662 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
664 // and insert into the document
665 uno::Reference<lang::XInitialization> xObjInitialization(xObj, uno::UNO_QUERY);
666 if (xObjInitialization.is())
668 // Request that the native data of the embedded object is not modified
669 // during parsing.
670 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue(u"StreamReadOnly"_ustr,
671 true) };
672 uno::Sequence<uno::Any> aArguments{ uno::Any(aValues) };
673 xObjInitialization->initialize(aArguments);
675 SwFrameFormat* pFlyFormat =
676 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
677 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
678 &aFrameSet);
679 if (xObjInitialization.is())
681 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue(u"StreamReadOnly"_ustr,
682 false) };
683 uno::Sequence<uno::Any> aArguments{ uno::Any(aValues) };
684 xObjInitialization->initialize(aArguments);
687 // set name at FrameFormat
688 if( !aName.isEmpty() )
689 pFlyFormat->SetFormatName( aName );
691 // set the alternative text
692 SwNoTextNode *pNoTextNd =
693 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
694 ->GetIndex()+1 ]->GetNoTextNode();
695 pNoTextNd->SetTitle( aAlt );
697 // if applicable create frames and register auto-bound frames
698 if( !bHidden )
700 // HIDDEN plug-ins should stay paragraph-bound. Since RegisterFlyFrame()
701 // will change paragraph-bound frames with wrap-through into a
702 // character-bound frame, here we must create the frames by hand.
703 RegisterFlyFrame( pFlyFormat );
706 if (!bHasData)
707 return true;
709 SwOLENode* pOLENode = pNoTextNd->GetOLENode();
710 if (!pOLENode)
711 return true;
713 m_aEmbeds.push(pOLENode);
715 return true;
718 #if HAVE_FEATURE_JAVA
719 void SwHTMLParser::NewObject()
721 OUString aClassID;
722 OUString aStandBy, aId, aStyle, aClass;
723 Size aSize( USHRT_MAX, USHRT_MAX );
724 Size aSpace( 0, 0 );
725 sal_Int16 eVertOri = text::VertOrientation::TOP;
726 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
728 bool bPercentWidth = false, bPercentHeight = false,
729 bDeclare = false;
730 // create a new Command list
731 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
733 const HTMLOptions& rHTMLOptions = GetOptions();
734 for (size_t i = rHTMLOptions.size(); i; )
736 const HTMLOption& rOption = rHTMLOptions[--i];
737 switch( rOption.GetToken() )
739 case HtmlOptionId::ID:
740 aId = rOption.GetString();
741 break;
742 case HtmlOptionId::STYLE:
743 aStyle = rOption.GetString();
744 break;
745 case HtmlOptionId::CLASS:
746 aClass = rOption.GetString();
747 break;
748 case HtmlOptionId::DECLARE:
749 bDeclare = true;
750 break;
751 case HtmlOptionId::CLASSID:
752 aClassID = rOption.GetString();
753 break;
754 case HtmlOptionId::CODEBASE:
755 break;
756 case HtmlOptionId::DATA:
757 break;
758 case HtmlOptionId::TYPE:
759 break;
760 case HtmlOptionId::CODETYPE:
761 break;
762 case HtmlOptionId::ARCHIVE:
763 case HtmlOptionId::UNKNOWN:
764 break;
765 case HtmlOptionId::STANDBY:
766 aStandBy = rOption.GetString();
767 break;
768 case HtmlOptionId::WIDTH:
769 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
770 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
771 break;
772 case HtmlOptionId::HEIGHT:
773 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
774 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
775 break;
776 case HtmlOptionId::ALIGN:
777 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
778 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
779 break;
780 case HtmlOptionId::USEMAP:
781 break;
782 case HtmlOptionId::NAME:
783 break;
784 case HtmlOptionId::HSPACE:
785 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
786 break;
787 case HtmlOptionId::VSPACE:
788 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
789 break;
790 case HtmlOptionId::BORDER:
791 break;
793 case HtmlOptionId::SDONCLICK:
794 case HtmlOptionId::ONCLICK:
795 case HtmlOptionId::SDONMOUSEOVER:
796 case HtmlOptionId::ONMOUSEOVER:
797 case HtmlOptionId::SDONMOUSEOUT:
798 case HtmlOptionId::ONMOUSEOUT:
799 break;
800 default: break;
802 // All parameters are passed to the applet.
803 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
804 rOption.GetString() );
808 // Objects that are declared only are not evaluated. Moreover, only
809 // Java applets are supported.
810 bool bIsApplet = false;
812 if( !bDeclare && aClassID.getLength() == 42 &&
813 aClassID.startsWith("clsid:") )
815 aClassID = aClassID.copy(6);
816 SvGlobalName aCID;
817 if( aCID.MakeId( aClassID ) )
819 SvGlobalName aJavaCID( 0x8AD9C840UL, 0x044EU, 0x11D1U, 0xB3U, 0xE9U,
820 0x00U, 0x80U, 0x5FU, 0x49U, 0x9DU, 0x93U );
822 bIsApplet = aJavaCID == aCID;
826 if( !bIsApplet )
828 m_pAppletImpl.reset();
829 return;
832 m_pAppletImpl->SetAltText( aStandBy );
834 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
835 SvxCSS1PropertyInfo aPropInfo;
836 if( HasStyleOptions( aStyle, aId, aClass ) )
837 (void)ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
839 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
840 if( !IsNewDoc() )
841 Reader::ResetFrameFormatAttrs( rFrameSet );
843 // set the anchor and the adjustment
844 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
846 // and still the size of the frame
847 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
848 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
849 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
851 #endif
853 void SwHTMLParser::EndObject()
855 #if HAVE_FEATURE_JAVA
856 if( !m_pAppletImpl )
857 return;
858 if( !m_pAppletImpl->CreateApplet( m_sBaseURL ) )
859 return;
861 m_pAppletImpl->FinishApplet();
863 // and insert into the document
864 SwFrameFormat* pFlyFormat =
865 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
866 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
867 &m_pAppletImpl->GetItemSet() );
869 // set the alternative name
870 SwNoTextNode *pNoTextNd =
871 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
872 ->GetIndex()+1 ]->GetNoTextNode();
873 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
875 // if applicable create frames and register auto-bound frames
876 RegisterFlyFrame( pFlyFormat );
878 m_pAppletImpl.reset();
879 #else
880 (void) this; // Silence loplugin:staticmethods
881 #endif
884 #if HAVE_FEATURE_JAVA
885 void SwHTMLParser::InsertApplet()
887 OUString aCodeBase, aCode, aName, aAlt, aId, aStyle, aClass;
888 Size aSize( USHRT_MAX, USHRT_MAX );
889 Size aSpace( 0, 0 );
890 bool bPercentWidth = false, bPercentHeight = false, bMayScript = false;
891 sal_Int16 eVertOri = text::VertOrientation::TOP;
892 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
894 // create a new Command list
895 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
897 const HTMLOptions& rHTMLOptions = GetOptions();
898 for (size_t i = rHTMLOptions.size(); i; )
900 const HTMLOption& rOption = rHTMLOptions[--i];
901 switch( rOption.GetToken() )
903 case HtmlOptionId::ID:
904 aId = rOption.GetString();
905 break;
906 case HtmlOptionId::STYLE:
907 aStyle = rOption.GetString();
908 break;
909 case HtmlOptionId::CLASS:
910 aClass = rOption.GetString();
911 break;
912 case HtmlOptionId::CODEBASE:
913 aCodeBase = rOption.GetString();
914 break;
915 case HtmlOptionId::CODE:
916 aCode = rOption.GetString();
917 break;
918 case HtmlOptionId::NAME:
919 aName = rOption.GetString();
920 break;
921 case HtmlOptionId::ALT:
922 aAlt = rOption.GetString();
923 break;
924 case HtmlOptionId::ALIGN:
925 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
926 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
927 break;
928 case HtmlOptionId::WIDTH:
929 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
930 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
931 break;
932 case HtmlOptionId::HEIGHT:
933 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
934 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
935 break;
936 case HtmlOptionId::HSPACE:
937 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
938 break;
939 case HtmlOptionId::VSPACE:
940 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
941 break;
942 case HtmlOptionId::MAYSCRIPT:
943 bMayScript = true;
944 break;
945 default: break;
948 // All parameters are passed to the applet.
949 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
950 rOption.GetString() );
953 if( aCode.isEmpty() )
955 m_pAppletImpl.reset();
956 return;
959 if ( !aCodeBase.isEmpty() )
960 aCodeBase = INetURLObject::GetAbsURL( m_sBaseURL, aCodeBase );
961 m_pAppletImpl->CreateApplet( aCode, aName, bMayScript, aCodeBase, m_sBaseURL );//, aAlt );
962 m_pAppletImpl->SetAltText( aAlt );
964 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
965 SvxCSS1PropertyInfo aPropInfo;
966 if( HasStyleOptions( aStyle, aId, aClass ) )
967 (void)ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
969 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
970 if( !IsNewDoc() )
971 Reader::ResetFrameFormatAttrs( rFrameSet );
973 // set the anchor and the adjustment
974 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
976 // and still the size or the frame
977 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
978 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
979 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
981 #endif
983 void SwHTMLParser::EndApplet()
985 #if HAVE_FEATURE_JAVA
986 if( !m_pAppletImpl )
987 return;
989 m_pAppletImpl->FinishApplet();
991 // and insert into the document
992 SwFrameFormat* pFlyFormat =
993 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
994 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
995 &m_pAppletImpl->GetItemSet());
997 // set the alternative name
998 SwNoTextNode *pNoTextNd =
999 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
1000 ->GetIndex()+1 ]->GetNoTextNode();
1001 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
1003 // if applicable create frames and register auto-bound frames
1004 RegisterFlyFrame( pFlyFormat );
1006 m_pAppletImpl.reset();
1007 #else
1008 (void) this;
1009 #endif
1012 void SwHTMLParser::InsertParam()
1014 #if HAVE_FEATURE_JAVA
1015 if( !m_pAppletImpl )
1016 return;
1018 OUString aName, aValue;
1020 const HTMLOptions& rHTMLOptions = GetOptions();
1021 for (size_t i = rHTMLOptions.size(); i; )
1023 const HTMLOption& rOption = rHTMLOptions[--i];
1024 switch( rOption.GetToken() )
1026 case HtmlOptionId::NAME:
1027 aName = rOption.GetString();
1028 break;
1029 case HtmlOptionId::VALUE:
1030 aValue = rOption.GetString();
1031 break;
1032 default: break;
1036 if( aName.isEmpty() )
1037 return;
1039 m_pAppletImpl->AppendParam( aName, aValue );
1040 #else
1041 (void) this;
1042 #endif
1045 void SwHTMLParser::InsertFloatingFrame()
1047 OUString aAlt, aId, aStyle, aClass;
1048 Size aSize( USHRT_MAX, USHRT_MAX );
1049 Size aSpace( 0, 0 );
1050 bool bPercentWidth = false, bPercentHeight = false;
1051 sal_Int16 eVertOri = text::VertOrientation::TOP;
1052 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
1054 const HTMLOptions& rHTMLOptions = GetOptions();
1056 // First fetch the options of the Writer-Frame-Format
1057 for (const auto & rOption : rHTMLOptions)
1059 switch( rOption.GetToken() )
1061 case HtmlOptionId::ID:
1062 aId = rOption.GetString();
1063 break;
1064 case HtmlOptionId::STYLE:
1065 aStyle = rOption.GetString();
1066 break;
1067 case HtmlOptionId::CLASS:
1068 aClass = rOption.GetString();
1069 break;
1070 case HtmlOptionId::ALT:
1071 aAlt = rOption.GetString();
1072 break;
1073 case HtmlOptionId::ALIGN:
1074 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
1075 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
1076 break;
1077 case HtmlOptionId::WIDTH:
1078 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
1079 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1080 break;
1081 case HtmlOptionId::HEIGHT:
1082 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
1083 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1084 break;
1085 case HtmlOptionId::HSPACE:
1086 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1087 break;
1088 case HtmlOptionId::VSPACE:
1089 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1090 break;
1091 default: break;
1095 // and now the ones for the SfxFrame
1096 SfxFrameDescriptor aFrameDesc;
1098 SfxFrameHTMLParser::ParseFrameOptions( &aFrameDesc, rHTMLOptions, m_sBaseURL );
1100 // create a floating frame
1101 comphelper::EmbeddedObjectContainer aCnt;
1102 OUString aObjName;
1103 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence(), aObjName );
1107 // TODO/MBA: testing
1108 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1110 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1111 if ( xSet.is() )
1113 const OUString& aName = aFrameDesc.GetName();
1114 ScrollingMode eScroll = aFrameDesc.GetScrollingMode();
1115 bool bHasBorder = aFrameDesc.HasFrameBorder();
1116 Size aMargin = aFrameDesc.GetMargin();
1118 OUString sHRef = aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE );
1120 if (INetURLObject(sHRef).IsExoticProtocol())
1121 NotifyMacroEventRead();
1123 xSet->setPropertyValue(u"FrameURL"_ustr, uno::Any( sHRef ) );
1124 xSet->setPropertyValue(u"FrameName"_ustr, uno::Any( aName ) );
1126 if ( eScroll == ScrollingMode::Auto )
1127 xSet->setPropertyValue(u"FrameIsAutoScroll"_ustr,
1128 uno::Any( true ) );
1129 else
1130 xSet->setPropertyValue(u"FrameIsScrollingMode"_ustr,
1131 uno::Any( eScroll == ScrollingMode::Yes ) );
1133 xSet->setPropertyValue(u"FrameIsBorder"_ustr,
1134 uno::Any( bHasBorder ) );
1136 xSet->setPropertyValue(u"FrameMarginWidth"_ustr,
1137 uno::Any( sal_Int32( aMargin.Width() ) ) );
1139 xSet->setPropertyValue(u"FrameMarginHeight"_ustr,
1140 uno::Any( sal_Int32( aMargin.Height() ) ) );
1144 catch ( uno::Exception& )
1148 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
1149 SvxCSS1PropertyInfo aPropInfo;
1150 if( HasStyleOptions( aStyle, aId, aClass ) )
1151 (void)ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
1153 // fetch the ItemSet
1154 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() );
1155 if( !IsNewDoc() )
1156 Reader::ResetFrameFormatAttrs( aFrameSet );
1158 // set the anchor and the adjustment
1159 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
1161 // and still the size of the frame
1162 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
1163 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
1164 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
1166 // and insert into the document
1167 SwFrameFormat* pFlyFormat =
1168 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
1169 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
1170 &aFrameSet);
1172 // set the alternative name
1173 SwNoTextNode *pNoTextNd =
1174 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
1175 ->GetIndex()+1 ]->GetNoTextNode();
1176 pNoTextNd->SetTitle( aAlt );
1178 // if applicable create frames and register auto-bound frames
1179 RegisterFlyFrame( pFlyFormat );
1181 m_bInFloatingFrame = true;
1183 ++m_nFloatingFrames;
1186 SwHTMLFrameType SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode )
1188 SwHTMLFrameType eType = HTML_FRMTYPE_OLE;
1190 SwOLENode* pOLENode = const_cast<SwOLENode*>(rNode.GetOLENode());
1191 assert(pOLENode && "must exist");
1192 SwOLEObj& rObj = pOLENode->GetOLEObj();
1194 uno::Reference < embed::XClassifiedObject > xClass = rObj.GetOleRef();
1195 SvGlobalName aClass( xClass->getClassID() );
1196 if( aClass == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1198 eType = HTML_FRMTYPE_PLUGIN;
1200 else if( aClass == SvGlobalName( SO3_IFRAME_CLASSID ) )
1202 eType = HTML_FRMTYPE_IFRAME;
1204 #if HAVE_FEATURE_JAVA
1205 else if( aClass == SvGlobalName( SO3_APPLET_CLASSID ) )
1207 eType = HTML_FRMTYPE_APPLET;
1209 #endif
1211 return eType;
1214 SwHTMLWriter& OutHTML_FrameFormatOLENode( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat,
1215 bool bInCntnr )
1217 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1218 SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1219 SwOLENode *pOLENd = rWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1221 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1222 if( !pOLENd )
1223 return rWrt;
1225 SwOLEObj &rObj = pOLENd->GetOLEObj();
1227 uno::Reference < embed::XEmbeddedObject > xObj( rObj.GetOleRef() );
1228 if ( !svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1229 return rWrt;
1231 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1232 bool bHiddenEmbed = false;
1234 if( !xSet.is() )
1236 OSL_FAIL("Unknown Object" );
1237 return rWrt;
1240 HtmlFrmOpts nFrameOpts;
1242 // if possible output a line break before the "object"
1243 if (rWrt.IsLFPossible())
1244 rWrt.OutNewLine( true );
1246 if( !rFrameFormat.GetName().isEmpty() )
1247 rWrt.OutImplicitMark( rFrameFormat.GetName(),
1248 "ole" );
1249 uno::Any aAny;
1250 SvGlobalName aGlobName( xObj->getClassID() );
1251 OStringBuffer sOut("<");
1252 if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1254 // first the plug-in specifics
1255 sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed);
1257 OUString aStr;
1258 OUString aURL;
1259 aAny = xSet->getPropertyValue(u"PluginURL"_ustr);
1260 if( (aAny >>= aStr) && !aStr.isEmpty() )
1262 aURL = rWrt.normalizeURL(aStr, false);
1265 if( !aURL.isEmpty() )
1267 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\"");
1268 rWrt.Strm().WriteOString( sOut );
1269 sOut.setLength(0);
1270 HTMLOutFuncs::Out_String( rWrt.Strm(), aURL );
1271 sOut.append('\"');
1274 OUString aType;
1275 aAny = xSet->getPropertyValue(u"PluginMimeType"_ustr);
1276 if( (aAny >>= aType) && !aType.isEmpty() )
1278 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"");
1279 rWrt.Strm().WriteOString( sOut );
1280 sOut.setLength(0);
1281 HTMLOutFuncs::Out_String( rWrt.Strm(), aType );
1282 sOut.append('\"');
1285 if ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) &&
1286 css::text::WrapTextMode_THROUGH == rFrameFormat.GetSurround().GetSurround() )
1288 // A HIDDEN plug-in
1289 sOut.append(" " OOO_STRING_SW_HTML_O_Hidden);
1290 nFrameOpts = HTML_FRMOPTS_HIDDEN_EMBED;
1291 bHiddenEmbed = true;
1293 else
1295 nFrameOpts = bInCntnr ? HTML_FRMOPTS_EMBED_CNTNR
1296 : HTML_FRMOPTS_EMBED;
1299 else if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1301 // or the applet specifics
1303 sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet);
1305 // CODEBASE
1306 OUString aCd;
1307 aAny = xSet->getPropertyValue(u"AppletCodeBase"_ustr);
1308 if( (aAny >>= aCd) && !aCd.isEmpty() )
1310 OUString sCodeBase(rWrt.normalizeURL(aCd, false));
1311 if( !sCodeBase.isEmpty() )
1313 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\"");
1314 rWrt.Strm().WriteOString( sOut );
1315 sOut.setLength(0);
1316 HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase );
1317 sOut.append('\"');
1321 // CODE
1322 OUString aClass;
1323 aAny = xSet->getPropertyValue(u"AppletCode"_ustr);
1324 aAny >>= aClass;
1325 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_code "=\"");
1326 rWrt.Strm().WriteOString( sOut );
1327 sOut.setLength(0);
1328 HTMLOutFuncs::Out_String( rWrt.Strm(), aClass );
1329 sOut.append('\"');
1331 // NAME
1332 OUString aAppletName;
1333 aAny = xSet->getPropertyValue(u"AppletName"_ustr);
1334 aAny >>= aAppletName;
1335 if( !aAppletName.isEmpty() )
1337 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
1338 rWrt.Strm().WriteOString( sOut );
1339 sOut.setLength(0);
1340 HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName );
1341 sOut.append('\"');
1344 bool bScript = false;
1345 aAny = xSet->getPropertyValue(u"AppletIsScript"_ustr);
1346 aAny >>= bScript;
1347 if( bScript )
1348 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_mayscript);
1350 nFrameOpts = bInCntnr ? HTML_FRMOPTS_APPLET_CNTNR
1351 : HTML_FRMOPTS_APPLET;
1353 else
1355 // or the Floating-Frame specifics
1357 sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe);
1358 rWrt.Strm().WriteOString( sOut );
1359 sOut.setLength(0);
1361 SfxFrameHTMLWriter::Out_FrameDescriptor( rWrt.Strm(), rWrt.GetBaseURL(),
1362 xSet );
1364 nFrameOpts = bInCntnr ? HTML_FRMOPTS_IFRAME_CNTNR
1365 : HTML_FRMOPTS_IFRAME;
1368 rWrt.Strm().WriteOString( sOut );
1369 sOut.setLength(0);
1371 // ALT, WIDTH, HEIGHT, HSPACE, VSPACE, ALIGN
1372 if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1373 nFrameOpts |= HTML_FRMOPTS_OLE_CSS1;
1374 OString aEndTags = rWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts );
1375 if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1376 rWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts );
1378 if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1380 // output the parameters of applets as separate tags
1381 // and write a </APPLET>
1383 uno::Sequence < beans::PropertyValue > aProps;
1384 aAny = xSet->getPropertyValue(u"AppletCommands"_ustr);
1385 aAny >>= aProps;
1387 SvCommandList aCommands;
1388 aCommands.FillFromSequence( aProps );
1389 std::vector<sal_uLong> aParams;
1390 size_t i = aCommands.size();
1391 while( i > 0 )
1393 const SvCommand& rCommand = aCommands[ --i ];
1394 const OUString& rName = rCommand.GetCommand();
1395 SwHtmlOptType nType = SwApplet_Impl::GetOptionType( rName, true );
1396 if( SwHtmlOptType::TAG == nType )
1398 const OUString& rValue = rCommand.GetArgument();
1399 rWrt.Strm().WriteChar( ' ' );
1400 HTMLOutFuncs::Out_String( rWrt.Strm(), rName );
1401 rWrt.Strm().WriteOString( "=\"" );
1402 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteChar( '\"' );
1404 else if( SwHtmlOptType::PARAM == nType )
1406 aParams.push_back( i );
1410 rWrt.Strm().WriteChar( '>' );
1412 rWrt.IncIndentLevel(); // indent the applet content
1414 size_t ii = aParams.size();
1415 while( ii > 0 )
1417 const SvCommand& rCommand = aCommands[ aParams[--ii] ];
1418 const OUString& rName = rCommand.GetCommand();
1419 const OUString& rValue = rCommand.GetArgument();
1420 rWrt.OutNewLine();
1421 sOut.append(
1422 "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param
1423 " " OOO_STRING_SVTOOLS_HTML_O_name
1424 "=\"");
1425 rWrt.Strm().WriteOString( sOut );
1426 sOut.setLength(0);
1427 HTMLOutFuncs::Out_String( rWrt.Strm(), rName );
1428 sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_value "=\"");
1429 rWrt.Strm().WriteOString( sOut );
1430 sOut.setLength(0);
1431 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteOString( "\">" );
1434 rWrt.DecIndentLevel(); // indent the applet content
1435 if( aCommands.size() )
1436 rWrt.OutNewLine();
1437 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet), false );
1439 else if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1441 // write plug-ins parameters as options
1443 uno::Sequence < beans::PropertyValue > aProps;
1444 aAny = xSet->getPropertyValue(u"PluginCommands"_ustr);
1445 aAny >>= aProps;
1447 SvCommandList aCommands;
1448 aCommands.FillFromSequence( aProps );
1449 for( size_t i = 0; i < aCommands.size(); i++ )
1451 const SvCommand& rCommand = aCommands[ i ];
1452 const OUString& rName = rCommand.GetCommand();
1454 if( SwApplet_Impl::GetOptionType( rName, false ) == SwHtmlOptType::TAG )
1456 const OUString& rValue = rCommand.GetArgument();
1457 rWrt.Strm().WriteChar( ' ' );
1458 HTMLOutFuncs::Out_String( rWrt.Strm(), rName );
1459 rWrt.Strm().WriteOString( "=\"" );
1460 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteChar( '\"' );
1463 rWrt.Strm().WriteChar( '>' );
1465 else
1467 // and for Floating-Frames just output another </IFRAME>
1469 rWrt.Strm().WriteChar( '>' );
1470 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe), false );
1473 if( !aEndTags.isEmpty() )
1474 rWrt.Strm().WriteOString( aEndTags );
1476 return rWrt;
1479 static void OutHTMLGraphic(SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, SwOLENode* pOLENd,
1480 const Graphic& rGraphic, bool bObjectOpened, bool bInCntnr)
1482 OUString aGraphicURL;
1483 OUString aMimeType;
1484 if (!rWrt.mbEmbedImages)
1486 const OUString* pTempFileName = rWrt.GetOrigFileName();
1487 if (pTempFileName)
1488 aGraphicURL = *pTempFileName;
1490 OUString aFilterName(u"JPG"_ustr);
1491 XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible;
1493 if (bObjectOpened)
1495 aFilterName = u"PNG"_ustr;
1496 nFlags = XOutFlags::NONE;
1497 aMimeType = u"image/png"_ustr;
1499 if (rGraphic.GetType() == GraphicType::NONE)
1501 // The OLE Object has no replacement image, write a stub.
1502 aGraphicURL = lcl_CalculateFileName(rWrt.GetOrigFileName(), rGraphic, u"png");
1503 osl::File aFile(aGraphicURL);
1504 aFile.open(osl_File_OpenFlag_Create);
1505 aFile.close();
1509 ErrCode nErr = XOutBitmap::WriteGraphic(rGraphic, aGraphicURL, aFilterName, nFlags);
1510 if (nErr) // error, don't write anything
1512 rWrt.m_nWarn = WARN_SWG_POOR_LOAD;
1513 if (bObjectOpened) // Still at least close the tag.
1514 rWrt.Strm().WriteOString(
1515 Concat2View("</" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"));
1516 return;
1518 aGraphicURL = URIHelper::SmartRel2Abs(INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
1519 URIHelper::GetMaybeFileHdl());
1521 HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask : HtmlFrmOpts::GenImgMask;
1522 if (bObjectOpened)
1523 nFlags |= HtmlFrmOpts::Replacement;
1524 HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
1525 OutHTML_ImageStart(aHtml, rWrt, rFrameFormat, aGraphicURL, rGraphic, pOLENd->GetTitle(),
1526 pOLENd->GetTwipSize(), nFlags, "ole", nullptr, aMimeType, true);
1527 OutHTML_ImageEnd(aHtml, rWrt);
1530 static void OutHTMLStartObject(SwHTMLWriter& rWrt, const OUString& rFileName, const OUString& rFileType)
1532 // OutHTMLStartObject is only for own objects
1533 OUString aFileName = rWrt.normalizeURL(rFileName, true);
1535 if (rWrt.IsLFPossible())
1536 rWrt.OutNewLine();
1537 rWrt.Strm().WriteOString(
1538 Concat2View("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object));
1539 rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + "\""));
1540 if (!rFileType.isEmpty())
1541 rWrt.Strm().WriteOString(Concat2View(" type=\"" + rFileType.toUtf8() + "\""));
1542 rWrt.Strm().WriteOString(">");
1543 rWrt.SetLFPossible(true);
1546 static void OutHTMLEndObject(SwHTMLWriter& rWrt)
1548 rWrt.Strm().WriteOString(
1549 Concat2View("</" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"));
1552 static bool TrySaveFormulaAsPDF(SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat,
1553 SwOLENode* pOLENd, bool bWriteReplacementGraphic, bool bInCntnr)
1555 if (!rWrt.mbReqIF)
1556 return false;
1557 if (!rWrt.m_bExportFormulasAsPDF)
1558 return false;
1560 auto xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
1561 *rWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat));
1562 uno::Reference<frame::XStorable> xStorable(xTextContent->getEmbeddedObject(), uno::UNO_QUERY);
1563 uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY);
1564 if (!xServiceInfo)
1565 return false;
1566 if (!xServiceInfo->supportsService(u"com.sun.star.formula.FormulaProperties"_ustr))
1567 return false;
1569 Graphic aGraphic(xTextContent->getReplacementGraphic());
1570 OUString aFileName = lcl_CalculateFileName(rWrt.GetOrigFileName(), aGraphic, u"pdf");
1572 utl::MediaDescriptor aDescr;
1573 aDescr[u"FilterName"_ustr] <<= u"math_pdf_Export"_ustr;
1574 // Properties from starmath/inc/unomodel.hxx
1575 aDescr[u"FilterData"_ustr] <<= comphelper::InitPropertySequence({
1576 { u"TitleRow"_ustr, css::uno::Any(false) },
1577 { u"FormulaText"_ustr, css::uno::Any(false) },
1578 { u"Border"_ustr, css::uno::Any(false) },
1579 { u"PrintFormat"_ustr, css::uno::Any(sal_Int32(1)) }, // PRINT_SIZE_SCALED
1581 xStorable->storeToURL(aFileName, aDescr.getAsConstPropertyValueList());
1583 OutHTMLStartObject(rWrt, aFileName, u"application/pdf"_ustr);
1585 if (bWriteReplacementGraphic)
1586 OutHTMLGraphic(rWrt, rFrameFormat, pOLENd, aGraphic, true, bInCntnr);
1588 OutHTMLEndObject(rWrt);
1590 return true;
1593 SwHTMLWriter& OutHTML_FrameFormatOLENodeGrf( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat,
1594 bool bInCntnr, bool bWriteReplacementGraphic )
1596 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1597 SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1598 SwOLENode *pOLENd = rWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1600 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1601 if( !pOLENd )
1602 return rWrt;
1604 if (rWrt.mbSkipImages)
1606 // If we skip images, embedded objects would be completely lost.
1607 // Instead, try to use the HTML export of the embedded object.
1608 auto xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat));
1609 uno::Reference<frame::XStorable> xStorable(xTextContent->getEmbeddedObject(), uno::UNO_QUERY);
1610 SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrameFormatOLENodeGrf: no embedded object");
1612 // Figure out what is the filter name of the embedded object.
1613 OUString aFilter;
1614 if (uno::Reference<lang::XServiceInfo> xServiceInfo{ xStorable, uno::UNO_QUERY })
1616 if (xServiceInfo->supportsService(u"com.sun.star.sheet.SpreadsheetDocument"_ustr))
1617 aFilter = "HTML (StarCalc)";
1618 else if (xServiceInfo->supportsService(u"com.sun.star.text.TextDocument"_ustr))
1619 aFilter = "HTML (StarWriter)";
1622 if (!aFilter.isEmpty())
1626 // FIXME: exception for the simplest test document, too
1627 SvMemoryStream aStream;
1628 uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
1629 utl::MediaDescriptor aMediaDescriptor;
1630 aMediaDescriptor[u"FilterName"_ustr] <<= aFilter;
1631 aMediaDescriptor[u"FilterOptions"_ustr] <<= u"SkipHeaderFooter"_ustr;
1632 aMediaDescriptor[u"OutputStream"_ustr] <<= xOutputStream;
1633 xStorable->storeToURL(u"private:stream"_ustr, aMediaDescriptor.getAsConstPropertyValueList());
1634 SAL_WARN_IF(aStream.GetSize()>=o3tl::make_unsigned(SAL_MAX_INT32), "sw.html", "Stream can't fit in OString");
1635 OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(aStream.GetSize()));
1636 // Wrap output in a <span> tag to avoid 'HTML parser error: Unexpected end tag: p'
1637 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span));
1638 rWrt.Strm().WriteOString(aData);
1639 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false);
1641 catch ( uno::Exception& )
1646 return rWrt;
1649 if (TrySaveFormulaAsPDF(rWrt, rFrameFormat, pOLENd, bWriteReplacementGraphic, bInCntnr))
1650 return rWrt;
1652 // Missing fallback graphic must not give up exporting the document, and also must produce
1653 // valid output (see OutHTMLGraphic)
1654 const Graphic* pFallbackGraphic = pOLENd->GetGraphic();
1655 Graphic aGraphic(pFallbackGraphic ? *pFallbackGraphic : Graphic());
1657 SwDocShell* pDocSh = rWrt.m_pDoc->GetDocShell();
1658 bool bObjectOpened = false;
1659 OUString aRTFType = u"text/rtf"_ustr;
1660 if (!rWrt.m_aRTFOLEMimeType.isEmpty())
1662 aRTFType = rWrt.m_aRTFOLEMimeType;
1665 if (rWrt.mbXHTML && pDocSh)
1667 // Map native data to an outer <object> element.
1669 // Calculate the file name, which is meant to be the same as the
1670 // replacement image, just with a .ole extension.
1671 OUString aFileName = lcl_CalculateFileName(rWrt.GetOrigFileName(), aGraphic, u"ole");
1673 // Write the data.
1674 SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
1675 uno::Reference<embed::XEmbeddedObject> xEmbeddedObject = rOLEObj.GetOleRef();
1676 OUString aFileType;
1677 SvFileStream aOutStream(aFileName, StreamMode::WRITE);
1678 uno::Reference<io::XActiveDataStreamer> xStreamProvider;
1679 uno::Reference<embed::XEmbedPersist2> xOwnEmbedded;
1680 if (xEmbeddedObject.is())
1682 xStreamProvider.set(xEmbeddedObject, uno::UNO_QUERY);
1683 xOwnEmbedded.set(xEmbeddedObject, uno::UNO_QUERY);
1685 if (xStreamProvider.is())
1687 // Real OLE2 case: OleEmbeddedObject.
1688 uno::Reference<io::XInputStream> xStream(xStreamProvider->getStream(), uno::UNO_QUERY);
1689 if (xStream.is())
1691 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream));
1692 if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd, rFrameFormat))
1694 // Data always wrapped in RTF.
1695 aFileType = aRTFType;
1699 else if (xOwnEmbedded.is())
1701 // Our own embedded object: OCommonEmbeddedObject.
1702 SvxMSExportOLEObjects aOLEExp(0);
1703 // Trigger the load of the OLE object if needed, otherwise we can't
1704 // export it.
1705 pOLENd->GetTwipSize();
1706 SvMemoryStream aMemory;
1707 rtl::Reference<SotStorage> pStorage = new SotStorage(aMemory);
1708 aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage);
1709 pStorage->Commit();
1710 aMemory.Seek(0);
1711 if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd, rFrameFormat))
1713 // Data always wrapped in RTF.
1714 aFileType = aRTFType;
1717 else
1719 // Otherwise the native data is just a grab-bag: ODummyEmbeddedObject.
1720 const OUString& aStreamName = rOLEObj.GetCurrentPersistName();
1721 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
1722 uno::Reference<io::XStream> xInStream;
1725 // Even the native data may be missing.
1726 xInStream = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ);
1727 } catch (const uno::Exception&)
1729 TOOLS_WARN_EXCEPTION("sw.html", "OutHTML_FrameFormatOLENodeGrf: failed to open stream element");
1731 if (xInStream.is())
1733 uno::Reference<io::XStream> xOutStream(new utl::OStreamWrapper(aOutStream));
1734 comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(),
1735 xOutStream->getOutputStream());
1738 uno::Reference<beans::XPropertySet> xOutStreamProps(xInStream, uno::UNO_QUERY);
1739 if (xOutStreamProps.is())
1740 xOutStreamProps->getPropertyValue(u"MediaType"_ustr) >>= aFileType;
1741 if (!aRTFType.isEmpty())
1743 aFileType = aRTFType;
1747 // Refer to this data.
1748 OutHTMLStartObject(rWrt, aFileName, aFileType);
1749 bObjectOpened = true;
1752 if (!bObjectOpened || bWriteReplacementGraphic)
1753 OutHTMLGraphic(rWrt, rFrameFormat, pOLENd, aGraphic, bObjectOpened, bInCntnr);
1755 if (bObjectOpened)
1756 // Close native data.
1757 OutHTMLEndObject(rWrt);
1759 return rWrt;
1762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */