Line data Source code
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 <cstdio>
13 : #include <cstring>
14 : #include <list>
15 : #include <map>
16 : #include <vector>
17 : #include <iostream>
18 : #include <libxml/parser.h>
19 : #include <libxml/tree.h>
20 : #include <libxml/xmlIO.h>
21 : #include <libxslt/transform.h>
22 : #include <libxslt/xsltutils.h>
23 : #include <libxslt/variables.h>
24 :
25 : #include <rtl/ustrbuf.hxx>
26 :
27 : #include <sax/tools/converter.hxx>
28 :
29 : #include <package/Inflater.hxx>
30 : #include <package/Deflater.hxx>
31 :
32 : #include <cppuhelper/factory.hxx>
33 : #include <comphelper/processfactory.hxx>
34 : #include <com/sun/star/uno/Any.hxx>
35 : #include <com/sun/star/uno/XInterface.hpp>
36 : #include <com/sun/star/container/XNameContainer.hpp>
37 : #include <com/sun/star/io/TempFile.hpp>
38 : #include <com/sun/star/io/XInputStream.hpp>
39 : #include <com/sun/star/io/XOutputStream.hpp>
40 : #include <com/sun/star/io/XSeekable.hpp>
41 : #include <com/sun/star/embed/XTransactedObject.hpp>
42 :
43 : #include <OleHandler.hxx>
44 : #include <boost/scoped_ptr.hpp>
45 :
46 : using namespace ::com::sun::star::uno;
47 : using namespace ::com::sun::star::lang;
48 : using namespace ::com::sun::star::io;
49 : using namespace ::com::sun::star::embed;
50 :
51 :
52 : namespace XSLT
53 : {
54 0 : Reference<XStream> SAL_CALL OleHandler::createTempFile() {
55 0 : Reference<XStream> tempFile( TempFile::create(m_xContext), UNO_QUERY);
56 : OSL_ASSERT(tempFile.is());
57 0 : return tempFile;
58 : }
59 :
60 0 : void SAL_CALL OleHandler::ensureCreateRootStorage()
61 : {
62 0 : if (m_storage == NULL || m_rootStream == NULL)
63 : {
64 0 : m_rootStream = createTempFile();
65 0 : Sequence<Any> args(1);
66 0 : args[0] <<= m_rootStream->getInputStream();
67 :
68 : Reference<XNameContainer> cont(
69 0 : Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
70 0 : ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
71 0 : m_storage = cont;
72 : }
73 0 : }
74 :
75 0 : void SAL_CALL OleHandler::initRootStorageFromBase64(const OString& content)
76 : {
77 0 : Sequence<sal_Int8> oleData;
78 : ::sax::Converter::decodeBase64(oleData, OStringToOUString(
79 0 : content, RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS));
80 0 : m_rootStream = createTempFile();
81 0 : Reference<XOutputStream> xOutput = m_rootStream->getOutputStream();
82 0 : xOutput->writeBytes(oleData);
83 0 : xOutput->flush();
84 : //Get the input stream and seek to begin
85 0 : Reference<XSeekable> xSeek(m_rootStream->getInputStream(), UNO_QUERY);
86 0 : xSeek->seek(0);
87 :
88 : //create an com.sun.star.embed.OLESimpleStorage from the temp stream
89 0 : Sequence<Any> args(1);
90 0 : args[0] <<= xSeek;
91 : Reference<XNameContainer> cont(
92 0 : Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
93 0 : ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
94 0 : m_storage = cont;
95 0 : }
96 :
97 : OString SAL_CALL
98 0 : OleHandler::encodeSubStorage(const OUString& streamName)
99 : {
100 0 : if (!m_storage->hasByName(streamName))
101 : {
102 0 : return "Not Found:";// + streamName;
103 : }
104 : ;
105 0 : Reference<XInputStream> subStream(*static_cast<Reference< XInterface > const *>(m_storage->getByName(streamName).getValue()), UNO_QUERY);
106 0 : if (!subStream.is())
107 : {
108 0 : return "Not Found:";// + streamName;
109 : }
110 : //The first four byte are the length of the uncompressed data
111 0 : Sequence<sal_Int8> pLength(4);
112 0 : Reference<XSeekable> xSeek(subStream, UNO_QUERY);
113 0 : xSeek->seek(0);
114 : //Get the uncompressed length
115 0 : int readbytes = subStream->readBytes(pLength, 4);
116 0 : if (4 != readbytes)
117 : {
118 0 : return "Can not read the length.";
119 : }
120 0 : int oleLength = (pLength[0] << 0) + (pLength[1] << 8)
121 0 : + (pLength[2] << 16) + (pLength[3] << 24);
122 0 : Sequence<sal_Int8> content(oleLength);
123 : //Read all bytes. The compressed length should less then the uncompressed length
124 0 : readbytes = subStream->readBytes(content, oleLength);
125 0 : if (oleLength < readbytes)
126 : {
127 0 : return "oleLength";// +oleLength + readBytes;
128 : }
129 :
130 : // Decompress the bytes
131 0 : boost::scoped_ptr< ::ZipUtils::Inflater> decompresser(new ::ZipUtils::Inflater(false));
132 0 : decompresser->setInput(content);
133 0 : Sequence<sal_Int8> result(oleLength);
134 0 : decompresser->doInflateSegment(result, 0, oleLength);
135 0 : decompresser->end();
136 0 : decompresser.reset();
137 : //return the base64 string of the uncompressed data
138 0 : OUStringBuffer buf(oleLength);
139 0 : ::sax::Converter::encodeBase64(buf, result);
140 0 : return OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
141 : }
142 :
143 : void SAL_CALL
144 0 : OleHandler::insertByName(const OUString& streamName, const OString& content)
145 : {
146 0 : if ( streamName == "oledata.mso" )
147 : {
148 0 : initRootStorageFromBase64(content);
149 : }
150 : else
151 : {
152 0 : ensureCreateRootStorage();
153 0 : insertSubStorage(streamName, content);
154 : }
155 0 : }
156 :
157 : const OString
158 0 : SAL_CALL OleHandler::getByName(const OUString& streamName)
159 : {
160 0 : if ( streamName == "oledata.mso" )
161 : {
162 : //get the length and seek to 0
163 0 : Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
164 0 : int oleLength = (int) xSeek->getLength();
165 0 : xSeek->seek(0);
166 : //read all bytes
167 0 : Reference<XInputStream> xInput = m_rootStream->getInputStream();
168 0 : Sequence<sal_Int8> oledata(oleLength);
169 0 : xInput->readBytes(oledata, oleLength);
170 : //return the base64 encoded string
171 0 : OUStringBuffer buf(oleLength);
172 0 : ::sax::Converter::encodeBase64(buf, oledata);
173 0 : return OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
174 : }
175 0 : return encodeSubStorage(streamName);
176 : }
177 :
178 : void SAL_CALL
179 0 : OleHandler::insertSubStorage(const OUString& streamName, const OString& content)
180 : {
181 : //decode the base64 string
182 0 : Sequence<sal_Int8> oledata;
183 : ::sax::Converter::decodeBase64(oledata,
184 0 : OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
185 : //create a temp stream to write data to
186 0 : Reference<XStream> subStream = createTempFile();
187 0 : Reference<XInputStream> xInput = subStream->getInputStream();
188 0 : Reference<XOutputStream> xOutput = subStream->getOutputStream();
189 : //write the length to the temp stream
190 0 : Sequence<sal_Int8> header(4);
191 0 : header[0] = (sal_Int8) (oledata.getLength() >> 0) & 0xFF;
192 0 : header[1] = (sal_Int8) (oledata.getLength() >> 8) & 0xFF;
193 0 : header[2] = (sal_Int8) (oledata.getLength() >> 16) & 0xFF;
194 0 : header[3] = (sal_Int8) (oledata.getLength() >> 24) & 0xFF;
195 0 : xOutput->writeBytes(header);
196 :
197 : // Compress the bytes
198 0 : Sequence<sal_Int8> output(oledata.getLength());
199 0 : boost::scoped_ptr< ::ZipUtils::Deflater> compresser(new ::ZipUtils::Deflater((sal_Int32) 3, false));
200 0 : compresser->setInputSegment(oledata);
201 0 : compresser->finish();
202 0 : int compressedDataLength = compresser->doDeflateSegment(output, 0, oledata.getLength());
203 0 : compresser.reset();
204 : //realloc the data length
205 0 : Sequence<sal_Int8> compressed(compressedDataLength);
206 0 : for (int i = 0; i < compressedDataLength; i++) {
207 0 : compressed[i] = output[i];
208 : }
209 :
210 : //write the compressed data to the temp stream
211 0 : xOutput->writeBytes(compressed);
212 : //seek to 0
213 0 : Reference<XSeekable> xSeek(xInput, UNO_QUERY);
214 0 : xSeek->seek(0);
215 :
216 : //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
217 0 : Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
218 0 : Any entry;
219 0 : entry <<= xInput;
220 0 : m_storage->insertByName(streamName, entry);
221 0 : xTransact->commit();
222 0 : }
223 :
224 :
225 :
226 6 : }
227 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
228 :
|