1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <config_java.h>
21
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>
46
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>
69
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>
83
84 using namespace com::sun::star;
85
86 #define HTML_DFLT_EMBED_WIDTH ((MM50*5)/2)
87 #define HTML_DFLT_EMBED_HEIGHT ((MM50*5)/2)
88
89 #define HTML_DFLT_APPLET_WIDTH ((MM50*5)/2)
90 #define HTML_DFLT_APPLET_HEIGHT ((MM50*5)/2)
91
92
93 const HtmlFrmOpts HTML_FRMOPTS_EMBED_ALL =
94 HtmlFrmOpts::Alt |
95 HtmlFrmOpts::Size |
96 HtmlFrmOpts::Name;
97 const HtmlFrmOpts HTML_FRMOPTS_EMBED_CNTNR =
98 HTML_FRMOPTS_EMBED_ALL |
99 HtmlFrmOpts::AbsSize;
100 const HtmlFrmOpts HTML_FRMOPTS_EMBED =
101 HTML_FRMOPTS_EMBED_ALL |
102 HtmlFrmOpts::Align |
103 HtmlFrmOpts::Space |
104 HtmlFrmOpts::BrClear |
105 HtmlFrmOpts::Name;
106 const HtmlFrmOpts HTML_FRMOPTS_HIDDEN_EMBED =
107 HtmlFrmOpts::Alt |
108 HtmlFrmOpts::Name;
109
110 const HtmlFrmOpts HTML_FRMOPTS_APPLET_ALL =
111 HtmlFrmOpts::Alt |
112 HtmlFrmOpts::Size;
113 const HtmlFrmOpts HTML_FRMOPTS_APPLET_CNTNR =
114 HTML_FRMOPTS_APPLET_ALL |
115 HtmlFrmOpts::AbsSize;
116 const HtmlFrmOpts HTML_FRMOPTS_APPLET =
117 HTML_FRMOPTS_APPLET_ALL |
118 HtmlFrmOpts::Align |
119 HtmlFrmOpts::Space |
120 HtmlFrmOpts::BrClear;
121
122 const HtmlFrmOpts HTML_FRMOPTS_IFRAME_ALL =
123 HtmlFrmOpts::Alt |
124 HtmlFrmOpts::Size;
125 const HtmlFrmOpts HTML_FRMOPTS_IFRAME_CNTNR =
126 HTML_FRMOPTS_IFRAME_ALL |
127 HtmlFrmOpts::AbsSize;
128 const HtmlFrmOpts HTML_FRMOPTS_IFRAME =
129 HTML_FRMOPTS_IFRAME_ALL |
130 HtmlFrmOpts::Align |
131 HtmlFrmOpts::Space |
132 HtmlFrmOpts::Border |
133 HtmlFrmOpts::BrClear;
134
135 const HtmlFrmOpts HTML_FRMOPTS_OLE_CSS1 =
136 HtmlFrmOpts::SAlign |
137 HtmlFrmOpts::SSpace;
138
139 namespace
140 {
141 /**
142 * Calculates a filename for an image, provided the HTML file name, the image
143 * itself and a wanted extension.
144 */
lcl_CalculateFileName(const OUString * pOrigFileName,const Graphic & rGraphic,std::u16string_view rExtension)145 OUString lcl_CalculateFileName(const OUString* pOrigFileName, const Graphic& rGraphic,
146 std::u16string_view rExtension)
147 {
148 OUString aFileName;
149
150 if (pOrigFileName)
151 aFileName = *pOrigFileName;
152 INetURLObject aURL(aFileName);
153 OUString aName = aURL.getBase() + "_" +
154 aURL.getExtension() + "_" +
155 OUString::number(rGraphic.GetChecksum(), 16);
156 aURL.setBase(aName);
157 aURL.setExtension(rExtension);
158 aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
159
160 return aFileName;
161 }
162 }
163
SetFixSize(const Size & rPixSize,const Size & rTwipDfltSize,bool bPercentWidth,bool bPercentHeight,SvxCSS1PropertyInfo const & rCSS1PropInfo,SfxItemSet & rFlyItemSet)164 void SwHTMLParser::SetFixSize( const Size& rPixSize,
165 const Size& rTwipDfltSize,
166 bool bPercentWidth, bool bPercentHeight,
167 SvxCSS1PropertyInfo const & rCSS1PropInfo,
168 SfxItemSet& rFlyItemSet )
169 {
170 // convert absolute size values into Twip
171 sal_uInt8 nPercentWidth = 0, nPercentHeight = 0;
172 Size aTwipSz( bPercentWidth || USHRT_MAX==rPixSize.Width() ? 0 : rPixSize.Width(),
173 bPercentHeight || USHRT_MAX==rPixSize.Height() ? 0 : rPixSize.Height() );
174 if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() )
175 {
176 aTwipSz =
177 Application::GetDefaultDevice()->PixelToLogic( aTwipSz,
178 MapMode(MapUnit::MapTwip) );
179 }
180
181 // process width
182 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eWidthType )
183 {
184 nPercentWidth = static_cast<sal_uInt8>(rCSS1PropInfo.m_nWidth);
185 aTwipSz.setWidth( rTwipDfltSize.Width() );
186 }
187 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eWidthType )
188 {
189 aTwipSz.setWidth( rCSS1PropInfo.m_nWidth );
190 }
191 else if( bPercentWidth && rPixSize.Width() )
192 {
193 nPercentWidth = static_cast<sal_uInt8>(rPixSize.Width());
194 if( nPercentWidth > 100 )
195 nPercentWidth = 100;
196
197 aTwipSz.setWidth( rTwipDfltSize.Width() );
198 }
199 else if( USHRT_MAX==rPixSize.Width() )
200 {
201 aTwipSz.setWidth( rTwipDfltSize.Width() );
202 }
203 if( aTwipSz.Width() < MINFLY )
204 {
205 aTwipSz.setWidth( MINFLY );
206 }
207
208 // process height
209 if( SVX_CSS1_LTYPE_PERCENTAGE == rCSS1PropInfo.m_eHeightType )
210 {
211 nPercentHeight = static_cast<sal_uInt8>(rCSS1PropInfo.m_nHeight);
212 aTwipSz.setHeight( rTwipDfltSize.Height() );
213 }
214 else if( SVX_CSS1_LTYPE_TWIP== rCSS1PropInfo.m_eHeightType )
215 {
216 aTwipSz.setHeight( rCSS1PropInfo.m_nHeight );
217 }
218 else if( bPercentHeight && rPixSize.Height() )
219 {
220 nPercentHeight = static_cast<sal_uInt8>(rPixSize.Height());
221 if( nPercentHeight > 100 )
222 nPercentHeight = 100;
223
224 aTwipSz.setHeight( rTwipDfltSize.Height() );
225 }
226 else if( USHRT_MAX==rPixSize.Height() )
227 {
228 aTwipSz.setHeight( rTwipDfltSize.Height() );
229 }
230 if( aTwipSz.Height() < MINFLY )
231 {
232 aTwipSz.setHeight( MINFLY );
233 }
234
235 // set size
236 SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, aTwipSz.Width(), aTwipSz.Height() );
237 aFrameSize.SetWidthPercent( nPercentWidth );
238 aFrameSize.SetHeightPercent( nPercentHeight );
239 rFlyItemSet.Put( aFrameSize );
240 }
241
SetSpace(const Size & rPixSpace,SfxItemSet & rCSS1ItemSet,SvxCSS1PropertyInfo & rCSS1PropInfo,SfxItemSet & rFlyItemSet)242 void SwHTMLParser::SetSpace( const Size& rPixSpace,
243 SfxItemSet& rCSS1ItemSet,
244 SvxCSS1PropertyInfo& rCSS1PropInfo,
245 SfxItemSet& rFlyItemSet )
246 {
247 sal_Int32 nLeftSpace = 0, nRightSpace = 0;
248 sal_uInt16 nUpperSpace = 0, nLowerSpace = 0;
249 if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() )
250 {
251 Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() );
252 aTwipSpc =
253 Application::GetDefaultDevice()->PixelToLogic( aTwipSpc,
254 MapMode(MapUnit::MapTwip) );
255 nLeftSpace = nRightSpace = aTwipSpc.Width();
256 nUpperSpace = nLowerSpace = o3tl::narrowing<sal_uInt16>(aTwipSpc.Height());
257 }
258
259 // set left/right margin
260 const SfxPoolItem *pItem;
261 if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, &pItem ) )
262 {
263 // if applicable remove the first line indent
264 const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem);
265 SvxLRSpaceItem aLRItem( *pLRItem );
266 aLRItem.SetTextFirstLineOffset( 0 );
267 if( rCSS1PropInfo.m_bLeftMargin )
268 {
269 nLeftSpace = aLRItem.GetLeft();
270 rCSS1PropInfo.m_bLeftMargin = false;
271 }
272 if( rCSS1PropInfo.m_bRightMargin )
273 {
274 nRightSpace = aLRItem.GetRight();
275 rCSS1PropInfo.m_bRightMargin = false;
276 }
277 rCSS1ItemSet.ClearItem( RES_LR_SPACE );
278 }
279 if( nLeftSpace > 0 || nRightSpace > 0 )
280 {
281 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
282 aLRItem.SetLeft( std::max<sal_Int32>(nLeftSpace, 0) );
283 aLRItem.SetRight( std::max<sal_Int32>(nRightSpace, 0) );
284 rFlyItemSet.Put( aLRItem );
285 if( nLeftSpace )
286 {
287 const SwFormatHoriOrient& rHoriOri =
288 rFlyItemSet.Get( RES_HORI_ORIENT );
289 if( text::HoriOrientation::NONE == rHoriOri.GetHoriOrient() )
290 {
291 SwFormatHoriOrient aHoriOri( rHoriOri );
292 aHoriOri.SetPos( aHoriOri.GetPos() + nLeftSpace );
293 rFlyItemSet.Put( aHoriOri );
294 }
295 }
296 }
297
298 // set top/bottom margin
299 if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, &pItem ) )
300 {
301 // if applicable remove the first line indent
302 const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem);
303 if( rCSS1PropInfo.m_bTopMargin )
304 {
305 nUpperSpace = pULItem->GetUpper();
306 rCSS1PropInfo.m_bTopMargin = false;
307 }
308 if( rCSS1PropInfo.m_bBottomMargin )
309 {
310 nLowerSpace = pULItem->GetLower();
311 rCSS1PropInfo.m_bBottomMargin = false;
312 }
313 rCSS1ItemSet.ClearItem( RES_UL_SPACE );
314 }
315 if( !(nUpperSpace || nLowerSpace) )
316 return;
317
318 SvxULSpaceItem aULItem( RES_UL_SPACE );
319 aULItem.SetUpper( nUpperSpace );
320 aULItem.SetLower( nLowerSpace );
321 rFlyItemSet.Put( aULItem );
322 if( nUpperSpace )
323 {
324 const SwFormatVertOrient& rVertOri =
325 rFlyItemSet.Get( RES_VERT_ORIENT );
326 if( text::VertOrientation::NONE == rVertOri.GetVertOrient() )
327 {
328 SwFormatVertOrient aVertOri( rVertOri );
329 aVertOri.SetPos( aVertOri.GetPos() + nUpperSpace );
330 rFlyItemSet.Put( aVertOri );
331 }
332 }
333 }
334
StripQueryFromPath(const OUString & rBase,const OUString & rPath)335 OUString SwHTMLParser::StripQueryFromPath(const OUString& rBase, const OUString& rPath)
336 {
337 if (!comphelper::isFileUrl(rBase))
338 return rPath;
339
340 sal_Int32 nIndex = rPath.indexOf('?');
341
342 if (nIndex != -1)
343 return rPath.copy(0, nIndex);
344
345 return rPath;
346 }
347
InsertEmbed()348 bool SwHTMLParser::InsertEmbed()
349 {
350 OUString aURL, aType, aName, aAlt, aId, aStyle, aClass;
351 OUString aData;
352 Size aSize( USHRT_MAX, USHRT_MAX );
353 Size aSpace( USHRT_MAX, USHRT_MAX );
354 bool bPercentWidth = false, bPercentHeight = false, bHidden = false;
355 sal_Int16 eVertOri = text::VertOrientation::NONE;
356 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
357 SvCommandList aCmdLst;
358 const HTMLOptions& rHTMLOptions = GetOptions();
359
360 // The options are read forwards, because the plug-ins expect them in this
361 // order. Still only the first value of an option may be regarded.
362 for (const auto & rOption : rHTMLOptions)
363 {
364 switch( rOption.GetToken() )
365 {
366 case HtmlOptionId::ID:
367 aId = rOption.GetString();
368 break;
369 case HtmlOptionId::STYLE:
370 aStyle = rOption.GetString();
371 break;
372 case HtmlOptionId::CLASS:
373 aClass = rOption.GetString();
374 break;
375 case HtmlOptionId::NAME:
376 aName = rOption.GetString();
377 break;
378 case HtmlOptionId::SRC:
379 if( aURL.isEmpty() )
380 aURL = rOption.GetString();
381 break;
382 case HtmlOptionId::ALT:
383 aAlt = rOption.GetString();
384 break;
385 case HtmlOptionId::TYPE:
386 if( aType.isEmpty() )
387 aType = rOption.GetString();
388 break;
389 case HtmlOptionId::ALIGN:
390 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
391 {
392 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
393 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
394 }
395 break;
396 case HtmlOptionId::WIDTH:
397 if( USHRT_MAX==aSize.Width() )
398 {
399 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
400 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
401 }
402 break;
403 case HtmlOptionId::HEIGHT:
404 if( USHRT_MAX==aSize.Height() )
405 {
406 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
407 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
408 }
409 break;
410 case HtmlOptionId::HSPACE:
411 if( USHRT_MAX==aSpace.Width() )
412 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
413 break;
414 case HtmlOptionId::VSPACE:
415 if( USHRT_MAX==aSpace.Height() )
416 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
417 break;
418 case HtmlOptionId::DATA:
419 if (m_bXHTML && aURL.isEmpty())
420 aData = rOption.GetString();
421 break;
422 case HtmlOptionId::UNKNOWN:
423 if (rOption.GetTokenString().equalsIgnoreAsciiCase(
424 OOO_STRING_SW_HTML_O_Hidden))
425 {
426 bHidden = !rOption.GetString().equalsIgnoreAsciiCase(
427 "FALSE");
428 }
429 break;
430 default: break;
431 }
432
433 // All parameters are passed to the plug-in.
434 aCmdLst.Append( rOption.GetTokenString(), rOption.GetString() );
435 }
436
437 if (aType == "image/png" && m_aEmbeds.empty())
438 // Toplevel <object> for PNG -> that's an image, not an OLE object.
439 return false;
440
441 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
442 SvxCSS1PropertyInfo aPropInfo;
443 if( HasStyleOptions( aStyle, aId, aClass ) )
444 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
445
446 // Convert the default values (except height/width, which is done by SetFrameSize())
447 if( eVertOri==text::VertOrientation::NONE && eHoriOri==text::HoriOrientation::NONE )
448 eVertOri = text::VertOrientation::TOP;
449 if( USHRT_MAX==aSpace.Width() )
450 aSpace.setWidth( 0 );
451 if( USHRT_MAX==aSpace.Height() )
452 aSpace.setHeight( 0 );
453 if( bHidden )
454 {
455 // Size (0,0) will be changed to (MINFLY, MINFLY) in SetFrameSize()
456 aSize.setWidth( 0 ); aSize.setHeight( 0 );
457 aSpace.setWidth( 0 ); aSpace.setHeight( 0 );
458 bPercentWidth = bPercentHeight = false;
459 }
460
461 // prepare the URL
462 INetURLObject aURLObj;
463 bool bHasURL = !aURL.isEmpty() &&
464 aURLObj.SetURL(
465 URIHelper::SmartRel2Abs(
466 INetURLObject(m_sBaseURL), aURL,
467 URIHelper::GetMaybeFileHdl()) );
468 bool bHasData = !aData.isEmpty();
469
470 try
471 {
472 // Strip query and everything after that for file:// URLs, browsers do
473 // the same.
474 aURLObj.SetURL(rtl::Uri::convertRelToAbs(
475 m_sBaseURL, SwHTMLParser::StripQueryFromPath(m_sBaseURL, aData)));
476 }
477 catch (const rtl::MalformedUriException& /*rException*/)
478 {
479 bHasData = false;
480 }
481
482 // do not insert plugin if it has neither URL nor type
483 bool bHasType = !aType.isEmpty();
484 if( !bHasURL && !bHasType && !bHasData )
485 return true;
486
487 if (!m_aEmbeds.empty())
488 {
489 // Nested XHTML <object> element: points to replacement graphic.
490 SwOLENode* pOLENode = m_aEmbeds.top();
491 svt::EmbeddedObjectRef& rObj = pOLENode->GetOLEObj().GetObject();
492 Graphic aGraphic;
493 if (GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aURLObj) != ERRCODE_NONE)
494 return true;
495
496 rObj.SetGraphic(aGraphic, aType);
497
498 // Set the size of the OLE frame to the size of the graphic.
499 OutputDevice* pDevice = Application::GetDefaultDevice();
500 if (aSize.getHeight() == USHRT_MAX || aSize.getWidth() == USHRT_MAX)
501 {
502 Size aPixelSize = aGraphic.GetSizePixel(pDevice);
503 if (aSize.getWidth() == USHRT_MAX)
504 aSize.setWidth(aPixelSize.getWidth());
505 if (aSize.getHeight() == USHRT_MAX)
506 aSize.setHeight(aPixelSize.getHeight());
507 }
508
509 SwFrameFormat* pFormat = pOLENode->GetFlyFormat();
510 if (!pFormat)
511 return true;
512
513 SwAttrSet aAttrSet(pFormat->GetAttrSet());
514 aAttrSet.ClearItem(RES_CNTNT);
515 Size aTwipSize(pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapTwip)));
516 SwFormatFrameSize aFrameSize(SwFrameSize::Fixed, aTwipSize.Width(), aTwipSize.Height());
517 aAttrSet.Put(aFrameSize);
518 pOLENode->GetDoc().SetFlyFrameAttr(*pFormat, aAttrSet);
519 return true;
520 }
521
522 // create the plug-in
523 comphelper::EmbeddedObjectContainer aCnt;
524 OUString aObjName;
525 uno::Reference < embed::XEmbeddedObject > xObj;
526 if (!bHasData)
527 {
528 xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_PLUGIN_CLASSID ).GetByteSequence(), aObjName );
529 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
530 {
531 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
532 if ( xSet.is() )
533 {
534 if( bHasURL )
535 xSet->setPropertyValue("PluginURL", uno::makeAny( aURL ) );
536 if( bHasType )
537 xSet->setPropertyValue("PluginMimeType", uno::makeAny( aType ) );
538
539 uno::Sequence < beans::PropertyValue > aProps;
540 aCmdLst.FillSequence( aProps );
541 xSet->setPropertyValue("PluginCommands", uno::makeAny( aProps ) );
542
543 }
544 }
545 }
546 else if (SwDocShell* pDocSh = m_xDoc->GetDocShell())
547 {
548 // Has non-empty data attribute in XHTML: map that to an OLE object.
549 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
550 aCnt.SwitchPersistence(xStorage);
551 aObjName = aCnt.CreateUniqueObjectName();
552 {
553 SvFileStream aFileStream(aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE),
554 StreamMode::READ);
555 uno::Reference<io::XInputStream> xInStream;
556 SvMemoryStream aMemoryStream;
557
558 // Allow any MIME type that starts with magic, unless a set of allowed types are
559 // specified.
560 auto it = m_aAllowedRTFOLEMimeTypes.find(aType);
561 if (m_aAllowedRTFOLEMimeTypes.empty() || it != m_aAllowedRTFOLEMimeTypes.end())
562 {
563 OString aMagic("{\\object");
564 OString aHeader(read_uInt8s_ToOString(aFileStream, aMagic.getLength()));
565 aFileStream.Seek(0);
566 if (aHeader == aMagic)
567 {
568 // OLE2 wrapped in RTF: either own format or real OLE2 embedding.
569 bool bOwnFormat = false;
570 if (SwReqIfReader::ExtractOleFromRtf(aFileStream, aMemoryStream, bOwnFormat))
571 {
572 xInStream.set(new utl::OStreamWrapper(aMemoryStream));
573 }
574
575 if (bOwnFormat)
576 {
577 uno::Sequence<beans::PropertyValue> aMedium = comphelper::InitPropertySequence(
578 { { "InputStream", uno::makeAny(xInStream) },
579 { "URL", uno::makeAny(OUString("private:stream")) },
580 { "DocumentBaseURL", uno::makeAny(m_sBaseURL) } });
581 xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &m_sBaseURL);
582 }
583 else
584 {
585 // The type is now an OLE2 container, not the original XHTML type.
586 aType = "application/vnd.sun.star.oleobject";
587 }
588 }
589 }
590
591 if (!xInStream.is())
592 // Non-RTF case.
593 xInStream.set(new utl::OStreamWrapper(aFileStream));
594
595 if (!xObj.is())
596 {
597 uno::Reference<io::XStream> xOutStream
598 = xStorage->openStreamElement(aObjName, embed::ElementModes::READWRITE);
599 if (aFileStream.IsOpen())
600 comphelper::OStorageHelper::CopyInputToOutput(xInStream,
601 xOutStream->getOutputStream());
602
603 if (!aType.isEmpty())
604 {
605 // Set media type of the native data.
606 uno::Reference<beans::XPropertySet> xOutStreamProps(xOutStream, uno::UNO_QUERY);
607 if (xOutStreamProps.is())
608 xOutStreamProps->setPropertyValue("MediaType", uno::makeAny(aType));
609 }
610 }
611 xObj = aCnt.GetEmbeddedObject(aObjName);
612 }
613 }
614
615 SfxItemSet aFrameSet( m_xDoc->GetAttrPool(),
616 svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} );
617 if( !IsNewDoc() )
618 Reader::ResetFrameFormatAttrs( aFrameSet );
619
620 // set the anchor
621 if( !bHidden )
622 {
623 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
624 }
625 else
626 {
627 SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA );
628 aAnchor.SetAnchor( m_pPam->GetPoint() );
629 aFrameSet.Put( aAnchor );
630 aFrameSet.Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME) );
631 aFrameSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
632 aFrameSet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::PRINT_AREA ) );
633 }
634
635 // and the size of the frame
636 Size aDfltSz( HTML_DFLT_EMBED_WIDTH, HTML_DFLT_EMBED_HEIGHT );
637 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
638 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
639
640 // and insert into the document
641 uno::Reference<lang::XInitialization> xObjInitialization(xObj, uno::UNO_QUERY);
642 if (xObjInitialization.is())
643 {
644 // Request that the native data of the embedded object is not modified
645 // during parsing.
646 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly",
647 true) };
648 uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) };
649 xObjInitialization->initialize(aArguments);
650 }
651 SwFrameFormat* pFlyFormat =
652 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
653 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
654 &aFrameSet);
655 if (xObjInitialization.is())
656 {
657 uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly",
658 false) };
659 uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) };
660 xObjInitialization->initialize(aArguments);
661 }
662
663 // set name at FrameFormat
664 if( !aName.isEmpty() )
665 pFlyFormat->SetName( aName );
666
667 // set the alternative text
668 SwNoTextNode *pNoTextNd =
669 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
670 ->GetIndex()+1 ]->GetNoTextNode();
671 pNoTextNd->SetTitle( aAlt );
672
673 // if applicable create frames and register auto-bound frames
674 if( !bHidden )
675 {
676 // HIDDEN plug-ins should stay paragraph-bound. Since RegisterFlyFrame()
677 // will change paragraph-bound frames with wrap-through into a
678 // character-bound frame, here we must create the frames by hand.
679 RegisterFlyFrame( pFlyFormat );
680 }
681
682 if (!bHasData)
683 return true;
684
685 SwOLENode* pOLENode = pNoTextNd->GetOLENode();
686 if (!pOLENode)
687 return true;
688
689 m_aEmbeds.push(pOLENode);
690
691 return true;
692 }
693
694 #if HAVE_FEATURE_JAVA
NewObject()695 void SwHTMLParser::NewObject()
696 {
697 OUString aClassID;
698 OUString aStandBy, aId, aStyle, aClass;
699 Size aSize( USHRT_MAX, USHRT_MAX );
700 Size aSpace( 0, 0 );
701 sal_Int16 eVertOri = text::VertOrientation::TOP;
702 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
703
704 bool bPercentWidth = false, bPercentHeight = false,
705 bDeclare = false;
706 // create a new Command list
707 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
708
709 const HTMLOptions& rHTMLOptions = GetOptions();
710 for (size_t i = rHTMLOptions.size(); i; )
711 {
712 const HTMLOption& rOption = rHTMLOptions[--i];
713 switch( rOption.GetToken() )
714 {
715 case HtmlOptionId::ID:
716 aId = rOption.GetString();
717 break;
718 case HtmlOptionId::STYLE:
719 aStyle = rOption.GetString();
720 break;
721 case HtmlOptionId::CLASS:
722 aClass = rOption.GetString();
723 break;
724 case HtmlOptionId::DECLARE:
725 bDeclare = true;
726 break;
727 case HtmlOptionId::CLASSID:
728 aClassID = rOption.GetString();
729 break;
730 case HtmlOptionId::CODEBASE:
731 break;
732 case HtmlOptionId::DATA:
733 break;
734 case HtmlOptionId::TYPE:
735 break;
736 case HtmlOptionId::CODETYPE:
737 break;
738 case HtmlOptionId::ARCHIVE:
739 case HtmlOptionId::UNKNOWN:
740 break;
741 case HtmlOptionId::STANDBY:
742 aStandBy = rOption.GetString();
743 break;
744 case HtmlOptionId::WIDTH:
745 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
746 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
747 break;
748 case HtmlOptionId::HEIGHT:
749 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
750 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
751 break;
752 case HtmlOptionId::ALIGN:
753 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
754 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
755 break;
756 case HtmlOptionId::USEMAP:
757 break;
758 case HtmlOptionId::NAME:
759 break;
760 case HtmlOptionId::HSPACE:
761 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
762 break;
763 case HtmlOptionId::VSPACE:
764 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
765 break;
766 case HtmlOptionId::BORDER:
767 break;
768
769 case HtmlOptionId::SDONCLICK:
770 case HtmlOptionId::ONCLICK:
771 case HtmlOptionId::SDONMOUSEOVER:
772 case HtmlOptionId::ONMOUSEOVER:
773 case HtmlOptionId::SDONMOUSEOUT:
774 case HtmlOptionId::ONMOUSEOUT:
775 break;
776 default: break;
777 }
778 // All parameters are passed to the applet.
779 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
780 rOption.GetString() );
781
782 }
783
784 // Objects that are declared only are not evaluated. Moreover, only
785 // Java applets are supported.
786 bool bIsApplet = false;
787
788 if( !bDeclare && aClassID.getLength() == 42 &&
789 aClassID.startsWith("clsid:") )
790 {
791 aClassID = aClassID.copy(6);
792 SvGlobalName aCID;
793 if( aCID.MakeId( aClassID ) )
794 {
795 SvGlobalName aJavaCID( 0x8AD9C840UL, 0x044EU, 0x11D1U, 0xB3U, 0xE9U,
796 0x00U, 0x80U, 0x5FU, 0x49U, 0x9DU, 0x93U );
797
798 bIsApplet = aJavaCID == aCID;
799 }
800 }
801
802 if( !bIsApplet )
803 {
804 m_pAppletImpl.reset();
805 return;
806 }
807
808 m_pAppletImpl->SetAltText( aStandBy );
809
810 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
811 SvxCSS1PropertyInfo aPropInfo;
812 if( HasStyleOptions( aStyle, aId, aClass ) )
813 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
814
815 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
816 if( !IsNewDoc() )
817 Reader::ResetFrameFormatAttrs( rFrameSet );
818
819 // set the anchor and the adjustment
820 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
821
822 // and still the size of the frame
823 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
824 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
825 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
826 }
827 #endif
828
EndObject()829 void SwHTMLParser::EndObject()
830 {
831 #if HAVE_FEATURE_JAVA
832 if( !m_pAppletImpl )
833 return;
834 if( !m_pAppletImpl->CreateApplet( m_sBaseURL ) )
835 return;
836
837 m_pAppletImpl->FinishApplet();
838
839 // and insert into the document
840 SwFrameFormat* pFlyFormat =
841 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
842 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
843 &m_pAppletImpl->GetItemSet() );
844
845 // set the alternative name
846 SwNoTextNode *pNoTextNd =
847 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
848 ->GetIndex()+1 ]->GetNoTextNode();
849 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
850
851 // if applicable create frames and register auto-bound frames
852 RegisterFlyFrame( pFlyFormat );
853
854 m_pAppletImpl.reset();
855 #else
856 (void) this; // Silence loplugin:staticmethods
857 #endif
858 }
859
860 #if HAVE_FEATURE_JAVA
InsertApplet()861 void SwHTMLParser::InsertApplet()
862 {
863 OUString aCodeBase, aCode, aName, aAlt, aId, aStyle, aClass;
864 Size aSize( USHRT_MAX, USHRT_MAX );
865 Size aSpace( 0, 0 );
866 bool bPercentWidth = false, bPercentHeight = false, bMayScript = false;
867 sal_Int16 eVertOri = text::VertOrientation::TOP;
868 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
869
870 // create a new Command list
871 m_pAppletImpl.reset(new SwApplet_Impl( m_xDoc->GetAttrPool() ));
872
873 const HTMLOptions& rHTMLOptions = GetOptions();
874 for (size_t i = rHTMLOptions.size(); i; )
875 {
876 const HTMLOption& rOption = rHTMLOptions[--i];
877 switch( rOption.GetToken() )
878 {
879 case HtmlOptionId::ID:
880 aId = rOption.GetString();
881 break;
882 case HtmlOptionId::STYLE:
883 aStyle = rOption.GetString();
884 break;
885 case HtmlOptionId::CLASS:
886 aClass = rOption.GetString();
887 break;
888 case HtmlOptionId::CODEBASE:
889 aCodeBase = rOption.GetString();
890 break;
891 case HtmlOptionId::CODE:
892 aCode = rOption.GetString();
893 break;
894 case HtmlOptionId::NAME:
895 aName = rOption.GetString();
896 break;
897 case HtmlOptionId::ALT:
898 aAlt = rOption.GetString();
899 break;
900 case HtmlOptionId::ALIGN:
901 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
902 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
903 break;
904 case HtmlOptionId::WIDTH:
905 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
906 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
907 break;
908 case HtmlOptionId::HEIGHT:
909 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
910 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
911 break;
912 case HtmlOptionId::HSPACE:
913 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
914 break;
915 case HtmlOptionId::VSPACE:
916 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
917 break;
918 case HtmlOptionId::MAYSCRIPT:
919 bMayScript = true;
920 break;
921 default: break;
922 }
923
924 // All parameters are passed to the applet.
925 m_pAppletImpl->AppendParam( rOption.GetTokenString(),
926 rOption.GetString() );
927 }
928
929 if( aCode.isEmpty() )
930 {
931 m_pAppletImpl.reset();
932 return;
933 }
934
935 if ( !aCodeBase.isEmpty() )
936 aCodeBase = INetURLObject::GetAbsURL( m_sBaseURL, aCodeBase );
937 m_pAppletImpl->CreateApplet( aCode, aName, bMayScript, aCodeBase, m_sBaseURL );//, aAlt );
938 m_pAppletImpl->SetAltText( aAlt );
939
940 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
941 SvxCSS1PropertyInfo aPropInfo;
942 if( HasStyleOptions( aStyle, aId, aClass ) )
943 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
944
945 SfxItemSet& rFrameSet = m_pAppletImpl->GetItemSet();
946 if( !IsNewDoc() )
947 Reader::ResetFrameFormatAttrs( rFrameSet );
948
949 // set the anchor and the adjustment
950 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, rFrameSet );
951
952 // and still the size or the frame
953 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
954 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, rFrameSet );
955 SetSpace( aSpace, aItemSet, aPropInfo, rFrameSet );
956 }
957 #endif
958
EndApplet()959 void SwHTMLParser::EndApplet()
960 {
961 #if HAVE_FEATURE_JAVA
962 if( !m_pAppletImpl )
963 return;
964
965 m_pAppletImpl->FinishApplet();
966
967 // and insert into the document
968 SwFrameFormat* pFlyFormat =
969 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
970 ::svt::EmbeddedObjectRef( m_pAppletImpl->GetApplet(), embed::Aspects::MSOLE_CONTENT ),
971 &m_pAppletImpl->GetItemSet());
972
973 // set the alternative name
974 SwNoTextNode *pNoTextNd =
975 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
976 ->GetIndex()+1 ]->GetNoTextNode();
977 pNoTextNd->SetTitle( m_pAppletImpl->GetAltText() );
978
979 // if applicable create frames and register auto-bound frames
980 RegisterFlyFrame( pFlyFormat );
981
982 m_pAppletImpl.reset();
983 #else
984 (void) this;
985 #endif
986 }
987
InsertParam()988 void SwHTMLParser::InsertParam()
989 {
990 #if HAVE_FEATURE_JAVA
991 if( !m_pAppletImpl )
992 return;
993
994 OUString aName, aValue;
995
996 const HTMLOptions& rHTMLOptions = GetOptions();
997 for (size_t i = rHTMLOptions.size(); i; )
998 {
999 const HTMLOption& rOption = rHTMLOptions[--i];
1000 switch( rOption.GetToken() )
1001 {
1002 case HtmlOptionId::NAME:
1003 aName = rOption.GetString();
1004 break;
1005 case HtmlOptionId::VALUE:
1006 aValue = rOption.GetString();
1007 break;
1008 default: break;
1009 }
1010 }
1011
1012 if( aName.isEmpty() )
1013 return;
1014
1015 m_pAppletImpl->AppendParam( aName, aValue );
1016 #else
1017 (void) this;
1018 #endif
1019 }
1020
InsertFloatingFrame()1021 void SwHTMLParser::InsertFloatingFrame()
1022 {
1023 OUString aAlt, aId, aStyle, aClass;
1024 Size aSize( USHRT_MAX, USHRT_MAX );
1025 Size aSpace( 0, 0 );
1026 bool bPercentWidth = false, bPercentHeight = false;
1027 sal_Int16 eVertOri = text::VertOrientation::TOP;
1028 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
1029
1030 const HTMLOptions& rHTMLOptions = GetOptions();
1031
1032 // First fetch the options of the Writer-Frame-Format
1033 for (const auto & rOption : rHTMLOptions)
1034 {
1035 switch( rOption.GetToken() )
1036 {
1037 case HtmlOptionId::ID:
1038 aId = rOption.GetString();
1039 break;
1040 case HtmlOptionId::STYLE:
1041 aStyle = rOption.GetString();
1042 break;
1043 case HtmlOptionId::CLASS:
1044 aClass = rOption.GetString();
1045 break;
1046 case HtmlOptionId::ALT:
1047 aAlt = rOption.GetString();
1048 break;
1049 case HtmlOptionId::ALIGN:
1050 eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri );
1051 eHoriOri = rOption.GetEnum( aHTMLImgHAlignTable, eHoriOri );
1052 break;
1053 case HtmlOptionId::WIDTH:
1054 bPercentWidth = (rOption.GetString().indexOf('%') != -1);
1055 aSize.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1056 break;
1057 case HtmlOptionId::HEIGHT:
1058 bPercentHeight = (rOption.GetString().indexOf('%') != -1);
1059 aSize.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1060 break;
1061 case HtmlOptionId::HSPACE:
1062 aSpace.setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1063 break;
1064 case HtmlOptionId::VSPACE:
1065 aSpace.setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1066 break;
1067 default: break;
1068 }
1069 }
1070
1071 // and now the ones for the SfxFrame
1072 SfxFrameDescriptor aFrameDesc;
1073
1074 SfxFrameHTMLParser::ParseFrameOptions( &aFrameDesc, rHTMLOptions, m_sBaseURL );
1075
1076 // create a floating frame
1077 comphelper::EmbeddedObjectContainer aCnt;
1078 OUString aObjName;
1079 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_IFRAME_CLASSID ).GetByteSequence(), aObjName );
1080
1081 try
1082 {
1083 // TODO/MBA: testing
1084 if ( svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1085 {
1086 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1087 if ( xSet.is() )
1088 {
1089 const OUString& aName = aFrameDesc.GetName();
1090 ScrollingMode eScroll = aFrameDesc.GetScrollingMode();
1091 bool bHasBorder = aFrameDesc.HasFrameBorder();
1092 Size aMargin = aFrameDesc.GetMargin();
1093
1094 xSet->setPropertyValue("FrameURL", uno::makeAny( aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) );
1095 xSet->setPropertyValue("FrameName", uno::makeAny( aName ) );
1096
1097 if ( eScroll == ScrollingMode::Auto )
1098 xSet->setPropertyValue("FrameIsAutoScroll",
1099 uno::makeAny( true ) );
1100 else
1101 xSet->setPropertyValue("FrameIsScrollingMode",
1102 uno::makeAny( eScroll == ScrollingMode::Yes ) );
1103
1104 xSet->setPropertyValue("FrameIsBorder",
1105 uno::makeAny( bHasBorder ) );
1106
1107 xSet->setPropertyValue("FrameMarginWidth",
1108 uno::makeAny( sal_Int32( aMargin.Width() ) ) );
1109
1110 xSet->setPropertyValue("FrameMarginHeight",
1111 uno::makeAny( sal_Int32( aMargin.Height() ) ) );
1112 }
1113 }
1114 }
1115 catch ( uno::Exception& )
1116 {
1117 }
1118
1119 SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() );
1120 SvxCSS1PropertyInfo aPropInfo;
1121 if( HasStyleOptions( aStyle, aId, aClass ) )
1122 ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo );
1123
1124 // fetch the ItemSet
1125 SfxItemSet aFrameSet( m_xDoc->GetAttrPool(),
1126 svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} );
1127 if( !IsNewDoc() )
1128 Reader::ResetFrameFormatAttrs( aFrameSet );
1129
1130 // set the anchor and the adjustment
1131 SetAnchorAndAdjustment( eVertOri, eHoriOri, aPropInfo, aFrameSet );
1132
1133 // and still the size of the frame
1134 Size aDfltSz( HTML_DFLT_APPLET_WIDTH, HTML_DFLT_APPLET_HEIGHT );
1135 SetFixSize( aSize, aDfltSz, bPercentWidth, bPercentHeight, aPropInfo, aFrameSet );
1136 SetSpace( aSpace, aItemSet, aPropInfo, aFrameSet );
1137
1138 // and insert into the document
1139 SwFrameFormat* pFlyFormat =
1140 m_xDoc->getIDocumentContentOperations().InsertEmbObject(*m_pPam,
1141 ::svt::EmbeddedObjectRef(xObj, embed::Aspects::MSOLE_CONTENT),
1142 &aFrameSet);
1143
1144 // set the alternative name
1145 SwNoTextNode *pNoTextNd =
1146 m_xDoc->GetNodes()[ pFlyFormat->GetContent().GetContentIdx()
1147 ->GetIndex()+1 ]->GetNoTextNode();
1148 pNoTextNd->SetTitle( aAlt );
1149
1150 // if applicable create frames and register auto-bound frames
1151 RegisterFlyFrame( pFlyFormat );
1152
1153 m_bInFloatingFrame = true;
1154 }
1155
GuessOLENodeFrameType(const SwNode & rNode)1156 sal_uInt16 SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode )
1157 {
1158 SwOLEObj& rObj = const_cast<SwOLENode*>(rNode.GetOLENode())->GetOLEObj();
1159
1160 SwHTMLFrameType eType = HTML_FRMTYPE_OLE;
1161
1162 uno::Reference < embed::XClassifiedObject > xClass = rObj.GetOleRef();
1163 SvGlobalName aClass( xClass->getClassID() );
1164 if( aClass == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1165 {
1166 eType = HTML_FRMTYPE_PLUGIN;
1167 }
1168 else if( aClass == SvGlobalName( SO3_IFRAME_CLASSID ) )
1169 {
1170 eType = HTML_FRMTYPE_IFRAME;
1171 }
1172 #if HAVE_FEATURE_JAVA
1173 else if( aClass == SvGlobalName( SO3_APPLET_CLASSID ) )
1174 {
1175 eType = HTML_FRMTYPE_APPLET;
1176 }
1177 #endif
1178
1179 return static_cast< sal_uInt16 >(eType);
1180 }
1181
OutHTML_FrameFormatOLENode(Writer & rWrt,const SwFrameFormat & rFrameFormat,bool bInCntnr)1182 Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFormat,
1183 bool bInCntnr )
1184 {
1185 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1186
1187 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1188 sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1189 SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1190
1191 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1192 if( !pOLENd )
1193 return rWrt;
1194
1195 SwOLEObj &rObj = pOLENd->GetOLEObj();
1196
1197 uno::Reference < embed::XEmbeddedObject > xObj( rObj.GetOleRef() );
1198 if ( !svt::EmbeddedObjectRef::TryRunningState( xObj ) )
1199 return rWrt;
1200
1201 uno::Reference < beans::XPropertySet > xSet( xObj->getComponent(), uno::UNO_QUERY );
1202 bool bHiddenEmbed = false;
1203
1204 if( !xSet.is() )
1205 {
1206 OSL_FAIL("Unknown Object" );
1207 return rWrt;
1208 }
1209
1210 HtmlFrmOpts nFrameOpts;
1211
1212 // if possible output a line break before the "object"
1213 if( rHTMLWrt.m_bLFPossible )
1214 rHTMLWrt.OutNewLine( true );
1215
1216 if( !rFrameFormat.GetName().isEmpty() )
1217 rHTMLWrt.OutImplicitMark( rFrameFormat.GetName(),
1218 "ole" );
1219 uno::Any aAny;
1220 SvGlobalName aGlobName( xObj->getClassID() );
1221 OStringBuffer sOut;
1222 sOut.append('<');
1223 if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1224 {
1225 // first the plug-in specifics
1226 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed);
1227
1228 OUString aStr;
1229 OUString aURL;
1230 aAny = xSet->getPropertyValue("PluginURL");
1231 if( (aAny >>= aStr) && !aStr.isEmpty() )
1232 {
1233 aURL = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(),
1234 aStr);
1235 }
1236
1237 if( !aURL.isEmpty() )
1238 {
1239 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\"");
1240 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1241 HTMLOutFuncs::Out_String( rWrt.Strm(), aURL, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1242 sOut.append('\"');
1243 }
1244
1245 OUString aType;
1246 aAny = xSet->getPropertyValue("PluginMimeType");
1247 if( (aAny >>= aType) && !aType.isEmpty() )
1248 {
1249 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"");
1250 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1251 HTMLOutFuncs::Out_String( rWrt.Strm(), aType, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1252 sOut.append('\"');
1253 }
1254
1255 if ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) &&
1256 css::text::WrapTextMode_THROUGH == rFrameFormat.GetSurround().GetSurround() )
1257 {
1258 // A HIDDEN plug-in
1259 sOut.append(' ').append(OOO_STRING_SW_HTML_O_Hidden);
1260 nFrameOpts = HTML_FRMOPTS_HIDDEN_EMBED;
1261 bHiddenEmbed = true;
1262 }
1263 else
1264 {
1265 nFrameOpts = bInCntnr ? HTML_FRMOPTS_EMBED_CNTNR
1266 : HTML_FRMOPTS_EMBED;
1267 }
1268 }
1269 else if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1270 {
1271 // or the applet specifics
1272
1273 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet);
1274
1275 // CODEBASE
1276 OUString aCd;
1277 aAny = xSet->getPropertyValue("AppletCodeBase");
1278 if( (aAny >>= aCd) && !aCd.isEmpty() )
1279 {
1280 OUString sCodeBase( URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aCd) );
1281 if( !sCodeBase.isEmpty() )
1282 {
1283 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\"");
1284 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1285 HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1286 sOut.append('\"');
1287 }
1288 }
1289
1290 // CODE
1291 OUString aClass;
1292 aAny = xSet->getPropertyValue("AppletCode");
1293 aAny >>= aClass;
1294 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_code "=\"");
1295 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1296 HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1297 sOut.append('\"');
1298
1299 // NAME
1300 OUString aAppletName;
1301 aAny = xSet->getPropertyValue("AppletName");
1302 aAny >>= aAppletName;
1303 if( !aAppletName.isEmpty() )
1304 {
1305 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
1306 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1307 HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1308 sOut.append('\"');
1309 }
1310
1311 bool bScript = false;
1312 aAny = xSet->getPropertyValue("AppletIsScript");
1313 aAny >>= bScript;
1314 if( bScript )
1315 sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_mayscript);
1316
1317 nFrameOpts = bInCntnr ? HTML_FRMOPTS_APPLET_CNTNR
1318 : HTML_FRMOPTS_APPLET;
1319 }
1320 else
1321 {
1322 // or the Floating-Frame specifics
1323
1324 sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe);
1325 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1326
1327 SfxFrameHTMLWriter::Out_FrameDescriptor( rWrt.Strm(), rWrt.GetBaseURL(),
1328 xSet,
1329 rHTMLWrt.m_eDestEnc,
1330 &rHTMLWrt.m_aNonConvertableCharacters );
1331
1332 nFrameOpts = bInCntnr ? HTML_FRMOPTS_IFRAME_CNTNR
1333 : HTML_FRMOPTS_IFRAME;
1334 }
1335
1336 rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
1337
1338 // ALT, WIDTH, HEIGHT, HSPACE, VSPACE, ALIGN
1339 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1340 nFrameOpts |= HTML_FRMOPTS_OLE_CSS1;
1341 OString aEndTags = rHTMLWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts );
1342 if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed )
1343 rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts );
1344
1345 if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) )
1346 {
1347 // output the parameters of applets as separate tags
1348 // and write a </APPLET>
1349
1350 uno::Sequence < beans::PropertyValue > aProps;
1351 aAny = xSet->getPropertyValue("AppletCommands");
1352 aAny >>= aProps;
1353
1354 SvCommandList aCommands;
1355 aCommands.FillFromSequence( aProps );
1356 std::vector<sal_uLong> aParams;
1357 size_t i = aCommands.size();
1358 while( i > 0 )
1359 {
1360 const SvCommand& rCommand = aCommands[ --i ];
1361 const OUString& rName = rCommand.GetCommand();
1362 SwHtmlOptType nType = SwApplet_Impl::GetOptionType( rName, true );
1363 if( SwHtmlOptType::TAG == nType )
1364 {
1365 const OUString& rValue = rCommand.GetArgument();
1366 rWrt.Strm().WriteChar( ' ' );
1367 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1368 rWrt.Strm().WriteCharPtr( "=\"" );
1369 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' );
1370 }
1371 else if( SwHtmlOptType::PARAM == nType )
1372 {
1373 aParams.push_back( i );
1374 }
1375 }
1376
1377 rHTMLWrt.Strm().WriteChar( '>' );
1378
1379 rHTMLWrt.IncIndentLevel(); // indent the applet content
1380
1381 size_t ii = aParams.size();
1382 while( ii > 0 )
1383 {
1384 const SvCommand& rCommand = aCommands[ aParams[--ii] ];
1385 const OUString& rName = rCommand.GetCommand();
1386 const OUString& rValue = rCommand.GetArgument();
1387 rHTMLWrt.OutNewLine();
1388 OStringBuffer sBuf;
1389 sBuf.append("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param
1390 " " OOO_STRING_SVTOOLS_HTML_O_name
1391 "=\"");
1392 rWrt.Strm().WriteOString( sBuf.makeStringAndClear() );
1393 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1394 sBuf.append("\" " OOO_STRING_SVTOOLS_HTML_O_value "=\"");
1395 rWrt.Strm().WriteOString( sBuf.makeStringAndClear() );
1396 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteCharPtr( "\">" );
1397 }
1398
1399 rHTMLWrt.DecIndentLevel(); // indent the applet content
1400 if( aCommands.size() )
1401 rHTMLWrt.OutNewLine();
1402 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet), false );
1403 }
1404 else if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) )
1405 {
1406 // write plug-ins parameters as options
1407
1408 uno::Sequence < beans::PropertyValue > aProps;
1409 aAny = xSet->getPropertyValue("PluginCommands");
1410 aAny >>= aProps;
1411
1412 SvCommandList aCommands;
1413 aCommands.FillFromSequence( aProps );
1414 for( size_t i = 0; i < aCommands.size(); i++ )
1415 {
1416 const SvCommand& rCommand = aCommands[ i ];
1417 const OUString& rName = rCommand.GetCommand();
1418
1419 if( SwApplet_Impl::GetOptionType( rName, false ) == SwHtmlOptType::TAG )
1420 {
1421 const OUString& rValue = rCommand.GetArgument();
1422 rWrt.Strm().WriteChar( ' ' );
1423 HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1424 rWrt.Strm().WriteCharPtr( "=\"" );
1425 HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' );
1426 }
1427 }
1428 rHTMLWrt.Strm().WriteChar( '>' );
1429 }
1430 else
1431 {
1432 // and for Floating-Frames just output another </IFRAME>
1433
1434 rHTMLWrt.Strm().WriteChar( '>' );
1435 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe), false );
1436 }
1437
1438 if( !aEndTags.isEmpty() )
1439 rWrt.Strm().WriteOString( aEndTags );
1440
1441 return rWrt;
1442 }
1443
OutHTML_FrameFormatOLENodeGrf(Writer & rWrt,const SwFrameFormat & rFrameFormat,bool bInCntnr)1444 Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrameFormat,
1445 bool bInCntnr )
1446 {
1447 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1448
1449 const SwFormatContent& rFlyContent = rFrameFormat.GetContent();
1450 sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1;
1451 SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode();
1452
1453 OSL_ENSURE( pOLENd, "OLE-Node expected" );
1454 if( !pOLENd )
1455 return rWrt;
1456
1457 if (rHTMLWrt.mbSkipImages)
1458 {
1459 // If we skip images, embedded objects would be completely lost.
1460 // Instead, try to use the HTML export of the embedded object.
1461 uno::Reference<text::XTextContent> xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rHTMLWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat));
1462 uno::Reference<document::XEmbeddedObjectSupplier2> xEmbeddedObjectSupplier(xTextContent, uno::UNO_QUERY);
1463 uno::Reference<frame::XStorable> xStorable(xEmbeddedObjectSupplier->getEmbeddedObject(), uno::UNO_QUERY);
1464 SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrameFormatOLENodeGrf: no embedded object");
1465
1466 // Figure out what is the filter name of the embedded object.
1467 uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY);
1468 OUString aFilter;
1469 if (xServiceInfo.is())
1470 {
1471 if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
1472 aFilter = "HTML (StarCalc)";
1473 else if (xServiceInfo->supportsService("com.sun.star.text.TextDocument"))
1474 aFilter = "HTML (StarWriter)";
1475 }
1476
1477 if (xStorable.is() && !aFilter.isEmpty())
1478 {
1479 try
1480 {
1481 // FIXME: exception for the simplest test document, too
1482 SvMemoryStream aStream;
1483 uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
1484 utl::MediaDescriptor aMediaDescriptor;
1485 aMediaDescriptor["FilterName"] <<= aFilter;
1486 aMediaDescriptor["FilterOptions"] <<= OUString("SkipHeaderFooter");
1487 aMediaDescriptor["OutputStream"] <<= xOutputStream;
1488 xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
1489 SAL_WARN_IF(aStream.GetSize()>=o3tl::make_unsigned(SAL_MAX_INT32), "sw.html", "Stream can't fit in OString");
1490 OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(aStream.GetSize()));
1491 // Wrap output in a <span> tag to avoid 'HTML parser error: Unexpected end tag: p'
1492 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span));
1493 rWrt.Strm().WriteOString(aData);
1494 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false);
1495 }
1496 catch ( uno::Exception& )
1497 {
1498 }
1499 }
1500
1501 return rWrt;
1502 }
1503
1504 if ( !pOLENd->GetGraphic() )
1505 {
1506 SAL_WARN("sw.html", "Unexpected missing OLE fallback graphic");
1507 return rWrt;
1508 }
1509
1510 Graphic aGraphic( *pOLENd->GetGraphic() );
1511
1512 SwDocShell* pDocSh = rHTMLWrt.m_pDoc->GetDocShell();
1513 bool bObjectOpened = false;
1514 OUString aRTFType = "text/rtf";
1515 if (!rHTMLWrt.m_aRTFOLEMimeType.isEmpty())
1516 {
1517 aRTFType = rHTMLWrt.m_aRTFOLEMimeType;
1518 }
1519
1520 if (rHTMLWrt.mbXHTML && pDocSh)
1521 {
1522 // Map native data to an outer <object> element.
1523
1524 // Calculate the file name, which is meant to be the same as the
1525 // replacement image, just with a .ole extension.
1526 OUString aFileName = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"ole");
1527
1528 // Write the data.
1529 SwOLEObj& rOLEObj = pOLENd->GetOLEObj();
1530 uno::Reference<embed::XEmbeddedObject> xEmbeddedObject = rOLEObj.GetOleRef();
1531 OUString aFileType;
1532 SvFileStream aOutStream(aFileName, StreamMode::WRITE);
1533 uno::Reference<io::XActiveDataStreamer> xStreamProvider;
1534 uno::Reference<embed::XEmbedPersist2> xOwnEmbedded;
1535 if (xEmbeddedObject.is())
1536 {
1537 xStreamProvider.set(xEmbeddedObject, uno::UNO_QUERY);
1538 xOwnEmbedded.set(xEmbeddedObject, uno::UNO_QUERY);
1539 }
1540 if (xStreamProvider.is())
1541 {
1542 // Real OLE2 case: OleEmbeddedObject.
1543 uno::Reference<io::XInputStream> xStream(xStreamProvider->getStream(), uno::UNO_QUERY);
1544 if (xStream.is())
1545 {
1546 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream));
1547 if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd, rFrameFormat))
1548 {
1549 // Data always wrapped in RTF.
1550 aFileType = aRTFType;
1551 }
1552 }
1553 }
1554 else if (xOwnEmbedded.is())
1555 {
1556 // Our own embedded object: OCommonEmbeddedObject.
1557 SvxMSExportOLEObjects aOLEExp(0);
1558 // Trigger the load of the OLE object if needed, otherwise we can't
1559 // export it.
1560 pOLENd->GetTwipSize();
1561 SvMemoryStream aMemory;
1562 tools::SvRef<SotStorage> pStorage = new SotStorage(aMemory);
1563 aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage);
1564 pStorage->Commit();
1565 aMemory.Seek(0);
1566 if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd, rFrameFormat))
1567 {
1568 // Data always wrapped in RTF.
1569 aFileType = aRTFType;
1570 }
1571 }
1572 else
1573 {
1574 // Otherwise the native data is just a grab-bag: ODummyEmbeddedObject.
1575 const OUString& aStreamName = rOLEObj.GetCurrentPersistName();
1576 uno::Reference<embed::XStorage> xStorage = pDocSh->GetStorage();
1577 uno::Reference<io::XStream> xInStream;
1578 try
1579 {
1580 // Even the native data may be missing.
1581 xInStream = xStorage->openStreamElement(aStreamName, embed::ElementModes::READ);
1582 } catch (const uno::Exception&)
1583 {
1584 TOOLS_WARN_EXCEPTION("sw.html", "OutHTML_FrameFormatOLENodeGrf: failed to open stream element");
1585 }
1586 if (xInStream.is())
1587 {
1588 uno::Reference<io::XStream> xOutStream(new utl::OStreamWrapper(aOutStream));
1589 comphelper::OStorageHelper::CopyInputToOutput(xInStream->getInputStream(),
1590 xOutStream->getOutputStream());
1591 }
1592
1593 uno::Reference<beans::XPropertySet> xOutStreamProps(xInStream, uno::UNO_QUERY);
1594 if (xOutStreamProps.is())
1595 xOutStreamProps->getPropertyValue("MediaType") >>= aFileType;
1596 if (!aRTFType.isEmpty())
1597 {
1598 aFileType = aRTFType;
1599 }
1600 }
1601 aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName);
1602
1603 // Refer to this data.
1604 if (rHTMLWrt.m_bLFPossible)
1605 rHTMLWrt.OutNewLine();
1606 rWrt.Strm().WriteOString(OString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object));
1607 rWrt.Strm().WriteOString(OString(" data=\"" + aFileName.toUtf8() + "\""));
1608 if (!aFileType.isEmpty())
1609 rWrt.Strm().WriteOString(OString(" type=\"" + aFileType.toUtf8() + "\""));
1610 rWrt.Strm().WriteOString(">");
1611 bObjectOpened = true;
1612 rHTMLWrt.m_bLFPossible = true;
1613 }
1614
1615 OUString aGraphicURL;
1616 OUString aMimeType;
1617 if(!rHTMLWrt.mbEmbedImages)
1618 {
1619 const OUString* pTempFileName = rHTMLWrt.GetOrigFileName();
1620 if(pTempFileName)
1621 aGraphicURL = *pTempFileName;
1622
1623 OUString aFilterName("JPG");
1624 XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible;
1625
1626 if (bObjectOpened)
1627 {
1628 aFilterName = "PNG";
1629 nFlags = XOutFlags::NONE;
1630 aMimeType = "image/png";
1631
1632 if (aGraphic.GetType() == GraphicType::NONE)
1633 {
1634 // The OLE Object has no replacement image, write a stub.
1635 aGraphicURL = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, u"png");
1636 osl::File aFile(aGraphicURL);
1637 aFile.open(osl_File_OpenFlag_Create);
1638 aFile.close();
1639 }
1640 }
1641
1642 ErrCode nErr = XOutBitmap::WriteGraphic( aGraphic, aGraphicURL,
1643 aFilterName,
1644 nFlags );
1645 if( nErr ) // error, don't write anything
1646 {
1647 rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
1648 return rWrt;
1649 }
1650 aGraphicURL = URIHelper::SmartRel2Abs(
1651 INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
1652 URIHelper::GetMaybeFileHdl() );
1653
1654 }
1655 HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask
1656 : HtmlFrmOpts::GenImgMask;
1657 if (bObjectOpened)
1658 nFlags |= HtmlFrmOpts::Replacement;
1659 HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace);
1660 OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic,
1661 pOLENd->GetTitle(), pOLENd->GetTwipSize(),
1662 nFlags, "ole", nullptr, aMimeType );
1663 OutHTML_ImageEnd(aHtml, rWrt);
1664
1665 if (bObjectOpened)
1666 // Close native data.
1667 rWrt.Strm().WriteOString(OString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object
1668 ">"));
1669
1670 return rWrt;
1671 }
1672
1673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1674