cool#10610 Ensure the parent-child relations of comments.
[LibreOffice.git] / filter / source / xsltfilter / OleHandler.cxx
blobfeab2eec414c0d00c2a8ab11c83ef6c3729d316c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4 * This file is part of the LibreOffice project.
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
12 #include <osl/diagnose.h>
13 #include <rtl/ustrbuf.hxx>
15 #include <package/Inflater.hxx>
16 #include <package/Deflater.hxx>
18 #include <cppuhelper/factory.hxx>
19 #include <comphelper/base64.hxx>
20 #include <com/sun/star/uno/Any.hxx>
21 #include <com/sun/star/container/XNameContainer.hpp>
22 #include <com/sun/star/io/TempFile.hpp>
23 #include <com/sun/star/io/XInputStream.hpp>
24 #include <com/sun/star/io/XOutputStream.hpp>
25 #include <com/sun/star/io/XSeekable.hpp>
26 #include <com/sun/star/embed/XTransactedObject.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include "OleHandler.hxx"
30 #include <optional>
32 using namespace ::com::sun::star::uno;
33 using namespace ::com::sun::star::lang;
34 using namespace ::com::sun::star::io;
35 using namespace ::com::sun::star::embed;
38 namespace XSLT
40 Reference<XStream> OleHandler::createTempFile() {
41 Reference<XStream> tempFile = TempFile::create(m_xContext);
42 OSL_ASSERT(tempFile.is());
43 return tempFile;
46 void OleHandler::ensureCreateRootStorage()
48 if (m_storage == nullptr || m_rootStream == nullptr)
50 m_rootStream = createTempFile();
51 Sequence<Any> args{ Any(m_rootStream->getInputStream()) };
53 m_storage.set(
54 Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
55 ->createInstanceWithArguments(u"com.sun.star.embed.OLESimpleStorage"_ustr, args), UNO_QUERY);
59 void OleHandler::initRootStorageFromBase64(std::string_view content)
61 Sequence<sal_Int8> oleData;
62 ::comphelper::Base64::decode(oleData, OStringToOUString(
63 content, RTL_TEXTENCODING_UTF8));
64 m_rootStream = createTempFile();
65 Reference<XOutputStream> xOutput = m_rootStream->getOutputStream();
66 xOutput->writeBytes(oleData);
67 xOutput->flush();
68 //Get the input stream and seek to begin
69 Reference<XSeekable> xSeek(m_rootStream->getInputStream(), UNO_QUERY);
70 xSeek->seek(0);
72 //create a com.sun.star.embed.OLESimpleStorage from the temp stream
73 Sequence<Any> args{ Any(xSeek) };
74 m_storage.set(
75 Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
76 ->createInstanceWithArguments(u"com.sun.star.embed.OLESimpleStorage"_ustr, args), UNO_QUERY);
79 OString
80 OleHandler::encodeSubStorage(const OUString& streamName)
82 if (!m_storage || !m_storage->hasByName(streamName))
84 return "Not Found:"_ostr;// + streamName;
87 Reference<XInputStream> subStream(m_storage->getByName(streamName), UNO_QUERY);
88 if (!subStream.is())
90 return "Not Found:"_ostr;// + streamName;
92 //The first four byte are the length of the uncompressed data
93 Sequence<sal_Int8> aLength(4);
94 Reference<XSeekable> xSeek(subStream, UNO_QUERY);
95 xSeek->seek(0);
96 //Get the uncompressed length
97 int readbytes = subStream->readBytes(aLength, 4);
98 if (4 != readbytes)
100 return "Can not read the length."_ostr;
102 sal_Int32 const oleLength = (static_cast<sal_uInt8>(aLength[0]) << 0U)
103 | (static_cast<sal_uInt8>(aLength[1]) << 8U)
104 | (static_cast<sal_uInt8>(aLength[2]) << 16U)
105 | (static_cast<sal_uInt8>(aLength[3]) << 24U);
106 if (oleLength < 0)
108 return "invalid oleLength"_ostr;
110 Sequence<sal_Int8> content(oleLength);
111 //Read all bytes. The compressed length should be less than the uncompressed length
112 readbytes = subStream->readBytes(content, oleLength);
113 if (oleLength < readbytes)
115 return "oleLength"_ostr;// +oleLength + readBytes;
118 // Decompress the bytes
119 std::optional< ::ZipUtils::Inflater> decompresser(std::in_place, false);
120 decompresser->setInput(content);
121 Sequence<sal_Int8> result(oleLength);
122 decompresser->doInflateSegment(result, 0, oleLength);
123 decompresser->end();
124 decompresser.reset();
125 //return the base64 string of the uncompressed data
126 OUStringBuffer buf(oleLength);
127 ::comphelper::Base64::encode(buf, result);
128 return OUStringToOString(buf, RTL_TEXTENCODING_ASCII_US);
131 void
132 OleHandler::insertByName(const OUString& streamName, std::string_view content)
134 if ( streamName == "oledata.mso" )
136 initRootStorageFromBase64(content);
138 else
140 ensureCreateRootStorage();
141 insertSubStorage(streamName, content);
145 OString
146 OleHandler::getByName(const OUString& streamName)
148 if ( streamName == "oledata.mso" )
150 //get the length and seek to 0
151 Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
152 int oleLength = static_cast<int>(xSeek->getLength());
153 xSeek->seek(0);
154 //read all bytes
155 Reference<XInputStream> xInput = m_rootStream->getInputStream();
156 Sequence<sal_Int8> oledata(oleLength);
157 xInput->readBytes(oledata, oleLength);
158 //return the base64 encoded string
159 OUStringBuffer buf(oleLength);
160 ::comphelper::Base64::encode(buf, oledata);
161 return OUStringToOString(buf, RTL_TEXTENCODING_ASCII_US);
163 return encodeSubStorage(streamName);
166 void
167 OleHandler::insertSubStorage(const OUString& streamName, std::string_view content)
169 //decode the base64 string
170 Sequence<sal_Int8> oledata;
171 ::comphelper::Base64::decode(oledata,
172 OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
173 //create a temp stream to write data to
174 Reference<XStream> subStream = createTempFile();
175 Reference<XInputStream> xInput = subStream->getInputStream();
176 Reference<XOutputStream> xOutput = subStream->getOutputStream();
177 //write the length to the temp stream
178 Sequence<sal_Int8> header{
179 static_cast<sal_Int8>((oledata.getLength() >> 0) & 0xFF),
180 static_cast<sal_Int8>((oledata.getLength() >> 8) & 0xFF),
181 static_cast<sal_Int8>((oledata.getLength() >> 16) & 0xFF),
182 static_cast<sal_Int8>((oledata.getLength() >> 24) & 0xFF)
184 xOutput->writeBytes(header);
186 // Compress the bytes
187 Sequence<sal_Int8> output(oledata.getLength());
188 std::optional< ::ZipUtils::Deflater> compresser(std::in_place, sal_Int32(3), false);
189 compresser->setInputSegment(oledata);
190 compresser->finish();
191 int compressedDataLength = compresser->doDeflateSegment(output, oledata.getLength());
192 compresser.reset();
193 //realloc the data length
194 output.realloc(compressedDataLength);
196 //write the compressed data to the temp stream
197 xOutput->writeBytes(output);
198 //seek to 0
199 Reference<XSeekable> xSeek(xInput, UNO_QUERY);
200 xSeek->seek(0);
202 //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
203 Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
204 Any entry;
205 entry <<= xInput;
206 m_storage->insertByName(streamName, entry);
207 xTransact->commit();
212 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */