LibreOffice Module filter (master) 1
OleHandler.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 * This file is part of the LibreOffice project.
5 *
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 */
10
11
12#include <rtl/ustrbuf.hxx>
13
14#include <package/Inflater.hxx>
15#include <package/Deflater.hxx>
16
18#include <comphelper/base64.hxx>
19#include <com/sun/star/uno/Any.hxx>
20#include <com/sun/star/container/XNameContainer.hpp>
21#include <com/sun/star/io/TempFile.hpp>
22#include <com/sun/star/io/XInputStream.hpp>
23#include <com/sun/star/io/XOutputStream.hpp>
24#include <com/sun/star/io/XSeekable.hpp>
25#include <com/sun/star/embed/XTransactedObject.hpp>
26#include <com/sun/star/lang/XMultiServiceFactory.hpp>
27
28#include "OleHandler.hxx"
29#include <optional>
30
31using namespace ::com::sun::star::uno;
32using namespace ::com::sun::star::lang;
33using namespace ::com::sun::star::io;
34using namespace ::com::sun::star::embed;
35
36
37namespace XSLT
38{
39 Reference<XStream> OleHandler::createTempFile() {
40 Reference<XStream> tempFile = TempFile::create(m_xContext);
41 OSL_ASSERT(tempFile.is());
42 return tempFile;
43 }
44
46 {
47 if (m_storage == nullptr || m_rootStream == nullptr)
48 {
50 Sequence<Any> args{ Any(m_rootStream->getInputStream()) };
51
52 Reference<XNameContainer> cont(
53 Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
54 ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
55 m_storage = cont;
56 }
57 }
58
59 void OleHandler::initRootStorageFromBase64(std::string_view content)
60 {
61 Sequence<sal_Int8> oleData;
62 ::comphelper::Base64::decode(oleData, OStringToOUString(
63 content, RTL_TEXTENCODING_UTF8));
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);
71
72 //create a com.sun.star.embed.OLESimpleStorage from the temp stream
73 Sequence<Any> args{ Any(xSeek) };
74 Reference<XNameContainer> cont(
75 Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
76 ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
77 m_storage = cont;
78 }
79
80 OString
81 OleHandler::encodeSubStorage(const OUString& streamName)
82 {
83 if (!m_storage || !m_storage->hasByName(streamName))
84 {
85 return "Not Found:";// + streamName;
86 }
87
88 Reference<XInputStream> subStream(m_storage->getByName(streamName), UNO_QUERY);
89 if (!subStream.is())
90 {
91 return "Not Found:";// + streamName;
92 }
93 //The first four byte are the length of the uncompressed data
94 Sequence<sal_Int8> aLength(4);
95 Reference<XSeekable> xSeek(subStream, UNO_QUERY);
96 xSeek->seek(0);
97 //Get the uncompressed length
98 int readbytes = subStream->readBytes(aLength, 4);
99 if (4 != readbytes)
100 {
101 return "Can not read the length.";
102 }
103 sal_Int32 const oleLength = (static_cast<sal_uInt8>(aLength[0]) << 0U)
104 | (static_cast<sal_uInt8>(aLength[1]) << 8U)
105 | (static_cast<sal_uInt8>(aLength[2]) << 16U)
106 | (static_cast<sal_uInt8>(aLength[3]) << 24U);
107 if (oleLength < 0)
108 {
109 return "invalid oleLength";
110 }
111 Sequence<sal_Int8> content(oleLength);
112 //Read all bytes. The compressed length should be less than the uncompressed length
113 readbytes = subStream->readBytes(content, oleLength);
114 if (oleLength < readbytes)
115 {
116 return "oleLength";// +oleLength + readBytes;
117 }
118
119 // Decompress the bytes
120 std::optional< ::ZipUtils::Inflater> decompresser(std::in_place, false);
121 decompresser->setInput(content);
122 Sequence<sal_Int8> result(oleLength);
123 decompresser->doInflateSegment(result, 0, oleLength);
124 decompresser->end();
125 decompresser.reset();
126 //return the base64 string of the uncompressed data
127 OUStringBuffer buf(oleLength);
129 return OUStringToOString(buf, RTL_TEXTENCODING_ASCII_US);
130 }
131
132 void
133 OleHandler::insertByName(const OUString& streamName, std::string_view content)
134 {
135 if ( streamName == "oledata.mso" )
136 {
138 }
139 else
140 {
142 insertSubStorage(streamName, content);
143 }
144 }
145
146 OString
147 OleHandler::getByName(const OUString& streamName)
148 {
149 if ( streamName == "oledata.mso" )
150 {
151 //get the length and seek to 0
152 Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
153 int oleLength = static_cast<int>(xSeek->getLength());
154 xSeek->seek(0);
155 //read all bytes
156 Reference<XInputStream> xInput = m_rootStream->getInputStream();
157 Sequence<sal_Int8> oledata(oleLength);
158 xInput->readBytes(oledata, oleLength);
159 //return the base64 encoded string
160 OUStringBuffer buf(oleLength);
161 ::comphelper::Base64::encode(buf, oledata);
162 return OUStringToOString(buf, RTL_TEXTENCODING_ASCII_US);
163 }
164 return encodeSubStorage(streamName);
165 }
166
167 void
168 OleHandler::insertSubStorage(const OUString& streamName, std::string_view content)
169 {
170 //decode the base64 string
171 Sequence<sal_Int8> oledata;
173 OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
174 //create a temp stream to write data to
175 Reference<XStream> subStream = createTempFile();
176 Reference<XInputStream> xInput = subStream->getInputStream();
177 Reference<XOutputStream> xOutput = subStream->getOutputStream();
178 //write the length to the temp stream
179 Sequence<sal_Int8> header{
180 static_cast<sal_Int8>((oledata.getLength() >> 0) & 0xFF),
181 static_cast<sal_Int8>((oledata.getLength() >> 8) & 0xFF),
182 static_cast<sal_Int8>((oledata.getLength() >> 16) & 0xFF),
183 static_cast<sal_Int8>((oledata.getLength() >> 24) & 0xFF)
184 };
185 xOutput->writeBytes(header);
186
187 // Compress the bytes
188 Sequence<sal_Int8> output(oledata.getLength());
189 std::optional< ::ZipUtils::Deflater> compresser(std::in_place, sal_Int32(3), false);
190 compresser->setInputSegment(oledata);
191 compresser->finish();
192 int compressedDataLength = compresser->doDeflateSegment(output, oledata.getLength());
193 compresser.reset();
194 //realloc the data length
195 output.realloc(compressedDataLength);
196
197 //write the compressed data to the temp stream
198 xOutput->writeBytes(output);
199 //seek to 0
200 Reference<XSeekable> xSeek(xInput, UNO_QUERY);
201 xSeek->seek(0);
202
203 //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
204 Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
205 Any entry;
206 entry <<= xInput;
207 m_storage->insertByName(streamName, entry);
208 xTransact->commit();
209 }
210
211
212}
213/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
214
constexpr sal_Int8 header[]
OString getByName(const OUString &streamName)
Definition: OleHandler.cxx:147
css::uno::Reference< XComponentContext > m_xContext
Definition: OleHandler.hxx:80
css::uno::Reference< XStream > createTempFile()
Definition: OleHandler.cxx:39
OString encodeSubStorage(const OUString &streamName)
Definition: OleHandler.cxx:81
void ensureCreateRootStorage()
Definition: OleHandler.cxx:45
void insertByName(const OUString &streamName, std::string_view content)
Definition: OleHandler.cxx:133
void initRootStorageFromBase64(std::string_view content)
Definition: OleHandler.cxx:59
css::uno::Reference< XNameContainer > m_storage
Definition: OleHandler.hxx:81
void insertSubStorage(const OUString &streamName, std::string_view content)
Definition: OleHandler.cxx:168
css::uno::Reference< XStream > m_rootStream
Definition: OleHandler.hxx:82
static void encode(OUStringBuffer &aStrBuffer, const css::uno::Sequence< sal_Int8 > &aPass)
static void decode(css::uno::Sequence< sal_Int8 > &aPass, std::u16string_view sBuffer)
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
unsigned char sal_uInt8
signed char sal_Int8
Any result