Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : :
3 : : /*
4 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 : : *
6 : : * The contents of this file are subject to the Mozilla Public License Version
7 : : * 1.1 (the "License"); you may not use this file except in compliance with
8 : : * the License. You may obtain a copy of the License at
9 : : * http://www.mozilla.org/MPL/
10 : : *
11 : : * Software distributed under the License is distributed on an "AS IS" basis,
12 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : : * for the specific language governing rights and limitations under the
14 : : * License.
15 : : *
16 : : * The Initial Developer of the Original Code is
17 : : * [ Peter Jentsch <pjotr@guineapics.de> ]
18 : : * Portions created by the Initial Developer are Copyright (C) 2011 the
19 : : * Initial Developer. All Rights Reserved.
20 : : *
21 : : * Contributor(s): Peter Jentsch <pjotr@guineapics.de>
22 : : *
23 : : * Alternatively, the contents of this file may be used under the terms of
24 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : : * instead of those above.
28 : : */
29 : :
30 : :
31 : : #include <cstdio>
32 : : #include <cstring>
33 : : #include <list>
34 : : #include <map>
35 : : #include <vector>
36 : : #include <iostream>
37 : : #include <libxml/parser.h>
38 : : #include <libxml/tree.h>
39 : : #include <libxml/xmlIO.h>
40 : : #include <libxslt/transform.h>
41 : : #include <libxslt/xsltutils.h>
42 : : #include <libxslt/variables.h>
43 : :
44 : : #include <rtl/ustrbuf.hxx>
45 : :
46 : : #include <sax/tools/converter.hxx>
47 : :
48 : : #include <package/Inflater.hxx>
49 : : #include <package/Deflater.hxx>
50 : :
51 : : #include <cppuhelper/factory.hxx>
52 : : #include <cppuhelper/servicefactory.hxx>
53 : : #include <com/sun/star/uno/Any.hxx>
54 : : #include <com/sun/star/uno/XInterface.hpp>
55 : : #include <com/sun/star/container/XNameContainer.hpp>
56 : : #include <com/sun/star/io/XInputStream.hpp>
57 : : #include <com/sun/star/io/XOutputStream.hpp>
58 : : #include <com/sun/star/io/XSeekable.hpp>
59 : : #include <com/sun/star/embed/XTransactedObject.hpp>
60 : :
61 : : #include <OleHandler.hxx>
62 : :
63 : : using namespace ::com::sun::star::uno;
64 : : using namespace ::com::sun::star::lang;
65 : : using namespace ::com::sun::star::io;
66 : : using namespace ::com::sun::star::embed;
67 : : using namespace ::rtl;
68 : :
69 : :
70 : : namespace XSLT
71 : : {
72 : 0 : Reference<XStream> SAL_CALL OleHandler::createTempFile() {
73 : : Reference<XStream>
74 : : tempFile(
75 : 0 : m_msf->createInstance(
76 : : OUString(
77 : 0 : RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ))),
78 : 0 : UNO_QUERY);
79 : : OSL_ASSERT(tempFile.is());
80 : 0 : return tempFile;
81 : : }
82 : :
83 : 0 : void SAL_CALL OleHandler::ensureCreateRootStorage()
84 : : {
85 : 0 : if (m_storage == NULL || m_rootStream == NULL)
86 : : {
87 : 0 : m_rootStream = createTempFile();
88 : 0 : Sequence<Any> args(1);
89 : 0 : args[0] <<= m_rootStream->getInputStream();
90 : 0 : OUString serviceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.OLESimpleStorage"));
91 : :
92 : 0 : Reference<XNameContainer> cont(m_msf->createInstanceWithArguments(serviceName, args), UNO_QUERY);
93 : 0 : m_storage = cont;
94 : : }
95 : 0 : }
96 : :
97 : 0 : void SAL_CALL OleHandler::initRootStorageFromBase64(const OString& content)
98 : : {
99 : 0 : Sequence<sal_Int8> oleData;
100 : : ::sax::Converter::decodeBase64(oleData, ::rtl::OStringToOUString(
101 : 0 : content, RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS));
102 : 0 : m_rootStream = createTempFile();
103 : 0 : Reference<XOutputStream> xOutput = m_rootStream->getOutputStream();
104 : 0 : xOutput->writeBytes(oleData);
105 : 0 : xOutput->flush();
106 : : //Get the input stream and seek to begin
107 : 0 : Reference<XSeekable> xSeek(m_rootStream->getInputStream(), UNO_QUERY);
108 : 0 : xSeek->seek(0);
109 : :
110 : : //create an com.sun.star.embed.OLESimpleStorage from the temp stream
111 : 0 : Sequence<Any> args(1);
112 : 0 : args[0] <<= xSeek;
113 : 0 : Reference<XNameContainer> cont(m_msf->createInstanceWithArguments(OUString(
114 : 0 : RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), args), UNO_QUERY);
115 : 0 : m_storage = cont;
116 : 0 : }
117 : :
118 : : OString SAL_CALL
119 : 0 : OleHandler::encodeSubStorage(const OUString& streamName)
120 : : {
121 : 0 : if (!m_storage->hasByName(streamName))
122 : : {
123 : 0 : return "Not Found:";// + streamName;
124 : : }
125 : : ;
126 : 0 : Reference<XInputStream> subStream((*(Reference< XInterface > *) m_storage->getByName(streamName).getValue()), UNO_QUERY);
127 : 0 : if (!subStream.is())
128 : : {
129 : 0 : return "Not Found:";// + streamName;
130 : : }
131 : : //The first four byte are the length of the uncompressed data
132 : 0 : Sequence<sal_Int8> pLength(4);
133 : 0 : Reference<XSeekable> xSeek(subStream, UNO_QUERY);
134 : 0 : xSeek->seek(0);
135 : : //Get the uncompressed length
136 : 0 : int readbytes = subStream->readBytes(pLength, 4);
137 : 0 : if (4 != readbytes)
138 : : {
139 : 0 : return "Can not read the length.";
140 : : }
141 : 0 : int oleLength = (pLength[0] << 0) + (pLength[1] << 8)
142 : 0 : + (pLength[2] << 16) + (pLength[3] << 24);
143 : 0 : Sequence<sal_Int8> content(oleLength);
144 : : //Read all bytes. The compressed length should less then the uncompressed length
145 : 0 : readbytes = subStream->readBytes(content, oleLength);
146 : 0 : if (oleLength < readbytes)
147 : : {
148 : 0 : return "oleLength";// +oleLength + readBytes;
149 : : }
150 : :
151 : : // Decompress the bytes
152 : 0 : ::ZipUtils::Inflater* decompresser = new ::ZipUtils::Inflater(sal_False);
153 : 0 : decompresser->setInput(content);
154 : 0 : Sequence<sal_Int8> result(oleLength);
155 : 0 : decompresser->doInflateSegment(result, 0, oleLength);
156 : 0 : decompresser->end();
157 : 0 : delete decompresser;
158 : : //return the base64 string of the uncompressed data
159 : 0 : OUStringBuffer buf(oleLength);
160 : 0 : ::sax::Converter::encodeBase64(buf, result);
161 : 0 : return ::rtl::OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
162 : : }
163 : :
164 : : void SAL_CALL
165 : 0 : OleHandler::insertByName(const OUString& streamName, const OString& content)
166 : : {
167 : 0 : if ( streamName == "oledata.mso" )
168 : : {
169 : 0 : initRootStorageFromBase64(content);
170 : : }
171 : : else
172 : : {
173 : 0 : ensureCreateRootStorage();
174 : 0 : insertSubStorage(streamName, content);
175 : : }
176 : 0 : }
177 : :
178 : : const OString
179 : 0 : SAL_CALL OleHandler::getByName(const OUString& streamName)
180 : : {
181 : 0 : if ( streamName == "oledata.mso" )
182 : : {
183 : : //get the length and seek to 0
184 : 0 : Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
185 : 0 : int oleLength = (int) xSeek->getLength();
186 : 0 : xSeek->seek(0);
187 : : //read all bytes
188 : 0 : Reference<XInputStream> xInput = m_rootStream->getInputStream();
189 : 0 : Sequence<sal_Int8> oledata(oleLength);
190 : 0 : xInput->readBytes(oledata, oleLength);
191 : : //return the base64 encoded string
192 : 0 : OUStringBuffer buf(oleLength);
193 : 0 : ::sax::Converter::encodeBase64(buf, oledata);
194 : 0 : return ::rtl::OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
195 : : }
196 : 0 : return encodeSubStorage(streamName);
197 : : }
198 : :
199 : : void SAL_CALL
200 : 0 : OleHandler::insertSubStorage(const OUString& streamName, const OString& content)
201 : : {
202 : : //decode the base64 string
203 : 0 : Sequence<sal_Int8> oledata;
204 : : ::sax::Converter::decodeBase64(oledata,
205 : 0 : rtl::OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
206 : : //create a temp stream to write data to
207 : 0 : Reference<XStream> subStream = createTempFile();
208 : 0 : Reference<XInputStream> xInput = subStream->getInputStream();
209 : 0 : Reference<XOutputStream> xOutput = subStream->getOutputStream();
210 : : //write the length to the temp stream
211 : 0 : Sequence<sal_Int8> header(4);
212 : 0 : header[0] = (sal_Int8) (oledata.getLength() >> 0) & 0xFF;
213 : 0 : header[1] = (sal_Int8) (oledata.getLength() >> 8) & 0xFF;
214 : 0 : header[2] = (sal_Int8) (oledata.getLength() >> 16) & 0xFF;
215 : 0 : header[3] = (sal_Int8) (oledata.getLength() >> 24) & 0xFF;
216 : 0 : xOutput->writeBytes(header);
217 : :
218 : : // Compress the bytes
219 : 0 : Sequence<sal_Int8> output(oledata.getLength());
220 : 0 : ::ZipUtils::Deflater* compresser = new ::ZipUtils::Deflater((sal_Int32) 3, sal_False);
221 : 0 : compresser->setInputSegment(oledata, 0, oledata.getLength());
222 : 0 : compresser->finish();
223 : 0 : int compressedDataLength = compresser->doDeflateSegment(output, 0, oledata.getLength());
224 : 0 : delete(compresser);
225 : : //realloc the data length
226 : 0 : Sequence<sal_Int8> compressed(compressedDataLength);
227 : 0 : for (int i = 0; i < compressedDataLength; i++) {
228 : 0 : compressed[i] = output[i];
229 : : }
230 : :
231 : : //write the compressed data to the temp stream
232 : 0 : xOutput->writeBytes(compressed);
233 : : //seek to 0
234 : 0 : Reference<XSeekable> xSeek(xInput, UNO_QUERY);
235 : 0 : xSeek->seek(0);
236 : :
237 : : //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
238 : 0 : Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
239 : 0 : Any entry;
240 : 0 : entry <<= xInput;
241 : 0 : m_storage->insertByName(streamName, entry);
242 : 0 : xTransact->commit();
243 : 0 : }
244 : :
245 : :
246 : :
247 : 0 : }
248 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
249 : :
|