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 <svx/unomodel.hxx>
21 #include <svx/fmmodel.hxx>
22 #include <galobj.hxx>
23 #include <svx/gallerybinaryengine.hxx>
24 #include <svx/galleryobjectcollection.hxx>
25 #include <svx/gallery1.hxx>
26 #include <galleryobjectbinarystorage.hxx>
27 #include <osl/thread.hxx>
28 #include "codec.hxx"
29 #include "gallerydrawmodel.hxx"
30 #include <vcl/cvtgrf.hxx>
31 
32 #include <sal/log.hxx>
33 
34 #include <com/sun/star/ucb/ContentCreationException.hpp>
35 #include <com/sun/star/sdbc/XResultSet.hpp>
36 #include <com/sun/star/ucb/XContentAccess.hpp>
37 #include <comphelper/fileformat.h>
38 #include <comphelper/graphicmimetype.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <tools/urlobj.hxx>
41 #include <tools/diagnose_ex.h>
42 #include <tools/datetime.hxx>
43 #include <unotools/datetime.hxx>
44 #include <unotools/ucbstreamhelper.hxx>
45 #include <unotools/streamwrap.hxx>
46 #include <unotools/tempfile.hxx>
47 #include <ucbhelper/content.hxx>
48 #include <tools/vcompat.hxx>
49 
50 using namespace ::com::sun::star;
51 
GalleryBinaryEngine(const GalleryBinaryStorageLocations & rGalleryBinaryStorageLocations,GalleryObjectCollection & rGalleryObjectCollection,bool bReadOnly)52 GalleryBinaryEngine::GalleryBinaryEngine(
53     const GalleryBinaryStorageLocations& rGalleryBinaryStorageLocations,
54     GalleryObjectCollection& rGalleryObjectCollection, bool bReadOnly)
55     : maGalleryStorageLocations(rGalleryBinaryStorageLocations)
56     , mrGalleryObjectCollection(rGalleryObjectCollection)
57     , mbReadOnly(bReadOnly)
58     , m_bDestDirRelative(false)
59 {
60     ImplCreateSvDrawStorage();
61 }
62 
~GalleryBinaryEngine()63 GalleryBinaryEngine::~GalleryBinaryEngine() { clearSotStorage(); }
64 
setDestDir(const OUString & rDestDir,bool bRelative)65 void GalleryBinaryEngine::setDestDir(const OUString& rDestDir, bool bRelative)
66 {
67     m_aDestDir = rDestDir;
68     m_bDestDirRelative = bRelative;
69 }
70 
clearSotStorage()71 void GalleryBinaryEngine::clearSotStorage() { m_aSvDrawStorageRef.clear(); }
72 
ImplCreateSvDrawStorage()73 void GalleryBinaryEngine::ImplCreateSvDrawStorage()
74 {
75     try
76     {
77         m_aSvDrawStorageRef
78             = new SotStorage(false, GetSdvURL().GetMainURL(INetURLObject::DecodeMechanism::NONE),
79                              mbReadOnly ? StreamMode::READ : StreamMode::STD_READWRITE);
80         // #i50423# ReadOnly may not been set though the file can't be written (because of security reasons)
81         if ((m_aSvDrawStorageRef->GetError() != ERRCODE_NONE) && !mbReadOnly)
82             m_aSvDrawStorageRef = new SotStorage(
83                 false, GetSdvURL().GetMainURL(INetURLObject::DecodeMechanism::NONE),
84                 StreamMode::READ);
85     }
86     catch (const css::ucb::ContentCreationException&)
87     {
88         TOOLS_WARN_EXCEPTION("svx", "failed to open: " << GetSdvURL().GetMainURL(
89                                                               INetURLObject::DecodeMechanism::NONE)
90                                                        << "due to");
91     }
92 }
93 
GetSvDrawStorage() const94 const tools::SvRef<SotStorage>& GalleryBinaryEngine::GetSvDrawStorage() const
95 {
96     return m_aSvDrawStorageRef;
97 }
98 
implWrite(const GalleryTheme & rTheme,const GalleryThemeEntry * pThm)99 bool GalleryBinaryEngine::implWrite(const GalleryTheme& rTheme, const GalleryThemeEntry* pThm)
100 {
101     INetURLObject aPathURL(GetThmURL());
102 
103     aPathURL.removeSegment();
104     aPathURL.removeFinalSlash();
105 
106     DBG_ASSERT(aPathURL.GetProtocol() != INetProtocol::NotValid, "invalid URL");
107 
108     if (FileExists(aPathURL) || CreateDir(aPathURL))
109     {
110 #ifdef UNX
111         std::unique_ptr<SvStream> pOStm(::utl::UcbStreamHelper::CreateStream(
112             GetThmURL().GetMainURL(INetURLObject::DecodeMechanism::NONE),
113             StreamMode::WRITE | StreamMode::COPY_ON_SYMLINK | StreamMode::TRUNC));
114 #else
115         std::unique_ptr<SvStream> pOStm(::utl::UcbStreamHelper::CreateStream(
116             GetThmURL().GetMainURL(INetURLObject::DecodeMechanism::NONE),
117             StreamMode::WRITE | StreamMode::TRUNC));
118 #endif
119 
120         if (pOStm)
121         {
122             writeGalleryTheme(*pOStm, rTheme, pThm);
123             pOStm.reset();
124             return true;
125         }
126 
127         return false;
128     }
129     return true;
130 }
131 
insertObject(const SgaObject & rObj,GalleryObject * pFoundEntry,sal_uInt32 nInsertPos)132 void GalleryBinaryEngine::insertObject(const SgaObject& rObj, GalleryObject* pFoundEntry,
133                                        sal_uInt32 nInsertPos)
134 {
135     if (pFoundEntry)
136     {
137         GalleryObject aNewEntry;
138 
139         // update title of new object if necessary
140         if (rObj.GetTitle().isEmpty())
141         {
142             std::unique_ptr<SgaObject> pOldObj(implReadSgaObject(pFoundEntry));
143 
144             if (pOldObj)
145             {
146                 const_cast<SgaObject&>(rObj).SetTitle(pOldObj->GetTitle());
147             }
148         }
149         else if (rObj.GetTitle() == "__<empty>__")
150             const_cast<SgaObject&>(rObj).SetTitle("");
151 
152         implWriteSgaObject(rObj, nInsertPos, &aNewEntry);
153         pFoundEntry->nOffset = aNewEntry.nOffset;
154     }
155     else
156         implWriteSgaObject(rObj, nInsertPos, nullptr);
157 }
158 
removeObject(const std::unique_ptr<GalleryObject> & pEntry)159 void GalleryBinaryEngine::removeObject(const std::unique_ptr<GalleryObject>& pEntry)
160 {
161     if (mrGalleryObjectCollection.getObjectList().empty())
162         KillFile(GetSdgURL());
163 
164     if (SgaObjKind::SvDraw == pEntry->eObjKind)
165         GetSvDrawStorage()->Remove(
166             pEntry->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE));
167 }
168 
implReadSgaObject(GalleryObject const * pEntry)169 std::unique_ptr<SgaObject> GalleryBinaryEngine::implReadSgaObject(GalleryObject const* pEntry)
170 {
171     std::unique_ptr<SgaObject> pSgaObj;
172 
173     if (pEntry)
174     {
175         std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream(
176             GetSdgURL().GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ));
177 
178         if (pIStm)
179         {
180             sal_uInt32 nInventor;
181 
182             // Check to ensure that the file is a valid SGA file
183             pIStm->Seek(pEntry->nOffset);
184             pIStm->ReadUInt32(nInventor);
185 
186             if (nInventor == COMPAT_FORMAT('S', 'G', 'A', '3'))
187             {
188                 pIStm->Seek(pEntry->nOffset);
189 
190                 switch (pEntry->eObjKind)
191                 {
192                     case SgaObjKind::Bitmap:
193                         pSgaObj.reset(new SgaObjectBmp());
194                         break;
195                     case SgaObjKind::Animation:
196                         pSgaObj.reset(new SgaObjectAnim());
197                         break;
198                     case SgaObjKind::Inet:
199                         pSgaObj.reset(new SgaObjectINet());
200                         break;
201                     case SgaObjKind::SvDraw:
202                         pSgaObj.reset(new SgaObjectSvDraw());
203                         break;
204                     case SgaObjKind::Sound:
205                         pSgaObj.reset(new SgaObjectSound());
206                         break;
207 
208                     default:
209                         break;
210                 }
211 
212                 if (pSgaObj)
213                 {
214                     ReadSgaObject(*pIStm, *pSgaObj);
215                     pSgaObj->ImplUpdateURL(pEntry->getURL());
216                 }
217             }
218         }
219     }
220 
221     return pSgaObj;
222 }
223 
implWriteSgaObject(const SgaObject & rObj,sal_uInt32 nPos,GalleryObject * pExistentEntry)224 bool GalleryBinaryEngine::implWriteSgaObject(const SgaObject& rObj, sal_uInt32 nPos,
225                                              GalleryObject* pExistentEntry)
226 {
227     std::unique_ptr<SvStream> pOStm(::utl::UcbStreamHelper::CreateStream(
228         GetSdgURL().GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE));
229     bool bRet = false;
230 
231     if (pOStm)
232     {
233         const sal_uInt32 nOffset = pOStm->Seek(STREAM_SEEK_TO_END);
234 
235         rObj.WriteData(*pOStm, m_aDestDir);
236 
237         if (!pOStm->GetError())
238         {
239             GalleryObject* pEntry;
240 
241             if (!pExistentEntry)
242             {
243                 pEntry = new GalleryObject;
244                 if (nPos < mrGalleryObjectCollection.size())
245                 {
246                     mrGalleryObjectCollection.getObjectList().emplace(
247                         mrGalleryObjectCollection.getObjectList().begin() + nPos, pEntry);
248                 }
249                 else
250                     mrGalleryObjectCollection.getObjectList().emplace_back(pEntry);
251             }
252             else
253                 pEntry = pExistentEntry;
254 
255             pEntry->m_pGalleryObjectStorage = std::make_unique<GalleryObjectBinaryStorage>();
256             pEntry->m_pGalleryObjectStorage->setURL(rObj.GetURL());
257 
258             pEntry->nOffset = nOffset;
259             pEntry->eObjKind = rObj.GetObjKind();
260             bRet = true;
261         }
262     }
263 
264     return bRet;
265 }
266 
readModel(const GalleryObject * pObject,SdrModel & rModel)267 bool GalleryBinaryEngine::readModel(const GalleryObject* pObject, SdrModel& rModel)
268 {
269     tools::SvRef<SotStorage> xSotStorage(GetSvDrawStorage());
270     bool bRet = false;
271     const INetURLObject aURL(ImplGetURL(pObject));
272 
273     if (xSotStorage.is())
274     {
275         const OUString aStreamName(GetSvDrawStreamNameFromURL(aURL));
276         tools::SvRef<SotStorageStream> xInputStream(
277             xSotStorage->OpenSotStream(aStreamName, StreamMode::READ));
278 
279         if (xInputStream.is() && !xInputStream->GetError())
280         {
281             xInputStream->SetBufferSize(STREAMBUF_SIZE);
282             bRet = GallerySvDrawImport(*xInputStream, rModel);
283             xInputStream->SetBufferSize(0);
284         }
285     }
286     return bRet;
287 }
288 
insertModel(const FmFormModel & rModel,const INetURLObject & rUserURL)289 SgaObjectSvDraw GalleryBinaryEngine::insertModel(const FmFormModel& rModel,
290                                                  const INetURLObject& rUserURL)
291 {
292     INetURLObject aURL(implCreateUniqueURL(SgaObjKind::SvDraw, rUserURL));
293     tools::SvRef<SotStorage> xSotStorage(GetSvDrawStorage());
294     bool bRet = false;
295 
296     if (xSotStorage.is())
297     {
298         const OUString aStreamName(GetSvDrawStreamNameFromURL(aURL));
299         tools::SvRef<SotStorageStream> xOutputStream(
300             xSotStorage->OpenSotStream(aStreamName, StreamMode::WRITE | StreamMode::TRUNC));
301 
302         if (xOutputStream.is() && !xOutputStream->GetError())
303         {
304             SvMemoryStream aMemoryStream(65535, 65535);
305             FmFormModel* pFormModel = const_cast<FmFormModel*>(&rModel);
306 
307             pFormModel->BurnInStyleSheetAttributes();
308 
309             {
310                 uno::Reference<io::XOutputStream> xDocOut(
311                     new utl::OOutputStreamWrapper(aMemoryStream));
312 
313                 if (xDocOut.is())
314                     (void)SvxDrawingLayerExport(pFormModel, xDocOut);
315             }
316 
317             aMemoryStream.Seek(0);
318 
319             xOutputStream->SetBufferSize(16348);
320             GalleryCodec aCodec(*xOutputStream);
321             aCodec.Write(aMemoryStream);
322 
323             xOutputStream->SetBufferSize(0);
324             xOutputStream->Commit();
325             bRet = !xOutputStream->GetError();
326         }
327     }
328     if (bRet)
329     {
330         SgaObjectSvDraw aObjSvDraw(rModel, aURL);
331         return aObjSvDraw;
332     }
333     return SgaObjectSvDraw();
334 }
335 
readModelStream(const GalleryObject * pObject,tools::SvRef<SotTempStream> const & rxModelStream)336 bool GalleryBinaryEngine::readModelStream(const GalleryObject* pObject,
337                                           tools::SvRef<SotTempStream> const& rxModelStream)
338 {
339     const INetURLObject aURL(ImplGetURL(pObject));
340     tools::SvRef<SotStorage> xSotStorage(GetSvDrawStorage());
341     bool bRet = false;
342 
343     if (xSotStorage.is())
344     {
345         const OUString aStreamName(GetSvDrawStreamNameFromURL(aURL));
346         tools::SvRef<SotStorageStream> xInputStream(
347             xSotStorage->OpenSotStream(aStreamName, StreamMode::READ));
348 
349         if (xInputStream.is() && !xInputStream->GetError())
350         {
351             sal_uInt32 nVersion = 0;
352 
353             xInputStream->SetBufferSize(16348);
354 
355             if (GalleryCodec::IsCoded(*xInputStream, nVersion))
356             {
357                 SvxGalleryDrawModel aModel;
358 
359                 if (aModel.GetModel())
360                 {
361                     if (GallerySvDrawImport(*xInputStream, *aModel.GetModel()))
362                     {
363                         aModel.GetModel()->BurnInStyleSheetAttributes();
364 
365                         {
366                             uno::Reference<io::XOutputStream> xDocOut(
367                                 new utl::OOutputStreamWrapper(*rxModelStream));
368 
369                             SvxDrawingLayerExport(aModel.GetModel(), xDocOut);
370                         }
371                     }
372 
373                     bRet = (rxModelStream->GetError() == ERRCODE_NONE);
374                 }
375             }
376 
377             xInputStream->SetBufferSize(0);
378         }
379     }
380     return bRet;
381 }
382 
383 SgaObjectSvDraw
insertModelStream(const tools::SvRef<SotTempStream> & rxModelStream,const INetURLObject & rUserURL)384 GalleryBinaryEngine::insertModelStream(const tools::SvRef<SotTempStream>& rxModelStream,
385                                        const INetURLObject& rUserURL)
386 {
387     INetURLObject aURL(implCreateUniqueURL(SgaObjKind::SvDraw, rUserURL));
388     tools::SvRef<SotStorage> xSotStorage(GetSvDrawStorage());
389 
390     if (xSotStorage.is())
391     {
392         const OUString aStreamName(GetSvDrawStreamNameFromURL(aURL));
393         tools::SvRef<SotStorageStream> xOutputStream(
394             xSotStorage->OpenSotStream(aStreamName, StreamMode::WRITE | StreamMode::TRUNC));
395 
396         if (xOutputStream.is() && !xOutputStream->GetError())
397         {
398             GalleryCodec aCodec(*xOutputStream);
399 
400             xOutputStream->SetBufferSize(16348);
401             aCodec.Write(*rxModelStream);
402 
403             if (!xOutputStream->GetError())
404             {
405                 xOutputStream->Seek(0);
406                 SgaObjectSvDraw aObjSvDraw(*xOutputStream, aURL);
407                 return aObjSvDraw;
408             }
409         }
410     }
411     return SgaObjectSvDraw();
412 }
413 
implCreateUniqueURL(SgaObjKind eObjKind,const INetURLObject & rUserURL,ConvertDataFormat nFormat)414 INetURLObject GalleryBinaryEngine::implCreateUniqueURL(SgaObjKind eObjKind,
415                                                        const INetURLObject& rUserURL,
416                                                        ConvertDataFormat nFormat)
417 {
418     INetURLObject aDir(rUserURL);
419     INetURLObject aInfoFileURL(rUserURL);
420     INetURLObject aNewURL;
421     sal_uInt32 nNextNumber = 1999;
422     char const* pExt = nullptr;
423     bool bExists;
424 
425     aDir.Append(u"dragdrop");
426     CreateDir(aDir);
427 
428     aInfoFileURL.Append(u"sdddndx1");
429 
430     // read next possible number
431     if (FileExists(aInfoFileURL))
432     {
433         std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream(
434             aInfoFileURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ));
435 
436         if (pIStm)
437         {
438             pIStm->ReadUInt32(nNextNumber);
439         }
440     }
441 
442     pExt = comphelper::GraphicMimeTypeHelper::GetExtensionForConvertDataFormat(nFormat);
443 
444     do
445     {
446         // get URL
447         if (SgaObjKind::SvDraw == eObjKind)
448         {
449             OUString aFileName = "gallery/svdraw/dd" + OUString::number(++nNextNumber % 99999999);
450             aNewURL = INetURLObject(aFileName, INetProtocol::PrivSoffice);
451 
452             bExists = false;
453 
454             for (auto const& pObject : mrGalleryObjectCollection.getObjectList())
455             {
456                 if (pObject->getURL() == aNewURL)
457                 {
458                     bExists = true;
459                     break;
460                 }
461             }
462         }
463         else
464         {
465             OUString aFileName = "dd" + OUString::number(++nNextNumber % 999999);
466 
467             if (pExt)
468                 aFileName += OUString(pExt, strlen(pExt), RTL_TEXTENCODING_ASCII_US);
469 
470             aNewURL = aDir;
471             aNewURL.Append(aFileName);
472 
473             bExists = FileExists(aNewURL);
474         }
475     } while (bExists);
476 
477     // write updated number
478     std::unique_ptr<SvStream> pOStm(::utl::UcbStreamHelper::CreateStream(
479         aInfoFileURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE));
480 
481     if (pOStm)
482     {
483         pOStm->WriteUInt32(nNextNumber);
484     }
485 
486     return aNewURL;
487 }
488 
insertGraphic(const Graphic & rGraphic,const GfxLink & aGfxLink,const ConvertDataFormat & nExportFormat,const INetURLObject & rUserURL)489 SgaObjectBmp GalleryBinaryEngine::insertGraphic(const Graphic& rGraphic, const GfxLink& aGfxLink,
490                                                 const ConvertDataFormat& nExportFormat,
491                                                 const INetURLObject& rUserURL)
492 {
493     const INetURLObject aURL(implCreateUniqueURL(SgaObjKind::Bitmap, rUserURL, nExportFormat));
494     std::unique_ptr<SvStream> pOStm(
495         ::utl::UcbStreamHelper::CreateStream(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
496                                              StreamMode::WRITE | StreamMode::TRUNC));
497     bool bRet = false;
498 
499     if (pOStm)
500     {
501         pOStm->SetVersion(SOFFICE_FILEFORMAT_50);
502 
503         if (ConvertDataFormat::SVM == nExportFormat)
504         {
505             GDIMetaFile aMtf(rGraphic.GetGDIMetaFile());
506 
507             aMtf.Write(*pOStm);
508             bRet = (pOStm->GetError() == ERRCODE_NONE);
509         }
510         else
511         {
512             if (aGfxLink.GetDataSize() && aGfxLink.GetData())
513             {
514                 pOStm->WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
515                 bRet = (pOStm->GetError() == ERRCODE_NONE);
516             }
517             else
518                 bRet = (GraphicConverter::Export(*pOStm, rGraphic, nExportFormat) == ERRCODE_NONE);
519         }
520 
521         pOStm.reset();
522     }
523     if (bRet)
524     {
525         const SgaObjectBmp aObjBmp(aURL);
526         return aObjBmp;
527     }
528     return SgaObjectBmp();
529 }
530 
updateSvDrawObject(const GalleryObject * pEntry)531 SgaObjectSvDraw GalleryBinaryEngine::updateSvDrawObject(const GalleryObject* pEntry)
532 {
533     if (GetSvDrawStorage().is())
534     {
535         const OUString aStmName(GetSvDrawStreamNameFromURL(pEntry->getURL()));
536         tools::SvRef<SotStorageStream> pIStm
537             = GetSvDrawStorage()->OpenSotStream(aStmName, StreamMode::READ);
538 
539         if (pIStm.is() && !pIStm->GetError())
540         {
541             pIStm->SetBufferSize(16384);
542 
543             SgaObjectSvDraw aNewObj(*pIStm, pEntry->getURL());
544 
545             pIStm->SetBufferSize(0);
546 
547             return aNewObj;
548         }
549     }
550     return SgaObjectSvDraw();
551 }
552 
updateTheme()553 void GalleryBinaryEngine::updateTheme()
554 {
555     ::utl::TempFile aTmp;
556     INetURLObject aInURL(GetSdgURL());
557     INetURLObject aTmpURL(aTmp.GetURL());
558 
559     DBG_ASSERT(aInURL.GetProtocol() != INetProtocol::NotValid, "invalid URL");
560     DBG_ASSERT(aTmpURL.GetProtocol() != INetProtocol::NotValid, "invalid URL");
561 
562     std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream(
563         aInURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ));
564     std::unique_ptr<SvStream> pTmpStm(::utl::UcbStreamHelper::CreateStream(
565         aTmpURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
566         StreamMode::WRITE | StreamMode::TRUNC));
567 
568     if (pIStm && pTmpStm)
569     {
570         for (const auto& i : mrGalleryObjectCollection.getObjectList())
571         {
572             GalleryObject* pEntry = i.get();
573             std::unique_ptr<SgaObject> pObj;
574 
575             switch (pEntry->eObjKind)
576             {
577                 case SgaObjKind::Bitmap:
578                     pObj.reset(new SgaObjectBmp());
579                     break;
580                 case SgaObjKind::Animation:
581                     pObj.reset(new SgaObjectAnim());
582                     break;
583                 case SgaObjKind::Inet:
584                     pObj.reset(new SgaObjectINet());
585                     break;
586                 case SgaObjKind::SvDraw:
587                     pObj.reset(new SgaObjectSvDraw());
588                     break;
589                 case SgaObjKind::Sound:
590                     pObj.reset(new SgaObjectSound());
591                     break;
592 
593                 default:
594                     break;
595             }
596 
597             if (pObj)
598             {
599                 pIStm->Seek(pEntry->nOffset);
600                 ReadSgaObject(*pIStm, *pObj);
601                 pEntry->nOffset = pTmpStm->Tell();
602                 WriteSgaObject(*pTmpStm, *pObj);
603             }
604         }
605     }
606     else
607     {
608         OSL_FAIL("File(s) could not be opened");
609     }
610 
611     pIStm.reset();
612     pTmpStm.reset();
613 
614     CopyFile(aTmpURL, aInURL);
615     KillFile(aTmpURL);
616 
617     ErrCode nStorErr = ERRCODE_NONE;
618 
619     try
620     {
621         tools::SvRef<SotStorage> aTempStorageRef(
622             new SotStorage(false, aTmpURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
623                            StreamMode::STD_READWRITE));
624         GetSvDrawStorage()->CopyTo(aTempStorageRef.get());
625         nStorErr = GetSvDrawStorage()->GetError();
626     }
627     catch (const css::ucb::ContentCreationException&)
628     {
629         TOOLS_WARN_EXCEPTION("svx", "failed to open: "
630                                         << aTmpURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)
631                                         << "due to");
632         nStorErr = ERRCODE_IO_GENERAL;
633     }
634 
635     if (nStorErr == ERRCODE_NONE)
636     {
637         clearSotStorage();
638         CopyFile(aTmpURL, GetSdvURL());
639         ImplCreateSvDrawStorage();
640     }
641 
642     KillFile(aTmpURL);
643 }
644 
insertFileOrDirURL(const INetURLObject & rFileOrDirURL,std::vector<INetURLObject> & rURLVector)645 void GalleryBinaryEngine::insertFileOrDirURL(const INetURLObject& rFileOrDirURL,
646                                              std::vector<INetURLObject>& rURLVector)
647 {
648     INetURLObject aURL;
649     try
650     {
651         ::ucbhelper::Content aCnt(rFileOrDirURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),
652                                   uno::Reference<ucb::XCommandEnvironment>(),
653                                   comphelper::getProcessComponentContext());
654         bool bFolder = false;
655 
656         aCnt.getPropertyValue("IsFolder") >>= bFolder;
657 
658         if (bFolder)
659         {
660             uno::Sequence<OUString> aProps{ "Url" };
661             uno::Reference<sdbc::XResultSet> xResultSet(
662                 aCnt.createCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY));
663             uno::Reference<ucb::XContentAccess> xContentAccess(xResultSet, uno::UNO_QUERY);
664             if (xContentAccess.is())
665             {
666                 while (xResultSet->next())
667                 {
668                     aURL.SetSmartURL(xContentAccess->queryContentIdentifierString());
669                     rURLVector.push_back(aURL);
670                 }
671             }
672         }
673         else
674             rURLVector.push_back(rFileOrDirURL);
675     }
676     catch (const ucb::ContentCreationException&)
677     {
678     }
679     catch (const uno::RuntimeException&)
680     {
681     }
682     catch (const uno::Exception&)
683     {
684     }
685 }
686 
writeGalleryTheme(SvStream & rOStm,const GalleryTheme & rTheme,const GalleryThemeEntry * pThm)687 SvStream& GalleryBinaryEngine::writeGalleryTheme(SvStream& rOStm, const GalleryTheme& rTheme,
688                                                  const GalleryThemeEntry* pThm)
689 {
690     const INetURLObject rRelURL1 = rTheme.GetParent()->GetRelativeURL();
691     const INetURLObject rRelURL2 = rTheme.GetParent()->GetUserURL();
692     const sal_uInt32 rId = rTheme.GetId();
693     sal_uInt32 nCount = mrGalleryObjectCollection.size();
694     bool bRel;
695 
696     rOStm.WriteUInt16(0x0004);
697     write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, pThm->GetThemeName(),
698                                                  RTL_TEXTENCODING_UTF8);
699     rOStm.WriteUInt32(nCount).WriteUInt16(osl_getThreadTextEncoding());
700 
701     for (sal_uInt32 i = 0; i < nCount; i++)
702     {
703         const GalleryObject* pObj = mrGalleryObjectCollection.getForPosition(i);
704         OUString aPath;
705 
706         if (SgaObjKind::SvDraw == pObj->eObjKind)
707         {
708             aPath = GetSvDrawStreamNameFromURL(pObj->getURL());
709             bRel = false;
710         }
711         else
712         {
713             aPath = pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE);
714             aPath = aPath.copy(
715                 0, std::min(rRelURL1.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength(),
716                             aPath.getLength()));
717             bRel = aPath == rRelURL1.GetMainURL(INetURLObject::DecodeMechanism::NONE);
718 
719             if (bRel
720                 && (pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength()
721                     > (rRelURL1.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength() + 1)))
722             {
723                 aPath = pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE);
724                 aPath = aPath.copy(
725                     std::min(rRelURL1.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength(),
726                              aPath.getLength()));
727             }
728             else
729             {
730                 aPath = pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE);
731                 aPath = aPath.copy(
732                     0,
733                     std::min(rRelURL2.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength(),
734                              aPath.getLength()));
735                 bRel = aPath == rRelURL2.GetMainURL(INetURLObject::DecodeMechanism::NONE);
736 
737                 if (bRel
738                     && (pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength()
739                         > (rRelURL2.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength()
740                            + 1)))
741                 {
742                     aPath = pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE);
743                     aPath = aPath.copy(std::min(
744                         rRelURL2.GetMainURL(INetURLObject::DecodeMechanism::NONE).getLength(),
745                         aPath.getLength()));
746                 }
747                 else
748                     aPath = pObj->getURL().GetMainURL(INetURLObject::DecodeMechanism::NONE);
749             }
750         }
751 
752         if (!m_aDestDir.isEmpty())
753         {
754             bool aFound = aPath.indexOf(m_aDestDir) != -1;
755             aPath = aPath.replaceFirst(m_aDestDir, "");
756             if (aFound)
757                 bRel = m_bDestDirRelative;
758             else
759                 SAL_WARN("svx", "failed to replace destdir of '" << m_aDestDir << "' in '" << aPath
760                                                                  << "'");
761         }
762 
763         rOStm.WriteBool(bRel);
764         write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aPath, RTL_TEXTENCODING_UTF8);
765         rOStm.WriteUInt32(pObj->nOffset).WriteUInt16(static_cast<sal_uInt16>(pObj->eObjKind));
766     }
767 
768     // more recently, a 512-byte reserve buffer is written,
769     // to recognize them two sal_uInt32-Ids will be written.
770     rOStm.WriteUInt32(COMPAT_FORMAT('G', 'A', 'L', 'R'))
771         .WriteUInt32(COMPAT_FORMAT('E', 'S', 'R', 'V'));
772 
773     const tools::Long nReservePos = rOStm.Tell();
774     std::unique_ptr<VersionCompatWrite> pCompat(new VersionCompatWrite(rOStm, 2));
775 
776     rOStm.WriteUInt32(rId).WriteBool(pThm->IsNameFromResource()); // From version 2 and up
777 
778     pCompat.reset();
779 
780     // Fill the rest of the buffer.
781     const tools::Long nRest
782         = std::max(tools::Long(512 - (rOStm.Tell() - nReservePos)), tools::Long(0));
783 
784     if (nRest)
785     {
786         std::unique_ptr<char[]> pReserve(new char[nRest]);
787         memset(pReserve.get(), 0, nRest);
788         rOStm.WriteBytes(pReserve.get(), nRest);
789     }
790 
791     return rOStm;
792 }
793 
getModificationDate() const794 DateTime GalleryBinaryEngine::getModificationDate() const
795 {
796     ::ucbhelper::Content aCnt(GetThmURL().GetMainURL(INetURLObject::DecodeMechanism::NONE),
797                               uno::Reference<ucb::XCommandEnvironment>(),
798                               comphelper::getProcessComponentContext());
799     util::DateTime aDateTimeModified;
800     DateTime aDateTime(DateTime::EMPTY);
801 
802     aCnt.getPropertyValue("DateModified") >>= aDateTimeModified;
803     ::utl::typeConvert(aDateTimeModified, aDateTime);
804 
805     return aDateTime;
806 }
807 
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
809