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 <comphelper/processfactory.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/TempFile.hpp>
57 : #include <com/sun/star/io/XInputStream.hpp>
58 : #include <com/sun/star/io/XOutputStream.hpp>
59 : #include <com/sun/star/io/XSeekable.hpp>
60 : #include <com/sun/star/embed/XTransactedObject.hpp>
61 :
62 : #include <OleHandler.hxx>
63 :
64 : using namespace ::com::sun::star::uno;
65 : using namespace ::com::sun::star::lang;
66 : using namespace ::com::sun::star::io;
67 : using namespace ::com::sun::star::embed;
68 : using namespace ::rtl;
69 :
70 :
71 : namespace XSLT
72 : {
73 0 : Reference<XStream> SAL_CALL OleHandler::createTempFile() {
74 : Reference<XStream> tempFile(
75 : TempFile::create(comphelper::getComponentContext(m_msf)),
76 0 : UNO_QUERY);
77 : OSL_ASSERT(tempFile.is());
78 0 : return tempFile;
79 : }
80 :
81 0 : void SAL_CALL OleHandler::ensureCreateRootStorage()
82 : {
83 0 : if (m_storage == NULL || m_rootStream == NULL)
84 : {
85 0 : m_rootStream = createTempFile();
86 0 : Sequence<Any> args(1);
87 0 : args[0] <<= m_rootStream->getInputStream();
88 0 : OUString serviceName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.OLESimpleStorage"));
89 :
90 0 : Reference<XNameContainer> cont(m_msf->createInstanceWithArguments(serviceName, args), UNO_QUERY);
91 0 : m_storage = cont;
92 : }
93 0 : }
94 :
95 0 : void SAL_CALL OleHandler::initRootStorageFromBase64(const OString& content)
96 : {
97 0 : Sequence<sal_Int8> oleData;
98 : ::sax::Converter::decodeBase64(oleData, ::rtl::OStringToOUString(
99 0 : content, RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS));
100 0 : m_rootStream = createTempFile();
101 0 : Reference<XOutputStream> xOutput = m_rootStream->getOutputStream();
102 0 : xOutput->writeBytes(oleData);
103 0 : xOutput->flush();
104 : //Get the input stream and seek to begin
105 0 : Reference<XSeekable> xSeek(m_rootStream->getInputStream(), UNO_QUERY);
106 0 : xSeek->seek(0);
107 :
108 : //create an com.sun.star.embed.OLESimpleStorage from the temp stream
109 0 : Sequence<Any> args(1);
110 0 : args[0] <<= xSeek;
111 0 : Reference<XNameContainer> cont(m_msf->createInstanceWithArguments(OUString(
112 0 : RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.OLESimpleStorage" )), args), UNO_QUERY);
113 0 : m_storage = cont;
114 0 : }
115 :
116 : OString SAL_CALL
117 0 : OleHandler::encodeSubStorage(const OUString& streamName)
118 : {
119 0 : if (!m_storage->hasByName(streamName))
120 : {
121 0 : return "Not Found:";// + streamName;
122 : }
123 : ;
124 0 : Reference<XInputStream> subStream((*(Reference< XInterface > *) m_storage->getByName(streamName).getValue()), UNO_QUERY);
125 0 : if (!subStream.is())
126 : {
127 0 : return "Not Found:";// + streamName;
128 : }
129 : //The first four byte are the length of the uncompressed data
130 0 : Sequence<sal_Int8> pLength(4);
131 0 : Reference<XSeekable> xSeek(subStream, UNO_QUERY);
132 0 : xSeek->seek(0);
133 : //Get the uncompressed length
134 0 : int readbytes = subStream->readBytes(pLength, 4);
135 0 : if (4 != readbytes)
136 : {
137 0 : return "Can not read the length.";
138 : }
139 0 : int oleLength = (pLength[0] << 0) + (pLength[1] << 8)
140 0 : + (pLength[2] << 16) + (pLength[3] << 24);
141 0 : Sequence<sal_Int8> content(oleLength);
142 : //Read all bytes. The compressed length should less then the uncompressed length
143 0 : readbytes = subStream->readBytes(content, oleLength);
144 0 : if (oleLength < readbytes)
145 : {
146 0 : return "oleLength";// +oleLength + readBytes;
147 : }
148 :
149 : // Decompress the bytes
150 0 : ::ZipUtils::Inflater* decompresser = new ::ZipUtils::Inflater(sal_False);
151 0 : decompresser->setInput(content);
152 0 : Sequence<sal_Int8> result(oleLength);
153 0 : decompresser->doInflateSegment(result, 0, oleLength);
154 0 : decompresser->end();
155 0 : delete decompresser;
156 : //return the base64 string of the uncompressed data
157 0 : OUStringBuffer buf(oleLength);
158 0 : ::sax::Converter::encodeBase64(buf, result);
159 0 : return ::rtl::OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
160 : }
161 :
162 : void SAL_CALL
163 0 : OleHandler::insertByName(const OUString& streamName, const OString& content)
164 : {
165 0 : if ( streamName == "oledata.mso" )
166 : {
167 0 : initRootStorageFromBase64(content);
168 : }
169 : else
170 : {
171 0 : ensureCreateRootStorage();
172 0 : insertSubStorage(streamName, content);
173 : }
174 0 : }
175 :
176 : const OString
177 0 : SAL_CALL OleHandler::getByName(const OUString& streamName)
178 : {
179 0 : if ( streamName == "oledata.mso" )
180 : {
181 : //get the length and seek to 0
182 0 : Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
183 0 : int oleLength = (int) xSeek->getLength();
184 0 : xSeek->seek(0);
185 : //read all bytes
186 0 : Reference<XInputStream> xInput = m_rootStream->getInputStream();
187 0 : Sequence<sal_Int8> oledata(oleLength);
188 0 : xInput->readBytes(oledata, oleLength);
189 : //return the base64 encoded string
190 0 : OUStringBuffer buf(oleLength);
191 0 : ::sax::Converter::encodeBase64(buf, oledata);
192 0 : return ::rtl::OUStringToOString(buf.toString(), RTL_TEXTENCODING_UTF8);
193 : }
194 0 : return encodeSubStorage(streamName);
195 : }
196 :
197 : void SAL_CALL
198 0 : OleHandler::insertSubStorage(const OUString& streamName, const OString& content)
199 : {
200 : //decode the base64 string
201 0 : Sequence<sal_Int8> oledata;
202 : ::sax::Converter::decodeBase64(oledata,
203 0 : rtl::OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
204 : //create a temp stream to write data to
205 0 : Reference<XStream> subStream = createTempFile();
206 0 : Reference<XInputStream> xInput = subStream->getInputStream();
207 0 : Reference<XOutputStream> xOutput = subStream->getOutputStream();
208 : //write the length to the temp stream
209 0 : Sequence<sal_Int8> header(4);
210 0 : header[0] = (sal_Int8) (oledata.getLength() >> 0) & 0xFF;
211 0 : header[1] = (sal_Int8) (oledata.getLength() >> 8) & 0xFF;
212 0 : header[2] = (sal_Int8) (oledata.getLength() >> 16) & 0xFF;
213 0 : header[3] = (sal_Int8) (oledata.getLength() >> 24) & 0xFF;
214 0 : xOutput->writeBytes(header);
215 :
216 : // Compress the bytes
217 0 : Sequence<sal_Int8> output(oledata.getLength());
218 0 : ::ZipUtils::Deflater* compresser = new ::ZipUtils::Deflater((sal_Int32) 3, sal_False);
219 0 : compresser->setInputSegment(oledata, 0, oledata.getLength());
220 0 : compresser->finish();
221 0 : int compressedDataLength = compresser->doDeflateSegment(output, 0, oledata.getLength());
222 0 : delete(compresser);
223 : //realloc the data length
224 0 : Sequence<sal_Int8> compressed(compressedDataLength);
225 0 : for (int i = 0; i < compressedDataLength; i++) {
226 0 : compressed[i] = output[i];
227 : }
228 :
229 : //write the compressed data to the temp stream
230 0 : xOutput->writeBytes(compressed);
231 : //seek to 0
232 0 : Reference<XSeekable> xSeek(xInput, UNO_QUERY);
233 0 : xSeek->seek(0);
234 :
235 : //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
236 0 : Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
237 0 : Any entry;
238 0 : entry <<= xInput;
239 0 : m_storage->insertByName(streamName, entry);
240 0 : xTransact->commit();
241 0 : }
242 :
243 :
244 :
245 0 : }
246 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
247 :
|