check IFrame "FrameURL" target
[LibreOffice.git] / sw / source / filter / html / htmlplug.cxx
blob76e07d63073d51c811ade9ea06d3d053155ba29b
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 <tools/diagnose_ex.h>
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()) && Application::GetDefaultDevice() )
177 aTwipSz =
178 Application::GetDefaultDevice()->PixelToLogic( aTwipSz,
179 MapMode(MapUnit::MapTwip) );
182 // process width
183 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eWidthType )
185 nPercentWidth = static_cast<sal_uInt8>(rCSS1PropInfo.m_nWidth);
186 aTwipSz.setWidth( rTwipDfltSize.Width() );
188 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eWidthType )
190 aTwipSz.setWidth( rCSS1PropInfo.m_nWidth );
192 else if( bPercentWidth && rPixSize.Width() )
194 nPercentWidth = static_cast<sal_uInt8>(rPixSize.Width());
195 if( nPercentWidth > 100 )
196 nPercentWidth = 100;
198 aTwipSz.setWidth( rTwipDfltSize.Width() );
200 else if( USHRT_MAX==rPixSize.Width() )
202 aTwipSz.setWidth( rTwipDfltSize.Width() );
204 if( aTwipSz.Width() < MINFLY )
206 aTwipSz.setWidth( MINFLY );
209 // process height
210 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eHeightType )
212 nPercentHeight = static_cast<sal_uInt8>(rCSS1PropInfo.m_nHeight);
213 aTwipSz.setHeight( rTwipDfltSize.Height() );
215 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eHeightType )
217 aTwipSz.setHeight( rCSS1PropInfo.m_nHeight );
219 else if( bPercentHeight && rPixSize.Height() )
221 nPercentHeight = static_cast<sal_uInt8>(rPixSize.Height());
222 if( nPercentHeight > 100 )
223 nPercentHeight = 100;
225 aTwipSz.setHeight( rTwipDfltSize.Height() );
227 else if( USHRT_MAX==rPixSize.Height() )
229 aTwipSz.setHeight( rTwipDfltSize.Height() );
231 if( aTwipSz.Height() < MINFLY )
233 aTwipSz.setHeight( MINFLY );
236 // set size
237 SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, aTwipSz.Width(), aTwipSz.Height() );
238 aFrameSize.SetWidthPercent( nPercentWidth );
239 aFrameSize.SetHeightPercent( nPercentHeight );
240 rFlyItemSet.Put( aFrameSize );
243 void SwHTMLParser::SetSpace( const Size& rPixSpace,
244 SfxItemSet& rCSS1ItemSet,
245 SvxCSS1PropertyInfo& rCSS1PropInfo,
246 SfxItemSet& rFlyItemSet )
248 sal_Int32 nLeftSpace = 0, nRightSpace = 0;
249 sal_uInt16 nUpperSpace = 0, nLowerSpace = 0;
250 if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() )
252 Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() );
253 aTwipSpc =
254 Application::GetDefaultDevice()->PixelToLogic( aTwipSpc,
255 MapMode(MapUnit::MapTwip) );
256 nLeftSpace = nRightSpace = aTwipSpc.Width();
257 nUpperSpace = nLowerSpace = o3tl::narrowing<sal_uInt16>(aTwipSpc.Height());
260 // set left/right margin
261 const SfxPoolItem *pItem;
262 if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, &pItem ) )
264 // if applicable remove the first line indent
265 const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem);
266 SvxLRSpaceItem aLRItem( *pLRItem );
267 aLRItem.SetTextFirstLineOffset( 0 );
268 if( rCSS1PropInfo.m_bLeftMargin )
270 nLeftSpace = aLRItem.GetLeft();
271 rCSS1PropInfo.m_bLeftMargin = false;
273 if( rCSS1PropInfo.m_bRightMargin )
275 nRightSpace = aLRItem.GetRight();
276 rCSS1PropInfo.m_bRightMargin = false;
278 rCSS1ItemSet.ClearItem( RES_LR_SPACE );
280 if( nLeftSpace > 0 || nRightSpace > 0 )
282 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
283 aLRItem.SetLeft( std::max<sal_Int32>(nLeftSpace, 0) );
284 aLRItem.SetRight( std::max<sal_Int32>(nRightSpace, 0) );
285 rFlyItemSet.Put( aLRItem );
286 if( nLeftSpace )
288 const SwFormatHoriOrient& rHoriOri =
289 rFlyItemSet.Get( RES_HORI_ORIENT );
290 if( text::HoriOrientation::NONE == rHoriOri.GetHoriOrient() )
292 SwFormatHoriOrient aHoriOri( rHoriOri );
293 aHoriOri.SetPos( aHoriOri.GetPos() + nLeftSpace );
294 rFlyItemSet.Put( aHoriOri );
299 // set top/bottom margin
300 if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, &pItem ) )
302 // if applicable remove the first line indent
303 const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem);
304 if( rCSS1PropInfo.m_bTopMargin )
306 nUpperSpace = pULItem->GetUpper();
307 rCSS1PropInfo.m_bTopMargin = false;
309 if( rCSS1PropInfo.m_bBottomMargin )
311 nLowerSpace = pULItem->GetLower();
312 rCSS1PropInfo.m_bBottomMargin = false;
314 rCSS1ItemSet.ClearItem( RES_UL_SPACE );
316 if( !(nUpperSpace || nLowerSpace) )
317 return;
319 SvxULSpaceItem aULItem( RES_UL_SPACE );
320 aULItem.SetUpper( nUpperSpace );
321 aULItem.SetLower( nLowerSpace );
322 rFlyItemSet.Put( aULItem );
323 if( nUpperSpace )
325 const SwFormatVertOrient& rVertOri =
326 rFlyItemSet.Get( RES_VERT_ORIENT );
327 if( text::VertOrientation::NONE == rVertOri.GetVertOrient() )
329 SwFormatVertOrient aVertOri( rVertOri );
330 aVertOri.SetPos( aVertOri.GetPos() + nUpperSpace );
331 rFlyItemSet.Put( aVertOri );
336 OUString SwHTMLParser::StripQueryFromPath(const OUString& rBase, const OUString& rPath)
338 if (!comphelper::isFileUrl(rBase))
339 return rPath;
341 sal_Int32 nIndex = rPath.indexOf('?');
343 if (nIndex != -1)
344 return rPath.copy(0, nIndex);
346 return rPath;
349 bool SwHTMLParser::InsertEmbed()
351 OUString aURL, aType, aName, aAlt, aId, aStyle, aClass;
352 OUString aData;
353 Size aSize( USHRT_MAX, USHRT_MAX );
354 Size aSpace( USHRT_MAX, USHRT_MAX );
355 bool bPercentWidth = false, bPercentHeight = false, bHidden = false;
356 sal_Int16 eVertOri = text::VertOrientation::NONE;
357 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
358 SvCommandList aCmdLst;
359 const HTMLOptions& rHTMLOptions = GetOptions();
361 // The options are read forwards, because the plug-ins expect them in this
362 // order. Still only the first value of an option may be regarded.
363 for (const auto & rOption : rHTMLOptions)
365 switch( rOption.GetToken() )
367 case HtmlOptionId::ID:
368 aId = rOption.GetString();
369 break;
370 case HtmlOptionId::STYLE:
371 aStyle = rOption.GetString();
372 break;
373 case HtmlOptionId::CLASS:
374 aClass = rOption.GetString();
375 break;
376 case HtmlOptionId::NAME:
377 aName = rOption.GetString();
378 break;
379 case HtmlOptionId::SRC:
380 if( aURL.isEmpty() )
381 aURL = rOption.GetString();
382 break;
383 case HtmlOptionId::ALT:
384 aAlt = rOption.GetString();
385 break;
386 case HtmlOptionId::TYPE:
387 if( aType.isEmpty() )
388 aType = rOption.GetString();
389 break;
390 case HtmlOptionId::ALIGN:
391 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
393 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
394 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
396 break;
397 case HtmlOptionId::WIDTH:
398 if( USHRT_MAX==aSize.Width() )
400 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
401 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
403 break;
404 case HtmlOptionId::HEIGHT:
405 if( USHRT_MAX==aSize.Height() )
407 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
408 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
410 break;
411 case HtmlOptionId::HSPACE:
412 if( USHRT_MAX==aSpace.Width() )
413 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
414 break;
415 case HtmlOptionId::VSPACE:
416 if( USHRT_MAX==aSpace.Height() )
417 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
418 break;
419 case HtmlOptionId::DATA:
420 if (m_bXHTML && aURL.isEmpty())
421 aData = rOption.GetString();
422 break;
423 case HtmlOptionId::UNKNOWN:
424 if (rOption.GetTokenString().equalsIgnoreAsciiCase(
425 OOO_STRING_SW_HTML_O_Hidden))
427 bHidden = !rOption.GetString().equalsIgnoreAsciiCase(
428 "FALSE");
430 break;
431 default: break;
434 // All parameters are passed to the plug-in.
435 aCmdLst.Append( rOption.GetTokenString(), rOption.GetString() );
438 static const std::set<std::u16string_view> vAllowlist = {
439 u"image/png",
440 u"image/gif",
441 u"image/x-MS-bmp",
442 u"image/jpeg",
443 u"image/x-wmf",
444 u"image/svg+xml",
445 u"image/tiff",
446 u"image/x-emf",
449 if (vAllowlist.find(aType) != vAllowlist.end() && m_aEmbeds.empty())
451 // Toplevel <object> for an image format -> that's an image, not an OLE object.
452 m_aEmbeds.push(nullptr);
453 return false;
456 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
457 SvxCSS1PropertyInfo aPropInfo;
458 if( HasStyleOptions( aStyle, aId, aClass ) )
459 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
461 // Convert the default values (except height/width, which is done by SetFrameSize())
462 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
463 eVertOri = text::VertOrientation::TOP;
464 if( USHRT_MAX==aSpace.Width() )
465 aSpace.setWidth( 0 );
466 if( USHRT_MAX==aSpace.Height() )
467 aSpace.setHeight( 0 );
468 if( bHidden )
470 // Size (0,0) will be changed to (MINFLY, MINFLY) in SetFrameSize()
471 aSize.setWidth( 0 ); aSize.setHeight( 0 );
472 aSpace.setWidth( 0 ); aSpace.setHeight( 0 );
473 bPercentWidth = bPercentHeight = false;
476 // prepare the URL
477 INetURLObject aURLObj;
478 bool bHasURL = !aURL.isEmpty() &&
479 aURLObj.SetURL(
480 URIHelper::SmartRel2Abs(
481 INetURLObject(m_sBaseURL), aURL,
482 URIHelper::GetMaybeFileHdl()) );
483 bool bHasData = !aData.isEmpty();
487 // Strip query and everything after that for file:// URLs, browsers do
488 // the same.
489 aURLObj.SetURL(rtl::Uri::convertRelToAbs(
490 m_sBaseURL, SwHTMLParser::StripQueryFromPath(m_sBaseURL, aData)));
492 catch (const rtl::MalformedUriException& /*rException*/)
494 bHasData = false;
497 // do not insert plugin if it has neither URL nor type
498 bool bHasType = !aType.isEmpty();
499 if( !bHasURL && !bHasType && !bHasData )
500 return true;
502 if (!m_aEmbeds.empty())
504 // Nested XHTML <object> element: points to replacement graphic.
505 SwOLENode* pOLENode = m_aEmbeds.top();
506 if (!pOLENode)
508 // <object> is mapped to an image -> ignore replacement graphic.
509 return true;
512 svt::EmbeddedObjectRef& rObj = pOLENode->GetOLEObj().GetObject();
513 Graphic aGraphic;
514 if (GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aURLObj) != ERRCODE_NONE)
515 return true;
517 rObj.SetGraphic(aGraphic, aType);
519 // Set the size of the OLE frame to the size of the graphic.
520 SwFrameFormat* pFormat = pOLENode->GetFlyFormat();
521 if (!pFormat)
522 return true;
523 SwAttrSet aAttrSet(pFormat->GetAttrSet());
524 aAttrSet.ClearItem(RES_CNTNT);
525 OutputDevice* pDevice = Application::GetDefaultDevice();
526 Size aDefaultTwipSize(pDevice->PixelToLogic(aGraphic.GetSizePixel(pDevice), MapMode(MapUnit::MapTwip)));
527 SetFixSize(aSize, aDefaultTwipSize, bPercentWidth, bPercentHeight, aPropInfo, aAttrSet);
528 pOLENode->GetDoc().SetFlyFrameAttr(*pFormat, aAttrSet);
529 return true;
532 // create the plug-in
533 comphelper::EmbeddedObjectContainer aCnt;
534 OUString aObjName;
535 uno::Reference < embed::XEmbeddedObject > xObj;
536 if (!bHasData)
538 xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence(), aObjName );
539 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
541 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
542 if ( xSet.is() )
544 if( bHasURL )
545 xSet->setPropertyValue("PluginURL", uno::makeAny( aURL ) );
546 if( bHasType )
547 xSet->setPropertyValue("PluginMimeType", uno::makeAny( aType ) );
549 uno::Sequence < beans::PropertyValue > aProps;
550 aCmdLst.FillSequence( aProps );
551 xSet->setPropertyValue("PluginCommands", uno::makeAny( aProps ) );
556 else if (SwDocShell* pDocSh = m_xDoc->GetDocShell())
558 // Has non-empty data attribute in XHTML: map that to an OLE object.
559 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
560 aCnt.SwitchPersistence(xStorage);
561 aObjName = aCnt.CreateUniqueObjectName();
563 SvFileStream aFileStream(aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE),
564 StreamMode::READ);
565 uno::Reference<io::XInputStream> xInStream;
566 SvMemoryStream aMemoryStream;
568 // Allow any MIME type that starts with magic, unless a set of allowed types are
569 // specified.
570 auto it = m_aAllowedRTFOLEMimeTypes.find(aType);
571 if (m_aAllowedRTFOLEMimeTypes.empty() || it != m_aAllowedRTFOLEMimeTypes.end())
573 OString aMagic("{\\object");
574 OString aHeader(read_uInt8s_ToOString(aFileStream, aMagic.getLength()));
575 aFileStream.Seek(0);
576 if (aHeader == aMagic)
578 // OLE2 wrapped in RTF: either own format or real OLE2 embedding.
579 bool bOwnFormat = false;
580 if (SwReqIfReader::ExtractOleFromRtf(aFileStream, aMemoryStream, bOwnFormat))
582 xInStream.set(new utl::OStreamWrapper(aMemoryStream));
585 if (bOwnFormat)
587 uno::Sequence<beans::PropertyValue> aMedium = comphelper::InitPropertySequence(
588 { { "InputStream", uno::makeAny(xInStream) },
589 { "URL", uno::makeAny(OUString("private:stream")) },
590 { "DocumentBaseURL", uno::makeAny(m_sBaseURL) } });
591 xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &m_sBaseURL);
593 else
595 // The type is now an OLE2 container, not the original XHTML type.
596 aType = "application/vnd.sun.star.oleobject";
601 if (!xInStream.is())
602 // Non-RTF case.
603 xInStream.set(new utl::OStreamWrapper(aFileStream));
605 if (!xObj.is())
607 uno::Reference<io::XStream> xOutStream
608 = xStorage->openStreamElement(aObjName, embed::ElementModes::READWRITE);
609 if (aFileStream.IsOpen())
610 comphelper::OStorageHelper::CopyInputToOutput(xInStream,
611 xOutStream->getOutputStream());
613 if (!aType.isEmpty())
615 // Set media type of the native data.
616 uno::Reference<beans::XPropertySet> xOutStreamProps(xOutStream, uno::UNO_QUERY);
617 if (xOutStreamProps.is())
618 xOutStreamProps->setPropertyValue("MediaType", uno::makeAny(aType));
621 xObj = aCnt.GetEmbeddedObject(aObjName);
625 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() );
626 if( !IsNewDoc() )
627 Reader::ResetFrameFormatAttrs( aFrameSet );
629 // set the anchor
630 if( !bHidden )
632 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
634 else
636 SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA );
637 aAnchor.SetAnchor( m_pPam->GetPoint() );
638 aFrameSet.Put( aAnchor );
639 aFrameSet.Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME) );
640 aFrameSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
641 aFrameSet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) );
644 // and the size of the frame
645 Size aDfltSz( HTML_DFLT_EMBED_WIDTH, HTML_DFLT_EMBED_HEIGHT );
646 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
647 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
649 // and insert into the document
650 uno::Reference<lang::XInitialization> xObjInitialization(xObj, uno::UNO_QUERY);
651 if (xObjInitialization.is())
653 // Request that the native data of the embedded object is not modified
654 // during parsing.
655 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly",
656 true) };
657 uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) };
658 xObjInitialization->initialize(aArguments);
660 SwFrameFormat* pFlyFormat =
661 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
662 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
663 &aFrameSet);
664 if (xObjInitialization.is())
666 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly",
667 false) };
668 uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) };
669 xObjInitialization->initialize(aArguments);
672 // set name at FrameFormat
673 if( !aName.isEmpty() )
674 pFlyFormat->SetName( aName );
676 // set the alternative text
677 SwNoTextNode *pNoTextNd =
678 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
679 ->GetIndex()+1 ]->GetNoTextNode();
680 pNoTextNd->SetTitle( aAlt );
682 // if applicable create frames and register auto-bound frames
683 if( !bHidden )
685 // HIDDEN plug-ins should stay paragraph-bound. Since RegisterFlyFrame()
686 // will change paragraph-bound frames with wrap-through into a
687 // character-bound frame, here we must create the frames by hand.
688 RegisterFlyFrame( pFlyFormat );
691 if (!bHasData)
692 return true;
694 SwOLENode* pOLENode = pNoTextNd->GetOLENode();
695 if (!pOLENode)
696 return true;
698 m_aEmbeds.push(pOLENode);
700 return true;
703 #if HAVE_FEATURE_JAVA
704 void SwHTMLParser::NewObject()
706 OUString aClassID;
707 OUString aStandBy, aId, aStyle, aClass;
708 Size aSize( USHRT_MAX, USHRT_MAX );
709 Size aSpace( 0, 0 );
710 sal_Int16 eVertOri = text::VertOrientation::TOP;
711 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
713 bool bPercentWidth = false, bPercentHeight = false,
714 bDeclare = false;
715 // create a new Command list
716 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
718 const HTMLOptions& rHTMLOptions = GetOptions();
719 for (size_t i = rHTMLOptions.size(); i; )
721 const HTMLOption& rOption = rHTMLOptions[--i];
722 switch( rOption.GetToken() )
724 case HtmlOptionId::ID:
725 aId = rOption.GetString();
726 break;
727 case HtmlOptionId::STYLE:
728 aStyle = rOption.GetString();
729 break;
730 case HtmlOptionId::CLASS:
731 aClass = rOption.GetString();
732 break;
733 case HtmlOptionId::DECLARE:
734 bDeclare = true;
735 break;
736 case HtmlOptionId::CLASSID:
737 aClassID = rOption.GetString();
738 break;
739 case HtmlOptionId::CODEBASE:
740 break;
741 case HtmlOptionId::DATA:
742 break;
743 case HtmlOptionId::TYPE:
744 break;
745 case HtmlOptionId::CODETYPE:
746 break;
747 case HtmlOptionId::ARCHIVE:
748 case HtmlOptionId::UNKNOWN:
749 break;
750 case HtmlOptionId::STANDBY:
751 aStandBy = rOption.GetString();
752 break;
753 case HtmlOptionId::WIDTH:
754 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
755 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
756 break;
757 case HtmlOptionId::HEIGHT:
758 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
759 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
760 break;
761 case HtmlOptionId::ALIGN:
762 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
763 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
764 break;
765 case HtmlOptionId::USEMAP:
766 break;
767 case HtmlOptionId::NAME:
768 break;
769 case HtmlOptionId::HSPACE:
770 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
771 break;
772 case HtmlOptionId::VSPACE:
773 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
774 break;
775 case HtmlOptionId::BORDER:
776 break;
778 case HtmlOptionId::SDONCLICK:
779 case HtmlOptionId::ONCLICK:
780 case HtmlOptionId::SDONMOUSEOVER:
781 case HtmlOptionId::ONMOUSEOVER:
782 case HtmlOptionId::SDONMOUSEOUT:
783 case HtmlOptionId::ONMOUSEOUT:
784 break;
785 default: break;
787 // All parameters are passed to the applet.
788 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
789 rOption.GetString() );
793 // Objects that are declared only are not evaluated. Moreover, only
794 // Java applets are supported.
795 bool bIsApplet = false;
797 if( !bDeclare && aClassID.getLength() == 42 &&
798 aClassID.startsWith("clsid:") )
800 aClassID = aClassID.copy(6);
801 SvGlobalName aCID;
802 if( aCID.MakeId( aClassID ) )
804 SvGlobalName aJavaCID( 0x8AD9C840UL, 0x044EU, 0x11D1U, 0xB3U, 0xE9U,
805 0x00U, 0x80U, 0x5FU, 0x49U, 0x9DU, 0x93U );
807 bIsApplet = aJavaCID == aCID;
811 if( !bIsApplet )
813 m_pAppletImpl.reset();
814 return;
817 m_pAppletImpl->SetAltText( aStandBy );
819 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
820 SvxCSS1PropertyInfo aPropInfo;
821 if( HasStyleOptions( aStyle, aId, aClass ) )
822 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
824 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
825 if( !IsNewDoc() )
826 Reader::ResetFrameFormatAttrs( rFrameSet );
828 // set the anchor and the adjustment
829 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
831 // and still the size of the frame
832 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
833 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
834 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
836 #endif
838 void SwHTMLParser::EndObject()
840 #if HAVE_FEATURE_JAVA
841 if( !m_pAppletImpl )
842 return;
843 if( !m_pAppletImpl->CreateApplet( m_sBaseURL ) )
844 return;
846 m_pAppletImpl->FinishApplet();
848 // and insert into the document
849 SwFrameFormat* pFlyFormat =
850 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
851 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
852 &m_pAppletImpl->GetItemSet() );
854 // set the alternative name
855 SwNoTextNode *pNoTextNd =
856 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
857 ->GetIndex()+1 ]->GetNoTextNode();
858 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
860 // if applicable create frames and register auto-bound frames
861 RegisterFlyFrame( pFlyFormat );
863 m_pAppletImpl.reset();
864 #else
865 (void) this; // Silence loplugin:staticmethods
866 #endif
869 #if HAVE_FEATURE_JAVA
870 void SwHTMLParser::InsertApplet()
872 OUString aCodeBase, aCode, aName, aAlt, aId, aStyle, aClass;
873 Size aSize( USHRT_MAX, USHRT_MAX );
874 Size aSpace( 0, 0 );
875 bool bPercentWidth = false, bPercentHeight = false, bMayScript = false;
876 sal_Int16 eVertOri = text::VertOrientation::TOP;
877 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
879 // create a new Command list
880 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
882 const HTMLOptions& rHTMLOptions = GetOptions();
883 for (size_t i = rHTMLOptions.size(); i; )
885 const HTMLOption& rOption = rHTMLOptions[--i];
886 switch( rOption.GetToken() )
888 case HtmlOptionId::ID:
889 aId = rOption.GetString();
890 break;
891 case HtmlOptionId::STYLE:
892 aStyle = rOption.GetString();
893 break;
894 case HtmlOptionId::CLASS:
895 aClass = rOption.GetString();
896 break;
897 case HtmlOptionId::CODEBASE:
898 aCodeBase = rOption.GetString();
899 break;
900 case HtmlOptionId::CODE:
901 aCode = rOption.GetString();
902 break;
903 case HtmlOptionId::NAME:
904 aName = rOption.GetString();
905 break;
906 case HtmlOptionId::ALT:
907 aAlt = rOption.GetString();
908 break;
909 case HtmlOptionId::ALIGN:
910 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
911 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
912 break;
913 case HtmlOptionId::WIDTH:
914 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
915 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
916 break;
917 case HtmlOptionId::HEIGHT:
918 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
919 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
920 break;
921 case HtmlOptionId::HSPACE:
922 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
923 break;
924 case HtmlOptionId::VSPACE:
925 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
926 break;
927 case HtmlOptionId::MAYSCRIPT:
928 bMayScript = true;
929 break;
930 default: break;
933 // All parameters are passed to the applet.
934 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
935 rOption.GetString() );
938 if( aCode.isEmpty() )
940 m_pAppletImpl.reset();
941 return;
944 if ( !aCodeBase.isEmpty() )
945 aCodeBase = INetURLObject::GetAbsURL( m_sBaseURL, aCodeBase );
946 m_pAppletImpl->CreateApplet( aCode, aName, bMayScript, aCodeBase, m_sBaseURL );//, aAlt );
947 m_pAppletImpl->SetAltText( aAlt );
949 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
950 SvxCSS1PropertyInfo aPropInfo;
951 if( HasStyleOptions( aStyle, aId, aClass ) )
952 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
954 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
955 if( !IsNewDoc() )
956 Reader::ResetFrameFormatAttrs( rFrameSet );
958 // set the anchor and the adjustment
959 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
961 // and still the size or the frame
962 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
963 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
964 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
966 #endif
968 void SwHTMLParser::EndApplet()
970 #if HAVE_FEATURE_JAVA
971 if( !m_pAppletImpl )
972 return;
974 m_pAppletImpl->FinishApplet();
976 // and insert into the document
977 SwFrameFormat* pFlyFormat =
978 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
979 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
980 &m_pAppletImpl->GetItemSet());
982 // set the alternative name
983 SwNoTextNode *pNoTextNd =
984 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
985 ->GetIndex()+1 ]->GetNoTextNode();
986 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
988 // if applicable create frames and register auto-bound frames
989 RegisterFlyFrame( pFlyFormat );
991 m_pAppletImpl.reset();
992 #else
993 (void) this;
994 #endif
997 void SwHTMLParser::InsertParam()
999 #if HAVE_FEATURE_JAVA
1000 if( !m_pAppletImpl )
1001 return;
1003 OUString aName, aValue;
1005 const HTMLOptions& rHTMLOptions = GetOptions();
1006 for (size_t i = rHTMLOptions.size(); i; )
1008 const HTMLOption& rOption = rHTMLOptions[--i];
1009 switch( rOption.GetToken() )
1011 case HtmlOptionId::NAME:
1012 aName = rOption.GetString();
1013 break;
1014 case HtmlOptionId::VALUE:
1015 aValue = rOption.GetString();
1016 break;
1017 default: break;
1021 if( aName.isEmpty() )
1022 return;
1024 m_pAppletImpl->AppendParam( aName, aValue );
1025 #else
1026 (void) this;
1027 #endif
1030 void SwHTMLParser::InsertFloatingFrame()
1032 OUString aAlt, aId, aStyle, aClass;
1033 Size aSize( USHRT_MAX, USHRT_MAX );
1034 Size aSpace( 0, 0 );
1035 bool bPercentWidth = false, bPercentHeight = false;
1036 sal_Int16 eVertOri = text::VertOrientation::TOP;
1037 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
1039 const HTMLOptions& rHTMLOptions = GetOptions();
1041 // First fetch the options of the Writer-Frame-Format
1042 for (const auto & rOption : rHTMLOptions)
1044 switch( rOption.GetToken() )
1046 case HtmlOptionId::ID:
1047 aId = rOption.GetString();
1048 break;
1049 case HtmlOptionId::STYLE:
1050 aStyle = rOption.GetString();
1051 break;
1052 case HtmlOptionId::CLASS:
1053 aClass = rOption.GetString();
1054 break;
1055 case HtmlOptionId::ALT:
1056 aAlt = rOption.GetString();
1057 break;
1058 case HtmlOptionId::ALIGN:
1059 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
1060 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
1061 break;
1062 case HtmlOptionId::WIDTH:
1063 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
1064 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1065 break;
1066 case HtmlOptionId::HEIGHT:
1067 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
1068 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1069 break;
1070 case HtmlOptionId::HSPACE:
1071 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1072 break;
1073 case HtmlOptionId::VSPACE:
1074 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1075 break;
1076 default: break;
1080 // and now the ones for the SfxFrame
1081 SfxFrameDescriptor aFrameDesc;
1083 SfxFrameHTMLParser::ParseFrameOptions( &aFrameDesc, rHTMLOptions, m_sBaseURL );
1085 // create a floating frame
1086 comphelper::EmbeddedObjectContainer aCnt;
1087 OUString aObjName;
1088 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence(), aObjName );
1092 // TODO/MBA: testing
1093 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1095 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1096 if ( xSet.is() )
1098 const OUString& aName = aFrameDesc.GetName();
1099 ScrollingMode eScroll = aFrameDesc.GetScrollingMode();
1100 bool bHasBorder = aFrameDesc.HasFrameBorder();
1101 Size aMargin = aFrameDesc.GetMargin();
1103 OUString sHRef = aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE );
1105 if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro)
1106 NotifyMacroEventRead();
1108 xSet->setPropertyValue("FrameURL", uno::makeAny( sHRef ) );
1109 xSet->setPropertyValue("FrameName", uno::makeAny( aName ) );
1111 if ( eScroll == ScrollingMode::Auto )
1112 xSet->setPropertyValue("FrameIsAutoScroll",
1113 uno::makeAny( true ) );
1114 else
1115 xSet->setPropertyValue("FrameIsScrollingMode",
1116 uno::makeAny( eScroll == ScrollingMode::Yes ) );
1118 xSet->setPropertyValue("FrameIsBorder",
1119 uno::makeAny( bHasBorder ) );
1121 xSet->setPropertyValue("FrameMarginWidth",
1122 uno::makeAny( sal_Int32( aMargin.Width() ) ) );
1124 xSet->setPropertyValue("FrameMarginHeight",
1125 uno::makeAny( sal_Int32( aMargin.Height() ) ) );
1129 catch ( uno::Exception& )
1133 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
1134 SvxCSS1PropertyInfo aPropInfo;
1135 if( HasStyleOptions( aStyle, aId, aClass ) )
1136 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
1138 // fetch the ItemSet
1139 SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() );
1140 if( !IsNewDoc() )
1141 Reader::ResetFrameFormatAttrs( aFrameSet );
1143 // set the anchor and the adjustment
1144 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
1146 // and still the size of the frame
1147 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
1148 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
1149 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
1151 // and insert into the document
1152 SwFrameFormat* pFlyFormat =
1153 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
1154 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
1155 &aFrameSet);
1157 // set the alternative name
1158 SwNoTextNode *pNoTextNd =
1159 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
1160 ->GetIndex()+1 ]->GetNoTextNode();
1161 pNoTextNd->SetTitle( aAlt );
1163 // if applicable create frames and register auto-bound frames
1164 RegisterFlyFrame( pFlyFormat );
1166 m_bInFloatingFrame = true;
1168 ++m_nFloatingFrames;
1171 sal_uInt16 SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode )
1173 SwOLEObj& rObj = const_cast<SwOLENode*>(rNode.GetOLENode())->GetOLEObj();
1175 SwHTMLFrameType eType = HTML_FRMTYPE_OLE;
1177 uno::Reference < embed::XClassifiedObject > xClass = rObj.GetOleRef();
1178 SvGlobalName aClass( xClass->getClassID() );
1179 if( aClass == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1181 eType = HTML_FRMTYPE_PLUGIN;
1183 else if( aClass == SvGlobalName( SO3_IFRAME_CLASSID ) )
1185 eType = HTML_FRMTYPE_IFRAME;
1187 #if HAVE_FEATURE_JAVA
1188 else if( aClass == SvGlobalName( SO3_APPLET_CLASSID ) )
1190 eType = HTML_FRMTYPE_APPLET;
1192 #endif
1194 return static_cast< sal_uInt16 >(eType);
1197 Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFormat,
1198 bool bInCntnr )
1200 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1202 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1203 SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1204 SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1206 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1207 if( !pOLENd )
1208 return rWrt;
1210 SwOLEObj &rObj = pOLENd->GetOLEObj();
1212 uno::Reference < embed::XEmbeddedObject > xObj( rObj.GetOleRef() );
1213 if ( !svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1214 return rWrt;
1216 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1217 bool bHiddenEmbed = false;
1219 if( !xSet.is() )
1221 OSL_FAIL("Unknown Object" );
1222 return rWrt;
1225 HtmlFrmOpts nFrameOpts;
1227 // if possible output a line break before the "object"
1228 if( rHTMLWrt.m_bLFPossible )
1229 rHTMLWrt.OutNewLine( true );
1231 if( !rFrameFormat.GetName().isEmpty() )
1232 rHTMLWrt.OutImplicitMark( rFrameFormat.GetName(),
1233 "ole" );
1234 uno::Any aAny;
1235 SvGlobalName aGlobName( xObj->getClassID() );
1236 OStringBuffer sOut;
1237 sOut.append('<');
1238 if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1240 // first the plug-in specifics
1241 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed);
1243 OUString aStr;
1244 OUString aURL;
1245 aAny = xSet->getPropertyValue("PluginURL");
1246 if( (aAny >>= aStr) && !aStr.isEmpty() )
1248 aURL = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(),
1249 aStr);
1252 if( !aURL.isEmpty() )
1254 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\"");
1255 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1256 HTMLOutFuncs::Out_String( rWrt.Strm(), aURL, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1257 sOut.append('\"');
1260 OUString aType;
1261 aAny = xSet->getPropertyValue("PluginMimeType");
1262 if( (aAny >>= aType) && !aType.isEmpty() )
1264 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"");
1265 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1266 HTMLOutFuncs::Out_String( rWrt.Strm(), aType, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1267 sOut.append('\"');
1270 if ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) &&
1271 css::text::WrapTextMode_THROUGH == rFrameFormat.GetSurround().GetSurround() )
1273 // A HIDDEN plug-in
1274 sOut.append(' ').append(OOO_STRING_SW_HTML_O_Hidden);
1275 nFrameOpts = HTML_FRMOPTS_HIDDEN_EMBED;
1276 bHiddenEmbed = true;
1278 else
1280 nFrameOpts = bInCntnr ? HTML_FRMOPTS_EMBED_CNTNR
1281 : HTML_FRMOPTS_EMBED;
1284 else if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1286 // or the applet specifics
1288 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet);
1290 // CODEBASE
1291 OUString aCd;
1292 aAny = xSet->getPropertyValue("AppletCodeBase");
1293 if( (aAny >>= aCd) && !aCd.isEmpty() )
1295 OUString sCodeBase( URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aCd) );
1296 if( !sCodeBase.isEmpty() )
1298 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\"");
1299 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1300 HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1301 sOut.append('\"');
1305 // CODE
1306 OUString aClass;
1307 aAny = xSet->getPropertyValue("AppletCode");
1308 aAny >>= aClass;
1309 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_code "=\"");
1310 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1311 HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1312 sOut.append('\"');
1314 // NAME
1315 OUString aAppletName;
1316 aAny = xSet->getPropertyValue("AppletName");
1317 aAny >>= aAppletName;
1318 if( !aAppletName.isEmpty() )
1320 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
1321 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1322 HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1323 sOut.append('\"');
1326 bool bScript = false;
1327 aAny = xSet->getPropertyValue("AppletIsScript");
1328 aAny >>= bScript;
1329 if( bScript )
1330 sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_mayscript);
1332 nFrameOpts = bInCntnr ? HTML_FRMOPTS_APPLET_CNTNR
1333 : HTML_FRMOPTS_APPLET;
1335 else
1337 // or the Floating-Frame specifics
1339 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe);
1340 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1342 SfxFrameHTMLWriter::Out_FrameDescriptor( rWrt.Strm(), rWrt.GetBaseURL(),
1343 xSet,
1344 rHTMLWrt.m_eDestEnc,
1345 &rHTMLWrt.m_aNonConvertableCharacters );
1347 nFrameOpts = bInCntnr ? HTML_FRMOPTS_IFRAME_CNTNR
1348 : HTML_FRMOPTS_IFRAME;
1351 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1353 // ALT, WIDTH, HEIGHT, HSPACE, VSPACE, ALIGN
1354 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1355 nFrameOpts |= HTML_FRMOPTS_OLE_CSS1;
1356 OString aEndTags = rHTMLWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts );
1357 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1358 rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts );
1360 if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1362 // output the parameters of applets as separate tags
1363 // and write a </APPLET>
1365 uno::Sequence < beans::PropertyValue > aProps;
1366 aAny = xSet->getPropertyValue("AppletCommands");
1367 aAny >>= aProps;
1369 SvCommandList aCommands;
1370 aCommands.FillFromSequence( aProps );
1371 std::vector<sal_uLong> aParams;
1372 size_t i = aCommands.size();
1373 while( i > 0 )
1375 const SvCommand& rCommand = aCommands[ --i ];
1376 const OUString& rName = rCommand.GetCommand();
1377 SwHtmlOptType nType = SwApplet_Impl::GetOptionType( rName, true );
1378 if( SwHtmlOptType::TAG == nType )
1380 const OUString& rValue = rCommand.GetArgument();
1381 rWrt.Strm().WriteChar( ' ' );
1382 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1383 rWrt.Strm().WriteCharPtr( "=\"" );
1384 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' );
1386 else if( SwHtmlOptType::PARAM == nType )
1388 aParams.push_back( i );
1392 rHTMLWrt.Strm().WriteChar( '>' );
1394 rHTMLWrt.IncIndentLevel(); // indent the applet content
1396 size_t ii = aParams.size();
1397 while( ii > 0 )
1399 const SvCommand& rCommand = aCommands[ aParams[--ii] ];
1400 const OUString& rName = rCommand.GetCommand();
1401 const OUString& rValue = rCommand.GetArgument();
1402 rHTMLWrt.OutNewLine();
1403 OStringBuffer sBuf;
1404 sBuf.append("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param
1405 " " OOO_STRING_SVTOOLS_HTML_O_name
1406 "=\"");
1407 rWrt.Strm().WriteOString( sBuf.makeStringAndClear() );
1408 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1409 sBuf.append("\" " OOO_STRING_SVTOOLS_HTML_O_value "=\"");
1410 rWrt.Strm().WriteOString( sBuf.makeStringAndClear() );
1411 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteCharPtr( "\">" );
1414 rHTMLWrt.DecIndentLevel(); // indent the applet content
1415 if( aCommands.size() )
1416 rHTMLWrt.OutNewLine();
1417 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet), false );
1419 else if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1421 // write plug-ins parameters as options
1423 uno::Sequence < beans::PropertyValue > aProps;
1424 aAny = xSet->getPropertyValue("PluginCommands");
1425 aAny >>= aProps;
1427 SvCommandList aCommands;
1428 aCommands.FillFromSequence( aProps );
1429 for( size_t i = 0; i < aCommands.size(); i++ )
1431 const SvCommand& rCommand = aCommands[ i ];
1432 const OUString& rName = rCommand.GetCommand();
1434 if( SwApplet_Impl::GetOptionType( rName, false ) == SwHtmlOptType::TAG )
1436 const OUString& rValue = rCommand.GetArgument();
1437 rWrt.Strm().WriteChar( ' ' );
1438 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1439 rWrt.Strm().WriteCharPtr( "=\"" );
1440 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' );
1443 rHTMLWrt.Strm().WriteChar( '>' );
1445 else
1447 // and for Floating-Frames just output another </IFRAME>
1449 rHTMLWrt.Strm().WriteChar( '>' );
1450 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe), false );
1453 if( !aEndTags.isEmpty() )
1454 rWrt.Strm().WriteOString( aEndTags );
1456 return rWrt;
1459 Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrameFormat,
1460 bool bInCntnr )
1462 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1464 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1465 SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1466 SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1468 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1469 if( !pOLENd )
1470 return rWrt;
1472 if (rHTMLWrt.mbSkipImages)
1474 // If we skip images, embedded objects would be completely lost.
1475 // Instead, try to use the HTML export of the embedded object.
1476 uno::Reference<text::XTextContent> xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rHTMLWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat));
1477 uno::Reference<document::XEmbeddedObjectSupplier2> xEmbeddedObjectSupplier(xTextContent, uno::UNO_QUERY);
1478 uno::Reference<frame::XStorable> xStorable(xEmbeddedObjectSupplier->getEmbeddedObject(), uno::UNO_QUERY);
1479 SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrameFormatOLENodeGrf: no embedded object");
1481 // Figure out what is the filter name of the embedded object.
1482 uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY);
1483 OUString aFilter;
1484 if (xServiceInfo.is())
1486 if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
1487 aFilter = "HTML (StarCalc)";
1488 else if (xServiceInfo->supportsService("com.sun.star.text.TextDocument"))
1489 aFilter = "HTML (StarWriter)";
1492 if (xStorable.is() && !aFilter.isEmpty())
1496 // FIXME: exception for the simplest test document, too
1497 SvMemoryStream aStream;
1498 uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
1499 utl::MediaDescriptor aMediaDescriptor;
1500 aMediaDescriptor["FilterName"] <<= aFilter;
1501 aMediaDescriptor["FilterOptions"] <<= OUString("SkipHeaderFooter");
1502 aMediaDescriptor["OutputStream"] <<= xOutputStream;
1503 xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
1504 SAL_WARN_IF(aStream.GetSize()>=o3tl::make_unsigned(SAL_MAX_INT32), "sw.html", "Stream can't fit in OString");
1505 OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(aStream.GetSize()));
1506 // Wrap output in a <span> tag to avoid 'HTML parser error: Unexpected end tag: p'
1507 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span));
1508 rWrt.Strm().WriteOString(aData);
1509 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false);
1511 catch ( uno::Exception& )
1516 return rWrt;
1519 if ( !pOLENd->GetGraphic() )
1521 SAL_WARN("sw.html", "Unexpected missing OLE fallback graphic");
1522 return rWrt;
1525 Graphic aGraphic( *pOLENd->GetGraphic() );
1527 SwDocShell* pDocSh = rHTMLWrt.m_pDoc->GetDocShell();
1528 bool bObjectOpened = false;
1529 OUString aRTFType = "text/rtf";
1530 if (!rHTMLWrt.m_aRTFOLEMimeType.isEmpty())
1532 aRTFType = rHTMLWrt.m_aRTFOLEMimeType;
1535 if (rHTMLWrt.mbXHTML && pDocSh)
1537 // Map native data to an outer <object> element.
1539 // Calculate the file name, which is meant to be the same as the
1540 // replacement image, just with a .ole extension.
1541 OUString aFileName = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"ole");
1543 // Write the data.
1544 SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
1545 uno::Reference<embed::XEmbeddedObject> xEmbeddedObject = rOLEObj.GetOleRef();
1546 OUString aFileType;
1547 SvFileStream aOutStream(aFileName, StreamMode::WRITE);
1548 uno::Reference<io::XActiveDataStreamer> xStreamProvider;
1549 uno::Reference<embed::XEmbedPersist2> xOwnEmbedded;
1550 if (xEmbeddedObject.is())
1552 xStreamProvider.set(xEmbeddedObject, uno::UNO_QUERY);
1553 xOwnEmbedded.set(xEmbeddedObject, uno::UNO_QUERY);
1555 if (xStreamProvider.is())
1557 // Real OLE2 case: OleEmbeddedObject.
1558 uno::Reference<io::XInputStream> xStream(xStreamProvider->getStream(), uno::UNO_QUERY);
1559 if (xStream.is())
1561 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream));
1562 if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd, rFrameFormat))
1564 // Data always wrapped in RTF.
1565 aFileType = aRTFType;
1569 else if (xOwnEmbedded.is())
1571 // Our own embedded object: OCommonEmbeddedObject.
1572 SvxMSExportOLEObjects aOLEExp(0);
1573 // Trigger the load of the OLE object if needed, otherwise we can't
1574 // export it.
1575 pOLENd->GetTwipSize();
1576 SvMemoryStream aMemory;
1577 tools::SvRef<SotStorage> pStorage = new SotStorage(aMemory);
1578 aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage);
1579 pStorage->Commit();
1580 aMemory.Seek(0);
1581 if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd, rFrameFormat))
1583 // Data always wrapped in RTF.
1584 aFileType = aRTFType;
1587 else
1589 // Otherwise the native data is just a grab-bag: ODummyEmbeddedObject.
1590 const OUString& aStreamName = rOLEObj.GetCurrentPersistName();
1591 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
1592 uno::Reference<io::XStream> xInStream;
1595 // Even the native data may be missing.
1596 xInStream = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ);
1597 } catch (const uno::Exception&)
1599 TOOLS_WARN_EXCEPTION("sw.html", "OutHTML_FrameFormatOLENodeGrf: failed to open stream element");
1601 if (xInStream.is())
1603 uno::Reference<io::XStream> xOutStream(new utl::OStreamWrapper(aOutStream));
1604 comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(),
1605 xOutStream->getOutputStream());
1608 uno::Reference<beans::XPropertySet> xOutStreamProps(xInStream, uno::UNO_QUERY);
1609 if (xOutStreamProps.is())
1610 xOutStreamProps->getPropertyValue("MediaType") >>= aFileType;
1611 if (!aRTFType.isEmpty())
1613 aFileType = aRTFType;
1616 aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName);
1618 // Refer to this data.
1619 if (rHTMLWrt.m_bLFPossible)
1620 rHTMLWrt.OutNewLine();
1621 rWrt.Strm().WriteOString(OStringConcatenation("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object));
1622 rWrt.Strm().WriteOString(OStringConcatenation(" data=\"" + aFileName.toUtf8() + "\""));
1623 if (!aFileType.isEmpty())
1624 rWrt.Strm().WriteOString(OStringConcatenation(" type=\"" + aFileType.toUtf8() + "\""));
1625 rWrt.Strm().WriteOString(">");
1626 bObjectOpened = true;
1627 rHTMLWrt.m_bLFPossible = true;
1630 OUString aGraphicURL;
1631 OUString aMimeType;
1632 if(!rHTMLWrt.mbEmbedImages)
1634 const OUString* pTempFileName = rHTMLWrt.GetOrigFileName();
1635 if(pTempFileName)
1636 aGraphicURL = *pTempFileName;
1638 OUString aFilterName("JPG");
1639 XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible;
1641 if (bObjectOpened)
1643 aFilterName = "PNG";
1644 nFlags = XOutFlags::NONE;
1645 aMimeType = "image/png";
1647 if (aGraphic.GetType() == GraphicType::NONE)
1649 // The OLE Object has no replacement image, write a stub.
1650 aGraphicURL = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"png");
1651 osl::File aFile(aGraphicURL);
1652 aFile.open(osl_File_OpenFlag_Create);
1653 aFile.close();
1657 ErrCode nErr = XOutBitmap::WriteGraphic( aGraphic, aGraphicURL,
1658 aFilterName,
1659 nFlags );
1660 if( nErr ) // error, don't write anything
1662 rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
1663 return rWrt;
1665 aGraphicURL = URIHelper::SmartRel2Abs(
1666 INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
1667 URIHelper::GetMaybeFileHdl() );
1670 HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask
1671 : HtmlFrmOpts::GenImgMask;
1672 if (bObjectOpened)
1673 nFlags |= HtmlFrmOpts::Replacement;
1674 HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
1675 OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic,
1676 pOLENd->GetTitle(), pOLENd->GetTwipSize(),
1677 nFlags, "ole", nullptr, aMimeType );
1678 OutHTML_ImageEnd(aHtml, rWrt);
1680 if (bObjectOpened)
1681 // Close native data.
1682 rWrt.Strm().WriteOString(OStringConcatenation("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object
1683 ">"));
1685 return rWrt;
1688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */