Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/io/NotConnectedException.hpp>
21 : #include <com/sun/star/io/BufferSizeExceededException.hpp>
22 : #include <com/sun/star/uno/RuntimeException.hpp>
23 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 : #include <ucbhelper/content.hxx>
25 : #include <com/sun/star/uno/Reference.h>
26 : #include <com/sun/star/ucb/NameClash.hpp>
27 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
28 : #include <unotools/tempfile.hxx>
29 : #include <unotools/ucbstreamhelper.hxx>
30 : #include <com/sun/star/io/XInputStream.hpp>
31 : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
32 : #include <com/sun/star/ucb/ResultSetException.hpp>
33 : #include <com/sun/star/uno/Sequence.h>
34 : #include <com/sun/star/sdbc/XResultSet.hpp>
35 : #include <com/sun/star/ucb/XContentAccess.hpp>
36 : #include <com/sun/star/sdbc/XRow.hpp>
37 : #include <com/sun/star/ucb/CommandAbortedException.hpp>
38 : #include <com/sun/star/datatransfer/DataFlavor.hpp>
39 : #include <com/sun/star/ucb/ContentInfo.hpp>
40 : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
41 : #include <com/sun/star/beans/Property.hpp>
42 : #include <com/sun/star/packages/manifest/ManifestWriter.hpp>
43 : #include <com/sun/star/packages/manifest/ManifestReader.hpp>
44 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
45 :
46 : #include <boost/scoped_array.hpp>
47 : #include <boost/scoped_ptr.hpp>
48 : #include <rtl/digest.h>
49 : #include <osl/diagnose.h>
50 : #include <tools/ref.hxx>
51 : #include <tools/debug.hxx>
52 : #include <unotools/streamhelper.hxx>
53 : #include <unotools/streamwrap.hxx>
54 : #include <unotools/ucbhelper.hxx>
55 : #include <unotools/localfilehelper.hxx>
56 : #include <tools/urlobj.hxx>
57 : #include <comphelper/processfactory.hxx>
58 : #include <cppuhelper/implbase2.hxx>
59 : #include <ucbhelper/commandenvironment.hxx>
60 :
61 : #include "sot/stg.hxx"
62 : #include "sot/storinfo.hxx"
63 : #include <sot/storage.hxx>
64 : #include <sot/exchange.hxx>
65 : #include <sot/formats.hxx>
66 : #include <comphelper/classids.hxx>
67 :
68 : #include <vector>
69 :
70 : using namespace ::com::sun::star::lang;
71 : using namespace ::com::sun::star::beans;
72 : using namespace ::com::sun::star::uno;
73 : using namespace ::com::sun::star::ucb;
74 : using namespace ::com::sun::star::io;
75 : using namespace ::com::sun::star::sdbc;
76 : using namespace ::ucbhelper;
77 :
78 : #if OSL_DEBUG_LEVEL > 1
79 : #include <stdio.h>
80 : static int nOpenFiles=0;
81 : static int nOpenStreams=0;
82 : #endif
83 :
84 : typedef ::cppu::WeakImplHelper2 < XInputStream, XSeekable > FileInputStreamWrapper_Base;
85 : class FileStreamWrapper_Impl : public FileInputStreamWrapper_Base
86 : {
87 : protected:
88 : ::osl::Mutex m_aMutex;
89 : OUString m_aURL;
90 : SvStream* m_pSvStream;
91 :
92 : public:
93 : FileStreamWrapper_Impl( const OUString& rName );
94 : virtual ~FileStreamWrapper_Impl();
95 :
96 : virtual void SAL_CALL seek( sal_Int64 _nLocation ) throw ( IllegalArgumentException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
97 : virtual sal_Int64 SAL_CALL getPosition( ) throw ( IOException, RuntimeException, std::exception) SAL_OVERRIDE;
98 : virtual sal_Int64 SAL_CALL getLength( ) throw ( IOException, RuntimeException, std::exception) SAL_OVERRIDE;
99 : virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception ) SAL_OVERRIDE;
100 : virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception ) SAL_OVERRIDE;
101 : virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception) SAL_OVERRIDE;
102 : virtual sal_Int32 SAL_CALL available() throw( NotConnectedException, RuntimeException, std::exception ) SAL_OVERRIDE;
103 : virtual void SAL_CALL closeInput() throw( NotConnectedException, RuntimeException, std::exception ) SAL_OVERRIDE;
104 :
105 : protected:
106 : void checkConnected();
107 : void checkError();
108 : };
109 :
110 :
111 0 : FileStreamWrapper_Impl::FileStreamWrapper_Impl( const OUString& rName )
112 : : m_aURL( rName )
113 0 : , m_pSvStream(0)
114 : {
115 : // if no URL is provided the stream is empty
116 0 : }
117 :
118 :
119 0 : FileStreamWrapper_Impl::~FileStreamWrapper_Impl()
120 : {
121 0 : if ( m_pSvStream )
122 : {
123 0 : delete m_pSvStream;
124 : #if OSL_DEBUG_LEVEL > 1
125 : --nOpenFiles;
126 : #endif
127 : }
128 :
129 0 : if ( !m_aURL.isEmpty() )
130 0 : ::utl::UCBContentHelper::Kill( m_aURL );
131 0 : }
132 :
133 :
134 0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
135 : throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
136 : {
137 0 : if ( m_aURL.isEmpty() )
138 : {
139 0 : aData.realloc( 0 );
140 0 : return 0;
141 : }
142 :
143 0 : checkConnected();
144 :
145 0 : if (nBytesToRead < 0)
146 0 : throw BufferSizeExceededException(OUString(),static_cast<XWeak*>(this));
147 :
148 0 : ::osl::MutexGuard aGuard( m_aMutex );
149 :
150 0 : aData.realloc(nBytesToRead);
151 :
152 0 : sal_uInt32 nRead = m_pSvStream->Read(static_cast<void*>(aData.getArray()), nBytesToRead);
153 0 : checkError();
154 :
155 : // Wenn gelesene Zeichen < MaxLength, Sequence anpassen
156 0 : if (nRead < (sal_uInt32)nBytesToRead)
157 0 : aData.realloc( nRead );
158 :
159 0 : return nRead;
160 : }
161 :
162 :
163 0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
164 : {
165 0 : if ( m_aURL.isEmpty() )
166 : {
167 0 : aData.realloc( 0 );
168 0 : return 0;
169 : }
170 :
171 0 : checkError();
172 :
173 0 : if (nMaxBytesToRead < 0)
174 0 : throw BufferSizeExceededException(OUString(),static_cast<XWeak*>(this));
175 :
176 0 : if (m_pSvStream->IsEof())
177 : {
178 0 : aData.realloc(0);
179 0 : return 0;
180 : }
181 : else
182 0 : return readBytes(aData, nMaxBytesToRead);
183 : }
184 :
185 :
186 0 : void SAL_CALL FileStreamWrapper_Impl::skipBytes(sal_Int32 nBytesToSkip) throw( NotConnectedException, BufferSizeExceededException, RuntimeException, std::exception )
187 : {
188 0 : if ( m_aURL.isEmpty() )
189 0 : return;
190 :
191 0 : ::osl::MutexGuard aGuard( m_aMutex );
192 0 : checkError();
193 :
194 0 : m_pSvStream->SeekRel(nBytesToSkip);
195 0 : checkError();
196 : }
197 :
198 :
199 0 : sal_Int32 SAL_CALL FileStreamWrapper_Impl::available() throw( NotConnectedException, RuntimeException, std::exception )
200 : {
201 0 : if ( m_aURL.isEmpty() )
202 0 : return 0;
203 :
204 0 : ::osl::MutexGuard aGuard( m_aMutex );
205 0 : checkConnected();
206 :
207 0 : sal_uInt32 nPos = m_pSvStream->Tell();
208 0 : checkError();
209 :
210 0 : m_pSvStream->Seek(STREAM_SEEK_TO_END);
211 0 : checkError();
212 :
213 0 : sal_Int32 nAvailable = (sal_Int32)m_pSvStream->Tell() - nPos;
214 0 : m_pSvStream->Seek(nPos);
215 0 : checkError();
216 :
217 0 : return nAvailable;
218 : }
219 :
220 :
221 0 : void SAL_CALL FileStreamWrapper_Impl::closeInput() throw( NotConnectedException, RuntimeException, std::exception )
222 : {
223 0 : if ( m_aURL.isEmpty() )
224 0 : return;
225 :
226 0 : ::osl::MutexGuard aGuard( m_aMutex );
227 0 : checkConnected();
228 0 : DELETEZ( m_pSvStream );
229 : #if OSL_DEBUG_LEVEL > 1
230 : --nOpenFiles;
231 : #endif
232 0 : ::utl::UCBContentHelper::Kill( m_aURL );
233 0 : m_aURL.clear();
234 : }
235 :
236 :
237 0 : void SAL_CALL FileStreamWrapper_Impl::seek( sal_Int64 _nLocation ) throw (IllegalArgumentException, IOException, RuntimeException, std::exception)
238 : {
239 0 : if ( m_aURL.isEmpty() )
240 0 : return;
241 :
242 0 : ::osl::MutexGuard aGuard( m_aMutex );
243 0 : checkConnected();
244 :
245 0 : m_pSvStream->Seek((sal_uInt32)_nLocation);
246 0 : checkError();
247 : }
248 :
249 :
250 0 : sal_Int64 SAL_CALL FileStreamWrapper_Impl::getPosition( ) throw (IOException, RuntimeException, std::exception)
251 : {
252 0 : if ( m_aURL.isEmpty() )
253 0 : return 0;
254 :
255 0 : ::osl::MutexGuard aGuard( m_aMutex );
256 0 : checkConnected();
257 :
258 0 : sal_uInt32 nPos = m_pSvStream->Tell();
259 0 : checkError();
260 0 : return (sal_Int64)nPos;
261 : }
262 :
263 :
264 0 : sal_Int64 SAL_CALL FileStreamWrapper_Impl::getLength( ) throw (IOException, RuntimeException, std::exception)
265 : {
266 0 : if ( m_aURL.isEmpty() )
267 0 : return 0;
268 :
269 0 : ::osl::MutexGuard aGuard( m_aMutex );
270 0 : checkConnected();
271 :
272 0 : sal_uInt32 nCurrentPos = m_pSvStream->Tell();
273 0 : checkError();
274 :
275 0 : m_pSvStream->Seek(STREAM_SEEK_TO_END);
276 0 : sal_uInt32 nEndPos = m_pSvStream->Tell();
277 0 : m_pSvStream->Seek(nCurrentPos);
278 :
279 0 : checkError();
280 :
281 0 : return (sal_Int64)nEndPos;
282 : }
283 :
284 :
285 0 : void FileStreamWrapper_Impl::checkConnected()
286 : {
287 0 : if ( m_aURL.isEmpty() )
288 0 : throw NotConnectedException(OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this)));
289 0 : if ( !m_pSvStream )
290 : {
291 0 : m_pSvStream = ::utl::UcbStreamHelper::CreateStream( m_aURL, STREAM_STD_READ );
292 : #if OSL_DEBUG_LEVEL > 1
293 : ++nOpenFiles;
294 : #endif
295 : }
296 0 : }
297 :
298 :
299 0 : void FileStreamWrapper_Impl::checkError()
300 : {
301 0 : checkConnected();
302 :
303 0 : if (m_pSvStream->SvStream::GetError() != ERRCODE_NONE)
304 : // TODO: really evaluate the error
305 0 : throw NotConnectedException(OUString(), const_cast<XWeak*>(static_cast<const XWeak*>(this)));
306 0 : }
307 :
308 0 : TYPEINIT1( UCBStorageStream, BaseStorageStream );
309 10157 : TYPEINIT1( UCBStorage, BaseStorage );
310 :
311 : #define COMMIT_RESULT_FAILURE 0
312 : #define COMMIT_RESULT_NOTHING_TO_DO 1
313 : #define COMMIT_RESULT_SUCCESS 2
314 :
315 : #define min( x, y ) (( x < y ) ? x : y)
316 :
317 0 : SotClipboardFormatId GetFormatId_Impl( SvGlobalName aName )
318 : {
319 0 : if ( aName == SvGlobalName( SO3_SW_CLASSID_60 ) )
320 0 : return SotClipboardFormatId::STARWRITER_60;
321 0 : if ( aName == SvGlobalName( SO3_SWWEB_CLASSID_60 ) )
322 0 : return SotClipboardFormatId::STARWRITERWEB_60;
323 0 : if ( aName == SvGlobalName( SO3_SWGLOB_CLASSID_60 ) )
324 0 : return SotClipboardFormatId::STARWRITERGLOB_60;
325 0 : if ( aName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
326 0 : return SotClipboardFormatId::STARDRAW_60;
327 0 : if ( aName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
328 0 : return SotClipboardFormatId::STARIMPRESS_60;
329 0 : if ( aName == SvGlobalName( SO3_SC_CLASSID_60 ) )
330 0 : return SotClipboardFormatId::STARCALC_60;
331 0 : if ( aName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
332 0 : return SotClipboardFormatId::STARCHART_60;
333 0 : if ( aName == SvGlobalName( SO3_SM_CLASSID_60 ) )
334 0 : return SotClipboardFormatId::STARMATH_60;
335 0 : if ( aName == SvGlobalName( SO3_OUT_CLASSID ) ||
336 0 : aName == SvGlobalName( SO3_APPLET_CLASSID ) ||
337 0 : aName == SvGlobalName( SO3_PLUGIN_CLASSID ) ||
338 0 : aName == SvGlobalName( SO3_IFRAME_CLASSID ) )
339 : // allowed, but not supported
340 0 : return SotClipboardFormatId::NONE;
341 : else
342 : {
343 : OSL_FAIL( "Unknown UCB storage format!" );
344 0 : return SotClipboardFormatId::NONE;
345 : }
346 : }
347 :
348 :
349 0 : SvGlobalName GetClassId_Impl( SotClipboardFormatId nFormat )
350 : {
351 0 : switch ( nFormat )
352 : {
353 : case SotClipboardFormatId::STARWRITER_8 :
354 : case SotClipboardFormatId::STARWRITER_8_TEMPLATE :
355 0 : return SvGlobalName( SO3_SW_CLASSID_60 );
356 : case SotClipboardFormatId::STARWRITERWEB_8 :
357 0 : return SvGlobalName( SO3_SWWEB_CLASSID_60 );
358 : case SotClipboardFormatId::STARWRITERGLOB_8 :
359 : case SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE :
360 0 : return SvGlobalName( SO3_SWGLOB_CLASSID_60 );
361 : case SotClipboardFormatId::STARDRAW_8 :
362 : case SotClipboardFormatId::STARDRAW_8_TEMPLATE :
363 0 : return SvGlobalName( SO3_SDRAW_CLASSID_60 );
364 : case SotClipboardFormatId::STARIMPRESS_8 :
365 : case SotClipboardFormatId::STARIMPRESS_8_TEMPLATE :
366 0 : return SvGlobalName( SO3_SIMPRESS_CLASSID_60 );
367 : case SotClipboardFormatId::STARCALC_8 :
368 : case SotClipboardFormatId::STARCALC_8_TEMPLATE :
369 0 : return SvGlobalName( SO3_SC_CLASSID_60 );
370 : case SotClipboardFormatId::STARCHART_8 :
371 : case SotClipboardFormatId::STARCHART_8_TEMPLATE :
372 0 : return SvGlobalName( SO3_SCH_CLASSID_60 );
373 : case SotClipboardFormatId::STARMATH_8 :
374 : case SotClipboardFormatId::STARMATH_8_TEMPLATE :
375 0 : return SvGlobalName( SO3_SM_CLASSID_60 );
376 : case SotClipboardFormatId::STARWRITER_60 :
377 0 : return SvGlobalName( SO3_SW_CLASSID_60 );
378 : case SotClipboardFormatId::STARWRITERWEB_60 :
379 0 : return SvGlobalName( SO3_SWWEB_CLASSID_60 );
380 : case SotClipboardFormatId::STARWRITERGLOB_60 :
381 0 : return SvGlobalName( SO3_SWGLOB_CLASSID_60 );
382 : case SotClipboardFormatId::STARDRAW_60 :
383 0 : return SvGlobalName( SO3_SDRAW_CLASSID_60 );
384 : case SotClipboardFormatId::STARIMPRESS_60 :
385 0 : return SvGlobalName( SO3_SIMPRESS_CLASSID_60 );
386 : case SotClipboardFormatId::STARCALC_60 :
387 0 : return SvGlobalName( SO3_SC_CLASSID_60 );
388 : case SotClipboardFormatId::STARCHART_60 :
389 0 : return SvGlobalName( SO3_SCH_CLASSID_60 );
390 : case SotClipboardFormatId::STARMATH_60 :
391 0 : return SvGlobalName( SO3_SM_CLASSID_60 );
392 : default :
393 0 : return SvGlobalName();
394 : }
395 : }
396 :
397 : // All storage and streams are refcounted internally; outside of this classes they are only accessible through a handle
398 : // class, that uses the refcounted object as impl-class.
399 :
400 : enum RepresentModes {
401 : nonset,
402 : svstream,
403 : xinputstream
404 : };
405 :
406 : class UCBStorageStream_Impl : public SvRefBase, public SvStream
407 : {
408 : virtual ~UCBStorageStream_Impl();
409 : public:
410 :
411 : virtual sal_uLong GetData( void* pData, sal_uLong nSize ) SAL_OVERRIDE;
412 : virtual sal_uLong PutData( const void* pData, sal_uLong nSize ) SAL_OVERRIDE;
413 : virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) SAL_OVERRIDE;
414 : virtual void SetSize( sal_uInt64 nSize ) SAL_OVERRIDE;
415 : virtual void FlushData() SAL_OVERRIDE;
416 : virtual void ResetError() SAL_OVERRIDE;
417 :
418 : UCBStorageStream* m_pAntiImpl; // only valid if an external reference exists
419 :
420 : OUString m_aOriginalName;// the original name before accessing the stream
421 : OUString m_aName; // the actual name ( changed with a Rename command at the parent )
422 : OUString m_aURL; // the full path name to create the content
423 : OUString m_aContentType;
424 : OUString m_aOriginalContentType;
425 : OString m_aKey;
426 : ::ucbhelper::Content* m_pContent; // the content that provides the data
427 : Reference<XInputStream> m_rSource; // the stream covering the original data of the content
428 : SvStream* m_pStream; // the stream worked on; for readonly streams it is the original stream of the content
429 : // for read/write streams it's a copy into a temporary file
430 : OUString m_aTempURL; // URL of this temporary stream
431 : RepresentModes m_nRepresentMode; // should it be used as XInputStream or as SvStream
432 : long m_nError;
433 : StreamMode m_nMode; // open mode ( read/write/trunc/nocreate/sharing )
434 : bool m_bSourceRead; // Source still contains useful information
435 : bool m_bModified; // only modified streams will be sent to the original content
436 : bool m_bCommited; // sending the streams is coordinated by the root storage of the package
437 : bool m_bDirect; // the storage and its streams are opened in direct mode; for UCBStorages
438 : // this means that the root storage does an autocommit when its external
439 : // reference is destroyed
440 : bool m_bIsOLEStorage;// an OLEStorage on a UCBStorageStream makes this an Autocommit-stream
441 :
442 : UCBStorageStream_Impl( const OUString&, StreamMode, UCBStorageStream*, bool, const OString* pKey=0,
443 : bool bRepair = false, Reference< XProgressHandler > xProgress = Reference< XProgressHandler >() );
444 :
445 : void Free();
446 : bool Init();
447 : bool Clear();
448 : sal_Int16 Commit(); // if modified and committed: transfer an XInputStream to the content
449 : bool Revert(); // discard all changes
450 : BaseStorage* CreateStorage();// create an OLE Storage on the UCBStorageStream
451 : sal_uLong GetSize();
452 :
453 : sal_uInt64 ReadSourceWriteTemporary( sal_uInt64 aLength ); // read aLength from source and copy to temporary,
454 : // no seeking is produced
455 : sal_uLong ReadSourceWriteTemporary(); // read source till the end and copy to temporary,
456 :
457 : sal_uLong CopySourceToTemporary(); // same as ReadSourceWriteToTemporary()
458 : // but the writing is done at the end of temporary
459 : // pointer position is not changed
460 : using SvStream::SetError;
461 : void SetError( sal_uInt32 nError );
462 : void PrepareCachedForReopen( StreamMode nMode );
463 : };
464 :
465 : typedef tools::SvRef<UCBStorageStream_Impl> UCBStorageStream_ImplRef;
466 :
467 : struct UCBStorageElement_Impl;
468 : typedef ::std::vector< UCBStorageElement_Impl* > UCBStorageElementList_Impl;
469 :
470 : class UCBStorage_Impl : public SvRefBase
471 : {
472 : virtual ~UCBStorage_Impl();
473 : public:
474 : UCBStorage* m_pAntiImpl; // only valid if external references exists
475 :
476 : OUString m_aOriginalName;// the original name before accessing the storage
477 : OUString m_aName; // the actual name ( changed with a Rename command at the parent )
478 : OUString m_aURL; // the full path name to create the content
479 : OUString m_aContentType;
480 : OUString m_aOriginalContentType;
481 : ::ucbhelper::Content* m_pContent; // the content that provides the storage elements
482 : ::utl::TempFile* m_pTempFile; // temporary file, only for storages on stream
483 : SvStream* m_pSource; // original stream, only for storages on a stream
484 : long m_nError;
485 : StreamMode m_nMode; // open mode ( read/write/trunc/nocreate/sharing )
486 : bool m_bModified; // only modified elements will be sent to the original content
487 : bool m_bCommited; // sending the streams is coordinated by the root storage of the package
488 : bool m_bDirect; // the storage and its streams are opened in direct mode; for UCBStorages
489 : // this means that the root storage does an autocommit when its external
490 : // reference is destroyed
491 : bool m_bIsRoot; // marks this storage as root storages that manages all oommits and reverts
492 : bool m_bDirty; // ???
493 : bool m_bIsLinked;
494 : bool m_bListCreated;
495 : SotClipboardFormatId m_nFormat;
496 : OUString m_aUserTypeName;
497 : SvGlobalName m_aClassId;
498 :
499 : UCBStorageElementList_Impl m_aChildrenList;
500 :
501 : bool m_bRepairPackage;
502 : Reference< XProgressHandler > m_xProgressHandler;
503 :
504 : UCBStorage_Impl( const ::ucbhelper::Content&, const OUString&, StreamMode, UCBStorage*, bool,
505 : bool, bool = false, Reference< XProgressHandler > = Reference< XProgressHandler >() );
506 : UCBStorage_Impl( const OUString&, StreamMode, UCBStorage*, bool, bool,
507 : bool = false, Reference< XProgressHandler > = Reference< XProgressHandler >() );
508 : UCBStorage_Impl( SvStream&, UCBStorage*, bool );
509 : void Init();
510 : sal_Int16 Commit();
511 : bool Revert();
512 : bool Insert( ::ucbhelper::Content *pContent );
513 : UCBStorage_Impl* OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect );
514 : UCBStorageStream_Impl* OpenStream( UCBStorageElement_Impl*, StreamMode, bool, const OString* pKey=0 );
515 : void SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& );
516 : void GetProps( sal_Int32&, Sequence < Sequence < PropertyValue > >& rSequence, const OUString& );
517 : sal_Int32 GetObjectCount();
518 : void ReadContent();
519 : void CreateContent();
520 2006 : ::ucbhelper::Content* GetContent()
521 2006 : { if ( !m_pContent ) CreateContent(); return m_pContent; }
522 4012 : UCBStorageElementList_Impl& GetChildrenList()
523 : {
524 4012 : long nError = m_nError;
525 4012 : ReadContent();
526 4012 : if ( m_nMode & StreamMode::WRITE )
527 : {
528 4012 : m_nError = nError;
529 4012 : if ( m_pAntiImpl )
530 : {
531 4012 : m_pAntiImpl->ResetError();
532 4012 : m_pAntiImpl->SetError( nError );
533 : }
534 : }
535 :
536 4012 : return m_aChildrenList;
537 : }
538 :
539 : void SetError( long nError );
540 : };
541 :
542 : typedef tools::SvRef<UCBStorage_Impl> UCBStorage_ImplRef;
543 :
544 : // this struct contains all necessary information on an element inside a UCBStorage
545 0 : struct UCBStorageElement_Impl
546 : {
547 : OUString m_aName; // the actual URL relative to the root "folder"
548 : OUString m_aOriginalName;// the original name in the content
549 : sal_uLong m_nSize;
550 : bool m_bIsFolder; // Only true when it is a UCBStorage !
551 : bool m_bIsStorage; // Also true when it is an OLEStorage !
552 : bool m_bIsRemoved; // element will be removed on commit
553 : bool m_bIsInserted; // element will be removed on revert
554 : UCBStorage_ImplRef m_xStorage; // reference to the "real" storage
555 : UCBStorageStream_ImplRef m_xStream; // reference to the "real" stream
556 :
557 0 : UCBStorageElement_Impl( const OUString& rName,
558 : bool bIsFolder = false, sal_uLong nSize = 0 )
559 : : m_aName( rName )
560 : , m_aOriginalName( rName )
561 : , m_nSize( nSize )
562 : , m_bIsFolder( bIsFolder )
563 : , m_bIsStorage( bIsFolder )
564 : , m_bIsRemoved( false )
565 0 : , m_bIsInserted( false )
566 : {
567 0 : }
568 :
569 : ::ucbhelper::Content* GetContent();
570 : bool IsModified();
571 : OUString GetContentType();
572 : void SetContentType( const OUString& );
573 : OUString GetOriginalContentType();
574 0 : bool IsLoaded()
575 0 : { return m_xStream.Is() || m_xStorage.Is(); }
576 : };
577 :
578 0 : ::ucbhelper::Content* UCBStorageElement_Impl::GetContent()
579 : {
580 0 : if ( m_xStream.Is() )
581 0 : return m_xStream->m_pContent;
582 0 : else if ( m_xStorage.Is() )
583 0 : return m_xStorage->GetContent();
584 : else
585 0 : return NULL;
586 : }
587 :
588 0 : OUString UCBStorageElement_Impl::GetContentType()
589 : {
590 0 : if ( m_xStream.Is() )
591 0 : return m_xStream->m_aContentType;
592 0 : else if ( m_xStorage.Is() )
593 0 : return m_xStorage->m_aContentType;
594 : else
595 : {
596 : OSL_FAIL("Element not loaded!");
597 0 : return OUString();
598 : }
599 : }
600 :
601 0 : void UCBStorageElement_Impl::SetContentType( const OUString& rType )
602 : {
603 0 : if ( m_xStream.Is() ) {
604 0 : m_xStream->m_aContentType = m_xStream->m_aOriginalContentType = rType;
605 : }
606 0 : else if ( m_xStorage.Is() ) {
607 0 : m_xStorage->m_aContentType = m_xStorage->m_aOriginalContentType = rType;
608 : }
609 : else {
610 : OSL_FAIL("Element not loaded!");
611 : }
612 0 : }
613 :
614 0 : OUString UCBStorageElement_Impl::GetOriginalContentType()
615 : {
616 0 : if ( m_xStream.Is() )
617 0 : return m_xStream->m_aOriginalContentType;
618 0 : else if ( m_xStorage.Is() )
619 0 : return m_xStorage->m_aOriginalContentType;
620 : else
621 0 : return OUString();
622 : }
623 :
624 0 : bool UCBStorageElement_Impl::IsModified()
625 : {
626 0 : bool bModified = m_bIsRemoved || m_bIsInserted || m_aName != m_aOriginalName;
627 0 : if ( bModified )
628 : {
629 0 : if ( m_xStream.Is() )
630 0 : bModified = m_xStream->m_aContentType != m_xStream->m_aOriginalContentType;
631 0 : else if ( m_xStorage.Is() )
632 0 : bModified = m_xStorage->m_aContentType != m_xStorage->m_aOriginalContentType;
633 : }
634 :
635 0 : return bModified;
636 : }
637 :
638 0 : UCBStorageStream_Impl::UCBStorageStream_Impl( const OUString& rName, StreamMode nMode, UCBStorageStream* pStream, bool bDirect, const OString* pKey, bool bRepair, Reference< XProgressHandler > xProgress )
639 : : m_pAntiImpl( pStream )
640 : , m_aURL( rName )
641 : , m_pContent( NULL )
642 : , m_pStream( NULL )
643 : , m_nRepresentMode( nonset )
644 : , m_nError( 0 )
645 : , m_nMode( nMode )
646 0 : , m_bSourceRead( !( nMode & StreamMode::TRUNC ) )
647 : , m_bModified( false )
648 : , m_bCommited( false )
649 : , m_bDirect( bDirect )
650 0 : , m_bIsOLEStorage( false )
651 : {
652 : // name is last segment in URL
653 0 : INetURLObject aObj( rName );
654 0 : m_aName = m_aOriginalName = aObj.GetLastName();
655 : try
656 : {
657 : // create the content
658 0 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
659 :
660 0 : OUString aTemp( rName );
661 :
662 0 : if ( bRepair )
663 : {
664 0 : xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
665 0 : xProgress );
666 0 : aTemp += "?repairpackage";
667 : }
668 :
669 0 : m_pContent = new ::ucbhelper::Content( aTemp, xComEnv, comphelper::getProcessComponentContext() );
670 :
671 0 : if ( pKey )
672 : {
673 0 : m_aKey = *pKey;
674 :
675 : // stream is encrypted and should be decrypted (without setting the key we'll get the raw data)
676 : sal_uInt8 aBuffer[RTL_DIGEST_LENGTH_SHA1];
677 0 : rtlDigestError nErr = rtl_digest_SHA1( pKey->getStr(), pKey->getLength(), aBuffer, RTL_DIGEST_LENGTH_SHA1 );
678 0 : if ( nErr == rtl_Digest_E_None )
679 : {
680 0 : sal_uInt8* pBuffer = aBuffer;
681 0 : ::com::sun::star::uno::Sequence < sal_Int8 > aSequ( reinterpret_cast<sal_Int8*>(pBuffer), RTL_DIGEST_LENGTH_SHA1 );
682 0 : ::com::sun::star::uno::Any aAny;
683 0 : aAny <<= aSequ;
684 0 : m_pContent->setPropertyValue("EncryptionKey", aAny );
685 : }
686 0 : }
687 : }
688 0 : catch (const ContentCreationException&)
689 : {
690 : // content could not be created
691 0 : SetError( SVSTREAM_CANNOT_MAKE );
692 : }
693 0 : catch (const RuntimeException&)
694 : {
695 : // any other error - not specified
696 0 : SetError( ERRCODE_IO_GENERAL );
697 0 : }
698 0 : }
699 :
700 0 : UCBStorageStream_Impl::~UCBStorageStream_Impl()
701 : {
702 0 : if( m_rSource.is() )
703 0 : m_rSource.clear();
704 :
705 0 : if( m_pStream )
706 0 : delete m_pStream;
707 :
708 0 : if ( !m_aTempURL.isEmpty() )
709 0 : ::utl::UCBContentHelper::Kill( m_aTempURL );
710 :
711 0 : if( m_pContent )
712 0 : delete m_pContent;
713 0 : }
714 :
715 :
716 0 : bool UCBStorageStream_Impl::Init()
717 : {
718 0 : if( m_nRepresentMode == xinputstream )
719 : {
720 : OSL_FAIL( "XInputStream misuse!" );
721 0 : SetError( ERRCODE_IO_ACCESSDENIED );
722 0 : return false;
723 : }
724 :
725 0 : if( !m_pStream )
726 : {
727 : // no temporary stream was created
728 : // create one
729 :
730 0 : m_nRepresentMode = svstream; // can not be used as XInputStream
731 :
732 0 : if ( m_aTempURL.isEmpty() )
733 0 : m_aTempURL = ::utl::TempFile().GetURL();
734 :
735 0 : m_pStream = ::utl::UcbStreamHelper::CreateStream( m_aTempURL, STREAM_STD_READWRITE, true /* bFileExists */ );
736 : #if OSL_DEBUG_LEVEL > 1
737 : ++nOpenFiles;
738 : #endif
739 :
740 0 : if( !m_pStream )
741 : {
742 : OSL_FAIL( "Suspicious temporary stream creation!" );
743 0 : SetError( SVSTREAM_CANNOT_MAKE );
744 0 : return false;
745 : }
746 :
747 0 : SetError( m_pStream->GetError() );
748 : }
749 :
750 0 : if( m_bSourceRead && !m_rSource.is() )
751 : {
752 : // source file contain useful information and is not opened
753 : // open it from the point of noncopied data
754 :
755 : try
756 : {
757 0 : m_rSource = m_pContent->openStream();
758 : }
759 0 : catch (const Exception&)
760 : {
761 : // usually means that stream could not be opened
762 : }
763 :
764 0 : if( m_rSource.is() )
765 : {
766 0 : m_pStream->Seek( STREAM_SEEK_TO_END );
767 :
768 : try
769 : {
770 0 : m_rSource->skipBytes( m_pStream->Tell() );
771 : }
772 0 : catch (const BufferSizeExceededException&)
773 : {
774 : // the temporary stream already contain all the data
775 0 : m_bSourceRead = false;
776 : }
777 0 : catch (const Exception&)
778 : {
779 : // something is really wrong
780 0 : m_bSourceRead = false;
781 : OSL_FAIL( "Can not operate original stream!" );
782 0 : SetError( SVSTREAM_CANNOT_MAKE );
783 : }
784 :
785 0 : m_pStream->Seek( 0 );
786 : }
787 : else
788 : {
789 : // if the new file is edited than no source exist
790 0 : m_bSourceRead = false;
791 : //SetError( SVSTREAM_CANNOT_MAKE );
792 : }
793 : }
794 :
795 : DBG_ASSERT( m_rSource.is() || !m_bSourceRead, "Unreadable source stream!" );
796 :
797 0 : return true;
798 : }
799 :
800 0 : sal_uLong UCBStorageStream_Impl::ReadSourceWriteTemporary()
801 : {
802 : // read source stream till the end and copy all the data to
803 : // the current position of the temporary stream
804 :
805 0 : sal_uLong aResult = 0;
806 :
807 0 : if( m_bSourceRead )
808 : {
809 0 : Sequence<sal_Int8> aData(32000);
810 :
811 : try
812 : {
813 : sal_uLong aReaded;
814 0 : do
815 : {
816 0 : aReaded = m_rSource->readBytes( aData, 32000 );
817 0 : aResult += m_pStream->Write( aData.getArray(), aReaded );
818 : } while( aReaded == 32000 );
819 : }
820 0 : catch (const Exception &e)
821 : {
822 : OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
823 : (void)e;
824 0 : }
825 : }
826 :
827 0 : m_bSourceRead = false;
828 :
829 0 : return aResult;
830 :
831 : }
832 :
833 0 : sal_uInt64 UCBStorageStream_Impl::ReadSourceWriteTemporary(sal_uInt64 aLength)
834 : {
835 : // read aLength bite from the source stream and copy them to the current
836 : // position of the temporary stream
837 :
838 0 : sal_uInt64 aResult = 0;
839 :
840 0 : if( m_bSourceRead )
841 : {
842 0 : Sequence<sal_Int8> aData(32000);
843 :
844 : try
845 : {
846 :
847 0 : sal_uLong aReaded = 32000;
848 :
849 0 : for (sal_uInt64 pInd = 0; pInd < aLength && aReaded == 32000 ; pInd += 32000)
850 : {
851 0 : sal_uLong aToCopy = min( aLength - pInd, 32000 );
852 0 : aReaded = m_rSource->readBytes( aData, aToCopy );
853 0 : aResult += m_pStream->Write( aData.getArray(), aReaded );
854 : }
855 :
856 0 : if( aResult < aLength )
857 0 : m_bSourceRead = false;
858 : }
859 0 : catch( const Exception & e )
860 : {
861 : OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
862 : (void)e;
863 0 : }
864 : }
865 :
866 0 : return aResult;
867 : }
868 :
869 0 : sal_uLong UCBStorageStream_Impl::CopySourceToTemporary()
870 : {
871 : // current position of the temporary stream is not changed
872 0 : sal_uLong aResult = 0;
873 :
874 0 : if( m_bSourceRead )
875 : {
876 0 : sal_uLong aPos = m_pStream->Tell();
877 0 : m_pStream->Seek( STREAM_SEEK_TO_END );
878 0 : aResult = ReadSourceWriteTemporary();
879 0 : m_pStream->Seek( aPos );
880 : }
881 :
882 0 : return aResult;
883 :
884 : }
885 :
886 : // UCBStorageStream_Impl must have a SvStream interface, because it then can be used as underlying stream
887 : // of an OLEStorage; so every write access caused by storage operations marks the UCBStorageStream as modified
888 0 : sal_uLong UCBStorageStream_Impl::GetData( void* pData, sal_uLong nSize )
889 : {
890 0 : sal_uLong aResult = 0;
891 :
892 0 : if( !Init() )
893 0 : return 0;
894 :
895 :
896 : // read data that is in temporary stream
897 0 : aResult = m_pStream->Read( pData, nSize );
898 0 : if( m_bSourceRead && aResult < nSize )
899 : {
900 : // read the tail of the data from original stream
901 : // copy this tail to the temporary stream
902 :
903 0 : sal_uLong aToRead = nSize - aResult;
904 0 : pData = static_cast<void*>( static_cast<char*>(pData) + aResult );
905 :
906 : try
907 : {
908 0 : Sequence<sal_Int8> aData( aToRead );
909 0 : sal_uLong aReaded = m_rSource->readBytes( aData, aToRead );
910 0 : aResult += m_pStream->Write( static_cast<void*>(aData.getArray()), aReaded );
911 0 : memcpy( pData, aData.getArray(), aReaded );
912 : }
913 0 : catch (const Exception &e)
914 : {
915 : OSL_FAIL( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
916 : (void)e;
917 : }
918 :
919 0 : if( aResult < nSize )
920 0 : m_bSourceRead = false;
921 : }
922 :
923 0 : return aResult;
924 : }
925 :
926 0 : sal_uLong UCBStorageStream_Impl::PutData( const void* pData, sal_uLong nSize )
927 : {
928 0 : if ( !(m_nMode & StreamMode::WRITE) )
929 : {
930 0 : SetError( ERRCODE_IO_ACCESSDENIED );
931 0 : return 0; // ?mav?
932 : }
933 :
934 0 : if( !nSize || !Init() )
935 0 : return 0;
936 :
937 0 : sal_uLong aResult = m_pStream->Write( pData, nSize );
938 :
939 0 : m_bModified = aResult > 0;
940 :
941 0 : return aResult;
942 :
943 : }
944 :
945 0 : sal_uInt64 UCBStorageStream_Impl::SeekPos(sal_uInt64 const nPos)
946 : {
947 : // check if a truncated STREAM_SEEK_TO_END was passed
948 : assert(nPos != SAL_MAX_UINT32);
949 :
950 0 : if( !Init() )
951 0 : return 0;
952 :
953 : sal_uInt64 aResult;
954 :
955 0 : if( nPos == STREAM_SEEK_TO_END )
956 : {
957 0 : m_pStream->Seek( STREAM_SEEK_TO_END );
958 0 : ReadSourceWriteTemporary();
959 0 : aResult = m_pStream->Tell();
960 : }
961 : else
962 : {
963 : // the problem is that even if nPos is larger the length
964 : // of the stream the stream pointer will be moved to this position
965 : // so we have to check if temporary stream does not contain required position
966 :
967 0 : if( m_pStream->Tell() > nPos
968 0 : || m_pStream->Seek( STREAM_SEEK_TO_END ) > nPos )
969 : {
970 : // no copiing is required
971 0 : aResult = m_pStream->Seek( nPos );
972 : }
973 : else
974 : {
975 : // the temp stream pointer points to the end now
976 0 : aResult = m_pStream->Tell();
977 :
978 0 : if( aResult < nPos )
979 : {
980 0 : if( m_bSourceRead )
981 : {
982 0 : aResult += ReadSourceWriteTemporary( nPos - aResult );
983 0 : if( aResult < nPos )
984 0 : m_bSourceRead = false;
985 :
986 : DBG_ASSERT( aResult == m_pStream->Tell(), "Error in stream arithmetic!\n" );
987 : }
988 :
989 0 : if( (m_nMode & StreamMode::WRITE) && !m_bSourceRead && aResult < nPos )
990 : {
991 : // it means that all the Source stream was copied already
992 : // but the required position still was not reached
993 : // for writable streams it should be done
994 0 : m_pStream->SetStreamSize( nPos );
995 0 : aResult = m_pStream->Seek( STREAM_SEEK_TO_END );
996 : DBG_ASSERT( aResult == nPos, "Error in stream arithmetic!\n" );
997 : }
998 : }
999 : }
1000 : }
1001 :
1002 0 : return aResult;
1003 : }
1004 :
1005 0 : void UCBStorageStream_Impl::SetSize(sal_uInt64 const nSize)
1006 : {
1007 0 : if ( !(m_nMode & StreamMode::WRITE) )
1008 : {
1009 0 : SetError( ERRCODE_IO_ACCESSDENIED );
1010 0 : return;
1011 : }
1012 :
1013 0 : if( !Init() )
1014 0 : return;
1015 :
1016 0 : m_bModified = true;
1017 :
1018 0 : if( m_bSourceRead )
1019 : {
1020 0 : sal_uInt64 const aPos = m_pStream->Tell();
1021 0 : m_pStream->Seek( STREAM_SEEK_TO_END );
1022 0 : if( m_pStream->Tell() < nSize )
1023 0 : ReadSourceWriteTemporary( nSize - m_pStream->Tell() );
1024 0 : m_pStream->Seek( aPos );
1025 : }
1026 :
1027 0 : m_pStream->SetStreamSize( nSize );
1028 0 : m_bSourceRead = false;
1029 : }
1030 :
1031 0 : void UCBStorageStream_Impl::FlushData()
1032 : {
1033 0 : if( m_pStream )
1034 : {
1035 0 : CopySourceToTemporary();
1036 0 : m_pStream->Flush();
1037 : }
1038 :
1039 0 : m_bCommited = true;
1040 0 : }
1041 :
1042 0 : void UCBStorageStream_Impl::SetError( sal_uInt32 nErr )
1043 : {
1044 0 : if ( !m_nError )
1045 : {
1046 0 : m_nError = nErr;
1047 0 : SvStream::SetError( nErr );
1048 0 : if ( m_pAntiImpl ) m_pAntiImpl->SetError( nErr );
1049 : }
1050 0 : }
1051 :
1052 0 : void UCBStorageStream_Impl::ResetError()
1053 : {
1054 0 : m_nError = 0;
1055 0 : SvStream::ResetError();
1056 0 : if ( m_pAntiImpl )
1057 0 : m_pAntiImpl->ResetError();
1058 0 : }
1059 :
1060 0 : sal_uLong UCBStorageStream_Impl::GetSize()
1061 : {
1062 0 : if( !Init() )
1063 0 : return 0;
1064 :
1065 0 : sal_uLong nPos = m_pStream->Tell();
1066 0 : m_pStream->Seek( STREAM_SEEK_TO_END );
1067 0 : ReadSourceWriteTemporary();
1068 0 : sal_uLong nRet = m_pStream->Tell();
1069 0 : m_pStream->Seek( nPos );
1070 :
1071 0 : return nRet;
1072 : }
1073 :
1074 0 : BaseStorage* UCBStorageStream_Impl::CreateStorage()
1075 : {
1076 : // create an OLEStorage on a SvStream ( = this )
1077 : // it gets the root attribute because otherwise it would probably not write before my root is committed
1078 0 : UCBStorageStream* pNewStorageStream = new UCBStorageStream( this );
1079 0 : Storage *pStorage = new Storage( *pNewStorageStream, m_bDirect );
1080 :
1081 : // GetError() call cleares error code for OLE storages, must be changed in future
1082 0 : long nTmpErr = pStorage->GetError();
1083 0 : pStorage->SetError( nTmpErr );
1084 :
1085 0 : m_bIsOLEStorage = !nTmpErr;
1086 0 : return static_cast< BaseStorage* > ( pStorage );
1087 : }
1088 :
1089 0 : sal_Int16 UCBStorageStream_Impl::Commit()
1090 : {
1091 : // send stream to the original content
1092 : // the parent storage is responsible for the correct handling of deleted contents
1093 0 : if ( m_bCommited || m_bIsOLEStorage || m_bDirect )
1094 : {
1095 : // modified streams with OLEStorages on it have autocommit; it is assumed that the OLEStorage
1096 : // was committed as well ( if not opened in direct mode )
1097 :
1098 0 : if ( m_bModified )
1099 : {
1100 : try
1101 : {
1102 0 : CopySourceToTemporary();
1103 :
1104 : // release all stream handles
1105 0 : Free();
1106 :
1107 : // the temporary file does not exist only for truncated streams
1108 : DBG_ASSERT( !m_aTempURL.isEmpty() || ( m_nMode & StreamMode::TRUNC ), "No temporary file to read from!");
1109 0 : if ( m_aTempURL.isEmpty() && !( m_nMode & StreamMode::TRUNC ) )
1110 0 : throw RuntimeException();
1111 :
1112 : // create wrapper to stream that is only used while reading inside package component
1113 0 : Reference < XInputStream > xStream = new FileStreamWrapper_Impl( m_aTempURL );
1114 :
1115 0 : Any aAny;
1116 0 : InsertCommandArgument aArg;
1117 0 : aArg.Data = xStream;
1118 0 : aArg.ReplaceExisting = true;
1119 0 : aAny <<= aArg;
1120 0 : m_pContent->executeCommand( OUString("insert"), aAny );
1121 :
1122 : // wrapper now controls lifetime of temporary file
1123 0 : m_aTempURL.clear();
1124 :
1125 0 : INetURLObject aObj( m_aURL );
1126 0 : aObj.SetName( m_aName );
1127 0 : m_aURL = aObj.GetMainURL( INetURLObject::NO_DECODE );
1128 0 : m_bModified = false;
1129 0 : m_bSourceRead = true;
1130 : }
1131 0 : catch (const CommandAbortedException&)
1132 : {
1133 : // any command wasn't executed successfully - not specified
1134 0 : SetError( ERRCODE_IO_GENERAL );
1135 0 : return COMMIT_RESULT_FAILURE;
1136 : }
1137 0 : catch (const RuntimeException&)
1138 : {
1139 : // any other error - not specified
1140 0 : SetError( ERRCODE_IO_GENERAL );
1141 0 : return COMMIT_RESULT_FAILURE;
1142 : }
1143 0 : catch (const Exception&)
1144 : {
1145 : // any other error - not specified
1146 0 : SetError( ERRCODE_IO_GENERAL );
1147 0 : return COMMIT_RESULT_FAILURE;
1148 : }
1149 :
1150 0 : m_bCommited = false;
1151 0 : return COMMIT_RESULT_SUCCESS;
1152 : }
1153 : }
1154 :
1155 0 : return COMMIT_RESULT_NOTHING_TO_DO;
1156 : }
1157 :
1158 0 : bool UCBStorageStream_Impl::Revert()
1159 : {
1160 : // if an OLEStorage is created on this stream, no "revert" is necessary because OLEStorages do nothing on "Revert" !
1161 0 : if ( m_bCommited )
1162 : {
1163 : OSL_FAIL("Revert while commit is in progress!" );
1164 0 : return false; // ???
1165 : }
1166 :
1167 0 : Free();
1168 0 : if ( !m_aTempURL.isEmpty() )
1169 : {
1170 0 : ::utl::UCBContentHelper::Kill( m_aTempURL );
1171 0 : m_aTempURL.clear();
1172 : }
1173 :
1174 0 : m_bSourceRead = false;
1175 : try
1176 : {
1177 0 : m_rSource = m_pContent->openStream();
1178 0 : if( m_rSource.is() )
1179 : {
1180 0 : if ( m_pAntiImpl && ( m_nMode & StreamMode::TRUNC ) )
1181 : // stream is in use and should be truncated
1182 0 : m_bSourceRead = false;
1183 : else
1184 : {
1185 0 : m_nMode &= ~StreamMode::TRUNC;
1186 0 : m_bSourceRead = true;
1187 : }
1188 : }
1189 : else
1190 0 : SetError( SVSTREAM_CANNOT_MAKE );
1191 : }
1192 0 : catch (const ContentCreationException&)
1193 : {
1194 0 : SetError( ERRCODE_IO_GENERAL );
1195 : }
1196 0 : catch (const RuntimeException&)
1197 : {
1198 0 : SetError( ERRCODE_IO_GENERAL );
1199 : }
1200 0 : catch (const Exception&)
1201 : {
1202 : }
1203 :
1204 0 : m_bModified = false;
1205 0 : m_aName = m_aOriginalName;
1206 0 : m_aContentType = m_aOriginalContentType;
1207 0 : return ( GetError() == ERRCODE_NONE );
1208 : }
1209 :
1210 0 : bool UCBStorageStream_Impl::Clear()
1211 : {
1212 0 : bool bRet = ( m_pAntiImpl == NULL );
1213 : DBG_ASSERT( bRet, "Removing used stream!" );
1214 0 : if( bRet )
1215 : {
1216 0 : Free();
1217 : }
1218 :
1219 0 : return bRet;
1220 : }
1221 :
1222 0 : void UCBStorageStream_Impl::Free()
1223 : {
1224 : #if OSL_DEBUG_LEVEL > 1
1225 : if ( m_pStream )
1226 : {
1227 : if ( !m_aTempURL.isEmpty() )
1228 : --nOpenFiles;
1229 : else
1230 : --nOpenStreams;
1231 : }
1232 : #endif
1233 :
1234 0 : m_nRepresentMode = nonset;
1235 0 : m_rSource.clear();
1236 0 : DELETEZ( m_pStream );
1237 0 : }
1238 :
1239 0 : void UCBStorageStream_Impl::PrepareCachedForReopen( StreamMode nMode )
1240 : {
1241 0 : bool isWritable = bool( m_nMode & StreamMode::WRITE );
1242 0 : if ( isWritable )
1243 : {
1244 : // once stream was writable, never reset to readonly
1245 0 : nMode |= StreamMode::WRITE;
1246 : }
1247 :
1248 0 : m_nMode = nMode;
1249 0 : Free();
1250 :
1251 0 : if ( nMode & StreamMode::TRUNC )
1252 : {
1253 0 : m_bSourceRead = false; // usually it should be 0 already but just in case...
1254 :
1255 0 : if ( !m_aTempURL.isEmpty() )
1256 : {
1257 0 : ::utl::UCBContentHelper::Kill( m_aTempURL );
1258 0 : m_aTempURL.clear();
1259 : }
1260 : }
1261 0 : }
1262 :
1263 0 : UCBStorageStream::UCBStorageStream( const OUString& rName, StreamMode nMode, bool bDirect, const OString* pKey, bool bRepair, Reference< XProgressHandler > xProgress )
1264 : {
1265 : // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
1266 : // to class UCBStorageStream !
1267 0 : pImp = new UCBStorageStream_Impl( rName, nMode, this, bDirect, pKey, bRepair, xProgress );
1268 0 : pImp->AddFirstRef(); // use direct refcounting because in header file only a pointer should be used
1269 0 : StorageBase::m_nMode = pImp->m_nMode;
1270 0 : }
1271 :
1272 0 : UCBStorageStream::UCBStorageStream( UCBStorageStream_Impl *pImpl )
1273 0 : : pImp( pImpl )
1274 : {
1275 0 : pImp->AddFirstRef(); // use direct refcounting because in header file only a pointer should be used
1276 0 : pImp->m_pAntiImpl = this;
1277 0 : SetError( pImp->m_nError );
1278 0 : StorageBase::m_nMode = pImp->m_nMode;
1279 0 : }
1280 :
1281 0 : UCBStorageStream::~UCBStorageStream()
1282 : {
1283 0 : if ( pImp->m_nMode & StreamMode::WRITE )
1284 0 : pImp->Flush();
1285 0 : pImp->m_pAntiImpl = NULL;
1286 0 : pImp->Free();
1287 0 : pImp->ReleaseRef();
1288 0 : }
1289 :
1290 0 : sal_uLong UCBStorageStream::Read( void * pData, sal_uLong nSize )
1291 : {
1292 : //return pImp->m_pStream->Read( pData, nSize );
1293 0 : return pImp->GetData( pData, nSize );
1294 : }
1295 :
1296 0 : sal_uLong UCBStorageStream::Write( const void* pData, sal_uLong nSize )
1297 : {
1298 0 : return pImp->PutData( pData, nSize );
1299 : }
1300 :
1301 0 : sal_uInt64 UCBStorageStream::Seek( sal_uInt64 nPos )
1302 : {
1303 : //return pImp->m_pStream->Seek( nPos );
1304 0 : return pImp->Seek( nPos );
1305 : }
1306 :
1307 0 : sal_uLong UCBStorageStream::Tell()
1308 : {
1309 0 : if( !pImp->Init() )
1310 0 : return 0;
1311 0 : return pImp->m_pStream->Tell();
1312 : }
1313 :
1314 0 : void UCBStorageStream::Flush()
1315 : {
1316 : // streams are never really transacted, so flush also means commit !
1317 0 : Commit();
1318 0 : }
1319 :
1320 0 : bool UCBStorageStream::SetSize( sal_uLong nNewSize )
1321 : {
1322 0 : pImp->SetSize( nNewSize );
1323 0 : return !pImp->GetError();
1324 : }
1325 :
1326 0 : bool UCBStorageStream::Validate( bool bWrite ) const
1327 : {
1328 0 : return ( !bWrite || ( pImp->m_nMode & StreamMode::WRITE ) );
1329 : }
1330 :
1331 0 : bool UCBStorageStream::ValidateMode( StreamMode m ) const
1332 : {
1333 : // ???
1334 0 : if( m == ( StreamMode::READ | StreamMode::TRUNC ) ) // from stg.cxx
1335 0 : return true;
1336 0 : if( ( m & STREAM_READWRITE) == StreamMode::READ )
1337 : {
1338 : // only SHARE_DENYWRITE or SHARE_DENYALL allowed
1339 0 : if( ( m & StreamMode::SHARE_DENYWRITE )
1340 0 : || ( m & StreamMode::SHARE_DENYALL ) )
1341 0 : return true;
1342 : }
1343 : else
1344 : {
1345 : // only SHARE_DENYALL allowed
1346 : // storages open in r/o mode are OK, since only
1347 : // the commit may fail
1348 0 : if( m & StreamMode::SHARE_DENYALL )
1349 0 : return true;
1350 : }
1351 :
1352 0 : return true;
1353 : }
1354 :
1355 0 : const SvStream* UCBStorageStream::GetSvStream() const
1356 : {
1357 0 : if( !pImp->Init() )
1358 0 : return NULL;
1359 :
1360 0 : pImp->CopySourceToTemporary();
1361 0 : return pImp->m_pStream; // should not live longer then pImp!!!
1362 : }
1363 :
1364 0 : SvStream* UCBStorageStream::GetModifySvStream()
1365 : {
1366 0 : return static_cast<SvStream*>(pImp);
1367 : }
1368 :
1369 0 : bool UCBStorageStream::Equals( const BaseStorageStream& rStream ) const
1370 : {
1371 : // ???
1372 0 : return static_cast<BaseStorageStream const *>(this) == &rStream;
1373 : }
1374 :
1375 0 : bool UCBStorageStream::Commit()
1376 : {
1377 : // mark this stream for sending it on root commit
1378 0 : pImp->FlushData();
1379 0 : return true;
1380 : }
1381 :
1382 0 : bool UCBStorageStream::Revert()
1383 : {
1384 0 : return pImp->Revert();
1385 : }
1386 :
1387 0 : bool UCBStorageStream::CopyTo( BaseStorageStream* pDestStm )
1388 : {
1389 0 : if( !pImp->Init() )
1390 0 : return false;
1391 :
1392 0 : UCBStorageStream* pStg = PTR_CAST( UCBStorageStream, pDestStm );
1393 0 : if ( pStg )
1394 0 : pStg->pImp->m_aContentType = pImp->m_aContentType;
1395 :
1396 0 : pDestStm->SetSize( 0 );
1397 0 : Seek( STREAM_SEEK_TO_END );
1398 0 : sal_Int32 n = Tell();
1399 0 : if( n < 0 )
1400 0 : return false;
1401 :
1402 0 : if( pDestStm->SetSize( n ) && n )
1403 : {
1404 0 : boost::scoped_array<sal_uInt8> p(new sal_uInt8[ 4096 ]);
1405 0 : Seek( 0L );
1406 0 : pDestStm->Seek( 0L );
1407 0 : while( n )
1408 : {
1409 0 : sal_uInt32 nn = n;
1410 0 : if( nn > 4096 )
1411 0 : nn = 4096;
1412 0 : if( Read( p.get(), nn ) != nn )
1413 0 : break;
1414 0 : if( pDestStm->Write( p.get(), nn ) != nn )
1415 0 : break;
1416 0 : n -= nn;
1417 0 : }
1418 : }
1419 :
1420 0 : return true;
1421 : }
1422 :
1423 0 : bool UCBStorageStream::SetProperty( const OUString& rName, const ::com::sun::star::uno::Any& rValue )
1424 : {
1425 0 : if ( rName == "Title")
1426 0 : return false;
1427 :
1428 0 : if ( rName == "MediaType")
1429 : {
1430 0 : OUString aTmp;
1431 0 : rValue >>= aTmp;
1432 0 : pImp->m_aContentType = aTmp;
1433 : }
1434 :
1435 : try
1436 : {
1437 0 : if ( pImp->m_pContent )
1438 : {
1439 0 : pImp->m_pContent->setPropertyValue( rName, rValue );
1440 0 : return true;
1441 : }
1442 : }
1443 0 : catch (const Exception&)
1444 : {
1445 : }
1446 :
1447 0 : return false;
1448 : }
1449 :
1450 0 : sal_uLong UCBStorageStream::GetSize() const
1451 : {
1452 0 : return pImp->GetSize();
1453 : }
1454 :
1455 30 : UCBStorage::UCBStorage( SvStream& rStrm, bool bDirect )
1456 : {
1457 30 : OUString aURL = GetLinkedFile( rStrm );
1458 30 : if ( !aURL.isEmpty() )
1459 : {
1460 0 : StreamMode nMode = StreamMode::READ;
1461 0 : if( rStrm.IsWritable() )
1462 0 : nMode = StreamMode::READ | StreamMode::WRITE;
1463 :
1464 0 : ::ucbhelper::Content aContent( aURL, Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
1465 0 : pImp = new UCBStorage_Impl( aContent, aURL, nMode, this, bDirect, true );
1466 : }
1467 : else
1468 : {
1469 : // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
1470 : // to class UCBStorage !
1471 30 : pImp = new UCBStorage_Impl( rStrm, this, bDirect );
1472 : }
1473 :
1474 30 : pImp->AddFirstRef();
1475 30 : pImp->Init();
1476 30 : StorageBase::m_nMode = pImp->m_nMode;
1477 30 : }
1478 :
1479 0 : UCBStorage::UCBStorage( const ::ucbhelper::Content& rContent, const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot )
1480 : {
1481 : // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
1482 : // to class UCBStorage !
1483 0 : pImp = new UCBStorage_Impl( rContent, rName, nMode, this, bDirect, bIsRoot );
1484 0 : pImp->AddFirstRef();
1485 0 : pImp->Init();
1486 0 : StorageBase::m_nMode = pImp->m_nMode;
1487 0 : }
1488 :
1489 0 : UCBStorage::UCBStorage( const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler )
1490 : {
1491 : // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
1492 : // to class UCBStorage !
1493 0 : pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, bIsRepair, xProgressHandler );
1494 0 : pImp->AddFirstRef();
1495 0 : pImp->Init();
1496 0 : StorageBase::m_nMode = pImp->m_nMode;
1497 0 : }
1498 :
1499 2006 : UCBStorage::UCBStorage( const OUString& rName, StreamMode nMode, bool bDirect, bool bIsRoot )
1500 : {
1501 : // pImp must be initialized in the body, because otherwise the vtable of the stream is not initialized
1502 : // to class UCBStorage !
1503 2006 : pImp = new UCBStorage_Impl( rName, nMode, this, bDirect, bIsRoot, false, Reference< XProgressHandler >() );
1504 2006 : pImp->AddFirstRef();
1505 2006 : pImp->Init();
1506 2006 : StorageBase::m_nMode = pImp->m_nMode;
1507 2006 : }
1508 :
1509 0 : UCBStorage::UCBStorage( UCBStorage_Impl *pImpl )
1510 0 : : pImp( pImpl )
1511 : {
1512 0 : pImp->m_pAntiImpl = this;
1513 0 : SetError( pImp->m_nError );
1514 0 : pImp->AddFirstRef(); // use direct refcounting because in header file only a pointer should be used
1515 0 : StorageBase::m_nMode = pImp->m_nMode;
1516 0 : }
1517 :
1518 6108 : UCBStorage::~UCBStorage()
1519 : {
1520 2036 : if ( pImp->m_bIsRoot && pImp->m_bDirect && ( !pImp->m_pTempFile || pImp->m_pSource ) )
1521 : // DirectMode is simulated with an AutoCommit
1522 0 : Commit();
1523 :
1524 2036 : pImp->m_pAntiImpl = NULL;
1525 2036 : pImp->ReleaseRef();
1526 4072 : }
1527 :
1528 0 : UCBStorage_Impl::UCBStorage_Impl( const ::ucbhelper::Content& rContent, const OUString& rName, StreamMode nMode, UCBStorage* pStorage, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler )
1529 : : m_pAntiImpl( pStorage )
1530 0 : , m_pContent( new ::ucbhelper::Content( rContent ) )
1531 : , m_pTempFile( NULL )
1532 : , m_pSource( NULL )
1533 : //, m_pStream( NULL )
1534 : , m_nError( 0 )
1535 : , m_nMode( nMode )
1536 : , m_bModified( false )
1537 : , m_bCommited( false )
1538 : , m_bDirect( bDirect )
1539 : , m_bIsRoot( bIsRoot )
1540 : , m_bDirty( false )
1541 : , m_bIsLinked( true )
1542 : , m_bListCreated( false )
1543 : , m_nFormat( SotClipboardFormatId::NONE )
1544 : , m_aClassId( SvGlobalName() )
1545 : , m_bRepairPackage( bIsRepair )
1546 0 : , m_xProgressHandler( xProgressHandler )
1547 : {
1548 0 : OUString aName( rName );
1549 0 : if( aName.isEmpty() )
1550 : {
1551 : // no name given = use temporary name!
1552 : DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" );
1553 0 : m_pTempFile = new ::utl::TempFile;
1554 0 : m_pTempFile->EnableKillingFile( true );
1555 0 : m_aName = m_aOriginalName = aName = m_pTempFile->GetURL();
1556 : }
1557 :
1558 0 : m_aURL = rName;
1559 0 : }
1560 :
1561 2006 : UCBStorage_Impl::UCBStorage_Impl( const OUString& rName, StreamMode nMode, UCBStorage* pStorage, bool bDirect, bool bIsRoot, bool bIsRepair, Reference< XProgressHandler > xProgressHandler )
1562 : : m_pAntiImpl( pStorage )
1563 : , m_pContent( NULL )
1564 : , m_pTempFile( NULL )
1565 : , m_pSource( NULL )
1566 : //, m_pStream( NULL )
1567 : , m_nError( 0 )
1568 : , m_nMode( nMode )
1569 : , m_bModified( false )
1570 : , m_bCommited( false )
1571 : , m_bDirect( bDirect )
1572 : , m_bIsRoot( bIsRoot )
1573 : , m_bDirty( false )
1574 : , m_bIsLinked( false )
1575 : , m_bListCreated( false )
1576 : , m_nFormat( SotClipboardFormatId::NONE )
1577 : , m_aClassId( SvGlobalName() )
1578 : , m_bRepairPackage( bIsRepair )
1579 2006 : , m_xProgressHandler( xProgressHandler )
1580 : {
1581 2006 : OUString aName( rName );
1582 2006 : if( aName.isEmpty() )
1583 : {
1584 : // no name given = use temporary name!
1585 : DBG_ASSERT( m_bIsRoot, "SubStorage must have a name!" );
1586 2006 : m_pTempFile = new ::utl::TempFile;
1587 2006 : m_pTempFile->EnableKillingFile( true );
1588 2006 : m_aName = m_aOriginalName = aName = m_pTempFile->GetURL();
1589 : }
1590 :
1591 2006 : if ( m_bIsRoot )
1592 : {
1593 : // create the special package URL for the package content
1594 2006 : OUString aTemp = "vnd.sun.star.pkg://";
1595 2006 : aTemp += INetURLObject::encode( aName, INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL );
1596 2006 : m_aURL = aTemp;
1597 :
1598 2006 : if ( m_nMode & StreamMode::WRITE )
1599 : {
1600 : // the root storage opens the package, so make sure that there is any
1601 2006 : SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aName, STREAM_STD_READWRITE, m_pTempFile != 0 /* bFileExists */ );
1602 2006 : delete pStream;
1603 2006 : }
1604 : }
1605 : else
1606 : {
1607 : // substorages are opened like streams: the URL is a "child URL" of the root package URL
1608 0 : m_aURL = rName;
1609 0 : if ( !m_aURL.startsWith( "vnd.sun.star.pkg://") )
1610 0 : m_bIsLinked = true;
1611 2006 : }
1612 2006 : }
1613 :
1614 30 : UCBStorage_Impl::UCBStorage_Impl( SvStream& rStream, UCBStorage* pStorage, bool bDirect )
1615 : : m_pAntiImpl( pStorage )
1616 : , m_pContent( NULL )
1617 30 : , m_pTempFile( new ::utl::TempFile )
1618 : , m_pSource( &rStream )
1619 : , m_nError( 0 )
1620 : , m_bModified( false )
1621 : , m_bCommited( false )
1622 : , m_bDirect( bDirect )
1623 : , m_bIsRoot( true )
1624 : , m_bDirty( false )
1625 : , m_bIsLinked( false )
1626 : , m_bListCreated( false )
1627 : , m_nFormat( SotClipboardFormatId::NONE )
1628 : , m_aClassId( SvGlobalName() )
1629 60 : , m_bRepairPackage( false )
1630 : {
1631 : // opening in direct mode is too fuzzy because the data is transferred to the stream in the Commit() call,
1632 : // which will be called in the storages' dtor
1633 30 : m_pTempFile->EnableKillingFile( true );
1634 : DBG_ASSERT( !bDirect, "Storage on a stream must not be opened in direct mode!" );
1635 :
1636 : // UCBStorages work on a content, so a temporary file for a content must be created, even if the stream is only
1637 : // accessed readonly
1638 : // the root storage opens the package; create the special package URL for the package content
1639 30 : OUString aTemp = "vnd.sun.star.pkg://";
1640 30 : aTemp += INetURLObject::encode( m_pTempFile->GetURL(), INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL );
1641 30 : m_aURL = aTemp;
1642 :
1643 : // copy data into the temporary file
1644 60 : boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READWRITE, true /* bFileExists */ ));
1645 30 : if ( pStream )
1646 : {
1647 30 : rStream.Seek(0);
1648 30 : rStream.ReadStream( *pStream );
1649 30 : pStream->Flush();
1650 30 : pStream.reset();
1651 : }
1652 :
1653 : // close stream and let content access the file
1654 30 : m_pSource->Seek(0);
1655 :
1656 : // check opening mode
1657 30 : m_nMode = StreamMode::READ;
1658 30 : if( rStream.IsWritable() )
1659 60 : m_nMode = StreamMode::READ | StreamMode::WRITE;
1660 30 : }
1661 :
1662 2036 : void UCBStorage_Impl::Init()
1663 : {
1664 : // name is last segment in URL
1665 2036 : INetURLObject aObj( m_aURL );
1666 2036 : if ( m_aName.isEmpty() )
1667 : // if the name was not already set to a temp name
1668 30 : m_aName = m_aOriginalName = aObj.GetLastName();
1669 :
1670 2036 : if ( !m_pContent )
1671 2036 : CreateContent();
1672 :
1673 2036 : if ( m_pContent )
1674 : {
1675 13 : if ( m_bIsLinked )
1676 : {
1677 0 : if( m_bIsRoot )
1678 : {
1679 0 : ReadContent();
1680 0 : if ( m_nError == ERRCODE_NONE )
1681 : {
1682 : // read the manifest.xml file
1683 0 : aObj.Append( OUString( "META-INF" ) );
1684 0 : aObj.Append( OUString( "manifest.xml" ) );
1685 :
1686 : // create input stream
1687 0 : boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( aObj.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READ ));
1688 : // no stream means no manifest.xml
1689 0 : if ( pStream )
1690 : {
1691 0 : if ( !pStream->GetError() )
1692 : {
1693 0 : ::utl::OInputStreamWrapper* pHelper = new ::utl::OInputStreamWrapper( *pStream );
1694 0 : com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > xInputStream( pHelper );
1695 :
1696 : // create a manifest reader object that will read in the manifest from the stream
1697 : Reference < ::com::sun::star::packages::manifest::XManifestReader > xReader =
1698 : ::com::sun::star::packages::manifest::ManifestReader::create(
1699 0 : ::comphelper::getProcessComponentContext() ) ;
1700 0 : Sequence < Sequence < PropertyValue > > aProps = xReader->readManifestSequence( xInputStream );
1701 :
1702 : // cleanup
1703 0 : xReader = NULL;
1704 0 : xInputStream = NULL;
1705 0 : SetProps( aProps, OUString() );
1706 : }
1707 0 : }
1708 : }
1709 : }
1710 : else
1711 0 : ReadContent();
1712 : }
1713 : else
1714 : {
1715 : // get the manifest information from the package
1716 : try {
1717 13 : Any aAny = m_pContent->getPropertyValue("MediaType");
1718 26 : OUString aTmp;
1719 13 : if ( ( aAny >>= aTmp ) && !aTmp.isEmpty() )
1720 13 : m_aContentType = m_aOriginalContentType = aTmp;
1721 : }
1722 0 : catch (const Exception&)
1723 : {
1724 : DBG_ASSERT( false,
1725 : "getPropertyValue has thrown an exception! Please let developers know the scenario!" );
1726 : }
1727 : }
1728 : }
1729 :
1730 2036 : if ( !m_aContentType.isEmpty() )
1731 : {
1732 : // get the clipboard format using the content type
1733 0 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
1734 0 : aDataFlavor.MimeType = m_aContentType;
1735 0 : m_nFormat = SotExchange::GetFormat( aDataFlavor );
1736 :
1737 : // get the ClassId using the clipboard format ( internal table )
1738 0 : m_aClassId = GetClassId_Impl( m_nFormat );
1739 :
1740 : // get human presentable name using the clipboard format
1741 0 : SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor );
1742 0 : m_aUserTypeName = aDataFlavor.HumanPresentableName;
1743 :
1744 0 : if( m_pContent && !m_bIsLinked && m_aClassId != SvGlobalName() )
1745 0 : ReadContent();
1746 2036 : }
1747 2036 : }
1748 :
1749 4029 : void UCBStorage_Impl::CreateContent()
1750 : {
1751 : try
1752 : {
1753 : // create content; where to put StreamMode ?! ( already done when opening the file of the package ? )
1754 4029 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
1755 :
1756 8058 : OUString aTemp( m_aURL );
1757 :
1758 4029 : if ( m_bRepairPackage )
1759 : {
1760 0 : xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
1761 0 : m_xProgressHandler );
1762 0 : aTemp += "?repairpackage";
1763 : }
1764 :
1765 12074 : m_pContent = new ::ucbhelper::Content( aTemp, xComEnv, comphelper::getProcessComponentContext() );
1766 : }
1767 8032 : catch (const ContentCreationException&)
1768 : {
1769 : // content could not be created
1770 4016 : SetError( SVSTREAM_CANNOT_MAKE );
1771 : }
1772 0 : catch (const RuntimeException&)
1773 : {
1774 : // any other error - not specified
1775 0 : SetError( SVSTREAM_CANNOT_MAKE );
1776 : }
1777 4029 : }
1778 :
1779 4012 : void UCBStorage_Impl::ReadContent()
1780 : {
1781 4012 : if ( m_bListCreated )
1782 6005 : return;
1783 :
1784 2006 : m_bListCreated = true;
1785 :
1786 : // create cursor for access to children
1787 2006 : Sequence< OUString > aProps(4);
1788 2006 : aProps[0] = "Title";
1789 2006 : aProps[1] = "IsFolder";
1790 2006 : aProps[2] = "MediaType";
1791 2006 : aProps[3] = "Size";
1792 2006 : ::ucbhelper::ResultSetInclude eInclude = ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS;
1793 :
1794 : try
1795 : {
1796 2006 : GetContent();
1797 2006 : if ( !m_pContent )
1798 1993 : return;
1799 :
1800 13 : Reference< XResultSet > xResultSet = m_pContent->createCursor( aProps, eInclude );
1801 26 : Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
1802 26 : Reference< XRow > xRow( xResultSet, UNO_QUERY );
1803 13 : if ( xResultSet.is() )
1804 : {
1805 26 : while ( xResultSet->next() )
1806 : {
1807 : // insert all into the children list
1808 0 : OUString aTitle( xRow->getString(1) );
1809 0 : OUString aContentType;
1810 0 : if ( m_bIsLinked )
1811 : {
1812 : // unpacked storages have to deal with the meta-inf folder by themselves
1813 0 : if ( aTitle == "META-INF" )
1814 0 : continue;
1815 : }
1816 : else
1817 : {
1818 0 : aContentType = xRow->getString(3);
1819 : }
1820 :
1821 0 : bool bIsFolder( xRow->getBoolean(2) );
1822 0 : sal_Int64 nSize = xRow->getLong(4);
1823 0 : UCBStorageElement_Impl* pElement = new UCBStorageElement_Impl( aTitle, bIsFolder, (sal_uLong) nSize );
1824 0 : m_aChildrenList.push_back( pElement );
1825 :
1826 0 : bool bIsOfficeDocument = m_bIsLinked || ( m_aClassId != SvGlobalName() );
1827 0 : if ( bIsFolder )
1828 : {
1829 0 : if ( m_bIsLinked )
1830 0 : OpenStorage( pElement, m_nMode, m_bDirect );
1831 0 : if ( pElement->m_xStorage.Is() )
1832 0 : pElement->m_xStorage->Init();
1833 : }
1834 0 : else if ( bIsOfficeDocument )
1835 : {
1836 : // streams can be external OLE objects, so they are now folders, but storages!
1837 0 : OUString aName( m_aURL + "/" + xRow->getString(1));
1838 :
1839 0 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
1840 0 : if ( m_bRepairPackage )
1841 : {
1842 0 : xComEnv = new ::ucbhelper::CommandEnvironment( Reference< ::com::sun::star::task::XInteractionHandler >(),
1843 0 : m_xProgressHandler );
1844 0 : aName += "?repairpackage";
1845 : }
1846 :
1847 0 : ::ucbhelper::Content aContent( aName, xComEnv, comphelper::getProcessComponentContext() );
1848 :
1849 0 : OUString aMediaType;
1850 0 : Any aAny = aContent.getPropertyValue("MediaType");
1851 0 : if ( ( aAny >>= aMediaType ) && ( aMediaType == "application/vnd.sun.star.oleobject" ) )
1852 0 : pElement->m_bIsStorage = true;
1853 0 : else if ( aMediaType.isEmpty() )
1854 : {
1855 : // older files didn't have that special content type, so they must be detected
1856 0 : OpenStream( pElement, STREAM_STD_READ, m_bDirect );
1857 0 : if ( Storage::IsStorageFile( pElement->m_xStream ) )
1858 0 : pElement->m_bIsStorage = true;
1859 : else
1860 0 : pElement->m_xStream->Free();
1861 0 : }
1862 : }
1863 0 : }
1864 13 : }
1865 : }
1866 0 : catch (const InteractiveIOException& r)
1867 : {
1868 0 : if ( r.Code != IOErrorCode_NOT_EXISTING )
1869 0 : SetError( ERRCODE_IO_GENERAL );
1870 : }
1871 0 : catch (const CommandAbortedException&)
1872 : {
1873 : // any command wasn't executed successfully - not specified
1874 0 : if ( !( m_nMode & StreamMode::WRITE ) )
1875 : // if the folder was just inserted and not already committed, this is not an error!
1876 0 : SetError( ERRCODE_IO_GENERAL );
1877 : }
1878 0 : catch (const RuntimeException&)
1879 : {
1880 : // any other error - not specified
1881 0 : SetError( ERRCODE_IO_GENERAL );
1882 : }
1883 0 : catch (const ResultSetException&)
1884 : {
1885 : // means that the package file is broken
1886 0 : SetError( ERRCODE_IO_BROKENPACKAGE );
1887 : }
1888 0 : catch (const SQLException&)
1889 : {
1890 : // means that the file can be broken
1891 0 : SetError( ERRCODE_IO_WRONGFORMAT );
1892 : }
1893 0 : catch (const Exception&)
1894 : {
1895 : // any other error - not specified
1896 0 : SetError( ERRCODE_IO_GENERAL );
1897 13 : }
1898 : }
1899 :
1900 4016 : void UCBStorage_Impl::SetError( long nError )
1901 : {
1902 4016 : if ( !m_nError )
1903 : {
1904 2023 : m_nError = nError;
1905 2023 : if ( m_pAntiImpl ) m_pAntiImpl->SetError( nError );
1906 : }
1907 4016 : }
1908 :
1909 0 : sal_Int32 UCBStorage_Impl::GetObjectCount()
1910 : {
1911 0 : sal_Int32 nCount = m_aChildrenList.size();
1912 0 : for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
1913 : {
1914 0 : UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
1915 : DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
1916 0 : if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
1917 0 : nCount += pElement->m_xStorage->GetObjectCount();
1918 : }
1919 :
1920 0 : return nCount;
1921 : }
1922 :
1923 0 : OUString Find_Impl( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
1924 : {
1925 0 : bool bFound = false;
1926 0 : for ( sal_Int32 nSeqs=0; nSeqs<rSequence.getLength(); nSeqs++ )
1927 : {
1928 0 : const Sequence < PropertyValue >& rMyProps = rSequence[nSeqs];
1929 0 : OUString aType;
1930 :
1931 0 : for ( sal_Int32 nProps=0; nProps<rMyProps.getLength(); nProps++ )
1932 : {
1933 0 : const PropertyValue& rAny = rMyProps[nProps];
1934 0 : if ( rAny.Name == "FullPath" )
1935 : {
1936 0 : OUString aTmp;
1937 0 : if ( ( rAny.Value >>= aTmp ) && aTmp == rPath )
1938 0 : bFound = true;
1939 0 : if ( !aType.isEmpty() )
1940 0 : break;
1941 : }
1942 0 : else if ( rAny.Name == "MediaType" )
1943 : {
1944 0 : if ( ( rAny.Value >>= aType ) && !aType.isEmpty() && bFound )
1945 0 : break;
1946 : }
1947 : }
1948 :
1949 0 : if ( bFound )
1950 0 : return aType;
1951 0 : }
1952 :
1953 0 : return OUString();
1954 : }
1955 :
1956 0 : void UCBStorage_Impl::SetProps( const Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
1957 : {
1958 0 : OUString aPath( rPath );
1959 0 : if ( !m_bIsRoot )
1960 0 : aPath += m_aName;
1961 0 : aPath += "/";
1962 :
1963 0 : m_aContentType = m_aOriginalContentType = Find_Impl( rSequence, aPath );
1964 :
1965 0 : if ( m_bIsRoot )
1966 : // the "FullPath" of a child always starts without '/'
1967 0 : aPath.clear();
1968 :
1969 0 : for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
1970 : {
1971 0 : UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
1972 : DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
1973 0 : if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
1974 0 : pElement->m_xStorage->SetProps( rSequence, aPath );
1975 : else
1976 : {
1977 0 : OUString aElementPath( aPath );
1978 0 : aElementPath += pElement->m_aName;
1979 0 : pElement->SetContentType( Find_Impl( rSequence, aElementPath ) );
1980 : }
1981 : }
1982 :
1983 0 : if ( !m_aContentType.isEmpty() )
1984 : {
1985 : // get the clipboard format using the content type
1986 0 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
1987 0 : aDataFlavor.MimeType = m_aContentType;
1988 0 : m_nFormat = SotExchange::GetFormat( aDataFlavor );
1989 :
1990 : // get the ClassId using the clipboard format ( internal table )
1991 0 : m_aClassId = GetClassId_Impl( m_nFormat );
1992 :
1993 : // get human presentable name using the clipboard format
1994 0 : SotExchange::GetFormatDataFlavor( m_nFormat, aDataFlavor );
1995 0 : m_aUserTypeName = aDataFlavor.HumanPresentableName;
1996 0 : }
1997 0 : }
1998 :
1999 0 : void UCBStorage_Impl::GetProps( sal_Int32& nProps, Sequence < Sequence < PropertyValue > >& rSequence, const OUString& rPath )
2000 : {
2001 : // first my own properties
2002 0 : Sequence < PropertyValue > aProps(2);
2003 :
2004 : // first property is the "FullPath" name
2005 : // it's '/' for the root storage and m_aName for each element, followed by a '/' if it's a folder
2006 0 : OUString aPath( rPath );
2007 0 : if ( !m_bIsRoot )
2008 0 : aPath += m_aName;
2009 0 : aPath += "/";
2010 0 : aProps[0].Name = "MediaType";
2011 0 : aProps[0].Value <<= m_aContentType;
2012 0 : aProps[1].Name = "FullPath";
2013 0 : aProps[1].Value <<= aPath;
2014 0 : rSequence[ nProps++ ] = aProps;
2015 :
2016 0 : if ( m_bIsRoot )
2017 : // the "FullPath" of a child always starts without '/'
2018 0 : aPath.clear();
2019 :
2020 : // now the properties of my elements
2021 0 : for ( size_t i = 0; i < m_aChildrenList.size(); ++i )
2022 : {
2023 0 : UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
2024 : DBG_ASSERT( !pElement->m_bIsFolder || pElement->m_xStorage.Is(), "Storage should be open!" );
2025 0 : if ( pElement->m_bIsFolder && pElement->m_xStorage.Is() )
2026 : // storages add there properties by themselves ( see above )
2027 0 : pElement->m_xStorage->GetProps( nProps, rSequence, aPath );
2028 : else
2029 : {
2030 : // properties of streams
2031 0 : OUString aElementPath( aPath );
2032 0 : aElementPath += pElement->m_aName;
2033 0 : aProps[0].Name = "MediaType";
2034 0 : aProps[0].Value <<= pElement->GetContentType();
2035 0 : aProps[1].Name = "FullPath";
2036 0 : aProps[1].Value <<= aElementPath;
2037 0 : rSequence[ nProps++ ] = aProps;
2038 : }
2039 0 : }
2040 0 : }
2041 :
2042 6108 : UCBStorage_Impl::~UCBStorage_Impl()
2043 : {
2044 : // first delete elements!
2045 2036 : for ( size_t i = 0, n = m_aChildrenList.size(); i < n; ++i )
2046 0 : delete m_aChildrenList[ i ];
2047 2036 : m_aChildrenList.clear();
2048 :
2049 2036 : delete m_pContent;
2050 2036 : delete m_pTempFile;
2051 4072 : }
2052 :
2053 0 : bool UCBStorage_Impl::Insert( ::ucbhelper::Content *pContent )
2054 : {
2055 : // a new substorage is inserted into a UCBStorage ( given by the parameter pContent )
2056 : // it must be inserted with a title and a type
2057 0 : bool bRet = false;
2058 :
2059 : try
2060 : {
2061 0 : Sequence< ContentInfo > aInfo = pContent->queryCreatableContentsInfo();
2062 0 : sal_Int32 nCount = aInfo.getLength();
2063 0 : if ( nCount == 0 )
2064 0 : return false;
2065 :
2066 0 : for ( sal_Int32 i = 0; i < nCount; ++i )
2067 : {
2068 : // Simply look for the first KIND_FOLDER...
2069 0 : const ContentInfo & rCurr = aInfo[i];
2070 0 : if ( rCurr.Attributes & ContentInfoAttribute::KIND_FOLDER )
2071 : {
2072 : // Make sure the only required bootstrap property is "Title",
2073 0 : const Sequence< Property > & rProps = rCurr.Properties;
2074 0 : if ( rProps.getLength() != 1 )
2075 0 : continue;
2076 :
2077 0 : if ( rProps[ 0 ].Name != "Title" )
2078 0 : continue;
2079 :
2080 0 : Sequence < OUString > aNames(1);
2081 0 : aNames[0] = "Title";
2082 0 : Sequence < Any > aValues(1);
2083 0 : aValues[0] = makeAny( OUString( m_aName ) );
2084 :
2085 0 : Content aNewFolder;
2086 0 : if ( !pContent->insertNewContent( rCurr.Type, aNames, aValues, aNewFolder ) )
2087 0 : continue;
2088 :
2089 : // remove old content, create an "empty" new one and initialize it with the new inserted
2090 0 : DELETEZ( m_pContent );
2091 0 : m_pContent = new ::ucbhelper::Content( aNewFolder );
2092 0 : bRet = true;
2093 : }
2094 0 : }
2095 : }
2096 0 : catch (const CommandAbortedException&)
2097 : {
2098 : // any command wasn't executed successfully - not specified
2099 0 : SetError( ERRCODE_IO_GENERAL );
2100 : }
2101 0 : catch (const RuntimeException&)
2102 : {
2103 : // any other error - not specified
2104 0 : SetError( ERRCODE_IO_GENERAL );
2105 : }
2106 0 : catch (const Exception&)
2107 : {
2108 : // any other error - not specified
2109 0 : SetError( ERRCODE_IO_GENERAL );
2110 : }
2111 :
2112 0 : return bRet;
2113 : }
2114 :
2115 0 : sal_Int16 UCBStorage_Impl::Commit()
2116 : {
2117 : // send all changes to the package
2118 0 : sal_Int16 nRet = COMMIT_RESULT_NOTHING_TO_DO;
2119 :
2120 : // there is nothing to do if the storage has been opened readonly or if it was opened in transacted mode and no
2121 : // commit command has been sent
2122 0 : if ( ( m_nMode & StreamMode::WRITE ) && ( m_bCommited || m_bDirect ) )
2123 : {
2124 : try
2125 : {
2126 : // all errors will be caught in the "catch" statement outside the loop
2127 0 : for ( size_t i = 0; i < m_aChildrenList.size() && nRet; ++i )
2128 : {
2129 0 : UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
2130 0 : ::ucbhelper::Content* pContent = pElement->GetContent();
2131 0 : boost::scoped_ptr< ::ucbhelper::Content > xDeleteContent;
2132 0 : if ( !pContent && pElement->IsModified() )
2133 : {
2134 : // if the element has never been opened, no content has been created until now
2135 0 : OUString aName( m_aURL );
2136 0 : aName += "/";
2137 0 : aName += pElement->m_aOriginalName;
2138 0 : pContent = new ::ucbhelper::Content( aName, Reference< ::com::sun::star::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
2139 0 : xDeleteContent.reset(pContent); // delete it later on exit scope
2140 : }
2141 :
2142 0 : if ( pElement->m_bIsRemoved )
2143 : {
2144 : // was it inserted, then removed (so there would be nothing to do!)
2145 0 : if ( !pElement->m_bIsInserted )
2146 : {
2147 : // first remove all open stream handles
2148 0 : if (pContent && (!pElement->m_xStream.Is() || pElement->m_xStream->Clear()))
2149 : {
2150 0 : pContent->executeCommand( OUString("delete"), makeAny( true ) );
2151 0 : nRet = COMMIT_RESULT_SUCCESS;
2152 : }
2153 : else
2154 : // couldn't release stream because there are external references to it
2155 0 : nRet = COMMIT_RESULT_FAILURE;
2156 : }
2157 : }
2158 : else
2159 : {
2160 0 : sal_Int16 nLocalRet = COMMIT_RESULT_NOTHING_TO_DO;
2161 0 : if ( pElement->m_xStorage.Is() )
2162 : {
2163 : // element is a storage
2164 : // do a commit in the following cases:
2165 : // - if storage is already inserted, and changed
2166 : // - storage is not in a package
2167 : // - it's a new storage, try to insert and commit if successful inserted
2168 0 : if ( !pElement->m_bIsInserted || m_bIsLinked || pElement->m_xStorage->Insert( m_pContent ) )
2169 : {
2170 0 : nLocalRet = pElement->m_xStorage->Commit();
2171 0 : pContent = pElement->GetContent();
2172 : }
2173 : }
2174 0 : else if ( pElement->m_xStream.Is() )
2175 : {
2176 : // element is a stream
2177 0 : nLocalRet = pElement->m_xStream->Commit();
2178 0 : if ( pElement->m_xStream->m_bIsOLEStorage )
2179 : {
2180 : // OLE storage should be stored encrytped, if the storage uses encryption
2181 0 : pElement->m_xStream->m_aContentType = "application/vnd.sun.star.oleobject";
2182 0 : Any aValue;
2183 0 : aValue <<= true;
2184 0 : pElement->m_xStream->m_pContent->setPropertyValue("Encrypted", aValue );
2185 : }
2186 :
2187 0 : pContent = pElement->GetContent();
2188 : }
2189 :
2190 0 : if (pContent && pElement->m_aName != pElement->m_aOriginalName)
2191 : {
2192 : // name ( title ) of the element was changed
2193 0 : nLocalRet = COMMIT_RESULT_SUCCESS;
2194 0 : Any aAny;
2195 0 : aAny <<= pElement->m_aName;
2196 0 : pContent->setPropertyValue("Title", aAny );
2197 : }
2198 :
2199 0 : if (pContent && pElement->IsLoaded() && pElement->GetContentType() != pElement->GetOriginalContentType())
2200 : {
2201 : // mediatype of the element was changed
2202 0 : nLocalRet = COMMIT_RESULT_SUCCESS;
2203 0 : Any aAny;
2204 0 : aAny <<= pElement->GetContentType();
2205 0 : pContent->setPropertyValue("MediaType", aAny );
2206 : }
2207 :
2208 0 : if ( nLocalRet != COMMIT_RESULT_NOTHING_TO_DO )
2209 0 : nRet = nLocalRet;
2210 : }
2211 :
2212 0 : if ( nRet == COMMIT_RESULT_FAILURE )
2213 0 : break;
2214 0 : }
2215 : }
2216 0 : catch (const ContentCreationException&)
2217 : {
2218 : // content could not be created
2219 0 : SetError( ERRCODE_IO_NOTEXISTS );
2220 0 : return COMMIT_RESULT_FAILURE;
2221 : }
2222 0 : catch (const CommandAbortedException&)
2223 : {
2224 : // any command wasn't executed successfully - not specified
2225 0 : SetError( ERRCODE_IO_GENERAL );
2226 0 : return COMMIT_RESULT_FAILURE;
2227 : }
2228 0 : catch (const RuntimeException&)
2229 : {
2230 : // any other error - not specified
2231 0 : SetError( ERRCODE_IO_GENERAL );
2232 0 : return COMMIT_RESULT_FAILURE;
2233 : }
2234 0 : catch (const Exception&)
2235 : {
2236 : // any other error - not specified
2237 0 : SetError( ERRCODE_IO_GENERAL );
2238 0 : return COMMIT_RESULT_FAILURE;
2239 : }
2240 :
2241 0 : if ( m_bIsRoot && m_pContent )
2242 : {
2243 : // the root storage must flush the root package content
2244 0 : if ( nRet == COMMIT_RESULT_SUCCESS )
2245 : {
2246 : try
2247 : {
2248 : // commit the media type to the JAR file
2249 : // clipboard format and ClassId will be retrieved from the media type when the file is loaded again
2250 0 : Any aType;
2251 0 : aType <<= m_aContentType;
2252 0 : m_pContent->setPropertyValue("MediaType", aType );
2253 :
2254 0 : if ( m_bIsLinked )
2255 : {
2256 : // write a manifest file
2257 : // first create a subfolder "META-inf"
2258 0 : Content aNewSubFolder;
2259 0 : bool bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, OUString("META-INF"), aNewSubFolder );
2260 0 : if ( bRet )
2261 : {
2262 : // create a stream to write the manifest file - use a temp file
2263 0 : OUString aURL( aNewSubFolder.getURL() );
2264 0 : boost::scoped_ptr< ::utl::TempFile> pTempFile(new ::utl::TempFile( &aURL ));
2265 :
2266 : // get the stream from the temp file and create an output stream wrapper
2267 0 : SvStream* pStream = pTempFile->GetStream( STREAM_STD_READWRITE );
2268 0 : ::utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *pStream );
2269 0 : com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > xOutputStream( pHelper );
2270 :
2271 : // create a manifest writer object that will fill the stream
2272 : Reference < ::com::sun::star::packages::manifest::XManifestWriter > xWriter =
2273 : ::com::sun::star::packages::manifest::ManifestWriter::create(
2274 0 : ::comphelper::getProcessComponentContext() );
2275 0 : sal_Int32 nCount = GetObjectCount() + 1;
2276 0 : Sequence < Sequence < PropertyValue > > aProps( nCount );
2277 0 : sal_Int32 nProps = 0;
2278 0 : GetProps( nProps, aProps, OUString() );
2279 0 : xWriter->writeManifestSequence( xOutputStream, aProps );
2280 :
2281 : // move the stream to its desired location
2282 0 : Content aSource( pTempFile->GetURL(), Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
2283 0 : xWriter = NULL;
2284 0 : xOutputStream = NULL;
2285 0 : pTempFile.reset();
2286 0 : aNewSubFolder.transferContent( aSource, InsertOperation_MOVE, OUString("manifest.xml"), NameClash::OVERWRITE );
2287 0 : }
2288 : }
2289 : else
2290 : {
2291 : #if OSL_DEBUG_LEVEL > 1
2292 : fprintf ( stderr, "Files: %i\n", nOpenFiles );
2293 : fprintf ( stderr, "Streams: %i\n", nOpenStreams );
2294 : #endif
2295 : // force writing
2296 0 : Any aAny;
2297 0 : m_pContent->executeCommand( OUString("flush"), aAny );
2298 0 : if ( m_pSource != 0 )
2299 : {
2300 0 : boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( m_pTempFile->GetURL(), STREAM_STD_READ ));
2301 0 : m_pSource->SetStreamSize(0);
2302 : // m_pSource->Seek(0);
2303 0 : pStream->ReadStream( *m_pSource );
2304 0 : pStream.reset();
2305 0 : m_pSource->Seek(0);
2306 0 : }
2307 0 : }
2308 : }
2309 0 : catch (const CommandAbortedException&)
2310 : {
2311 : // how to tell the content : forget all changes ?!
2312 : // or should we assume that the content does it by itself because he throwed an exception ?!
2313 : // any command wasn't executed successfully - not specified
2314 0 : SetError( ERRCODE_IO_GENERAL );
2315 0 : return COMMIT_RESULT_FAILURE;
2316 : }
2317 0 : catch (const RuntimeException&)
2318 : {
2319 : // how to tell the content : forget all changes ?!
2320 : // or should we assume that the content does it by itself because he throwed an exception ?!
2321 : // any other error - not specified
2322 0 : SetError( ERRCODE_IO_GENERAL );
2323 0 : return COMMIT_RESULT_FAILURE;
2324 : }
2325 0 : catch (const InteractiveIOException& r)
2326 : {
2327 0 : if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
2328 0 : SetError( ERRCODE_IO_ACCESSDENIED );
2329 0 : else if ( r.Code == IOErrorCode_NOT_EXISTING )
2330 0 : SetError( ERRCODE_IO_NOTEXISTS );
2331 0 : else if ( r.Code == IOErrorCode_CANT_READ )
2332 0 : SetError( ERRCODE_IO_CANTREAD );
2333 0 : else if ( r.Code == IOErrorCode_CANT_WRITE )
2334 0 : SetError( ERRCODE_IO_CANTWRITE );
2335 : else
2336 0 : SetError( ERRCODE_IO_GENERAL );
2337 :
2338 0 : return COMMIT_RESULT_FAILURE;
2339 : }
2340 0 : catch (const Exception&)
2341 : {
2342 : // how to tell the content : forget all changes ?!
2343 : // or should we assume that the content does it by itself because he throwed an exception ?!
2344 : // any other error - not specified
2345 0 : SetError( ERRCODE_IO_GENERAL );
2346 0 : return COMMIT_RESULT_FAILURE;
2347 : }
2348 : }
2349 0 : else if ( nRet != COMMIT_RESULT_NOTHING_TO_DO )
2350 : {
2351 : // how to tell the content : forget all changes ?! Should we ?!
2352 0 : SetError( ERRCODE_IO_GENERAL );
2353 0 : return nRet;
2354 : }
2355 :
2356 : // after successful root commit all elements names and types are adjusted and all removed elements
2357 : // are also removed from the lists
2358 0 : for ( size_t i = 0; i < m_aChildrenList.size(); )
2359 : {
2360 0 : UCBStorageElement_Impl* pInnerElement = m_aChildrenList[ i ];
2361 0 : if ( pInnerElement->m_bIsRemoved )
2362 : {
2363 0 : UCBStorageElementList_Impl::iterator it = m_aChildrenList.begin();
2364 0 : ::std::advance( it, i );
2365 0 : delete *it;
2366 0 : m_aChildrenList.erase( it );
2367 : }
2368 : else
2369 : {
2370 0 : pInnerElement->m_aOriginalName = pInnerElement->m_aName;
2371 0 : pInnerElement->m_bIsInserted = false;
2372 0 : ++i;
2373 : }
2374 : }
2375 : }
2376 :
2377 0 : m_bCommited = false;
2378 : }
2379 :
2380 0 : return nRet;
2381 : }
2382 :
2383 0 : bool UCBStorage_Impl::Revert()
2384 : {
2385 0 : for ( size_t i = 0; i < m_aChildrenList.size(); )
2386 : {
2387 0 : UCBStorageElement_Impl* pElement = m_aChildrenList[ i ];
2388 0 : pElement->m_bIsRemoved = false;
2389 0 : if ( pElement->m_bIsInserted )
2390 : {
2391 0 : UCBStorageElementList_Impl::iterator it = m_aChildrenList.begin();
2392 0 : ::std::advance( it, i );
2393 0 : delete *it;
2394 0 : m_aChildrenList.erase( it );
2395 : }
2396 : else
2397 : {
2398 0 : if ( pElement->m_xStream.Is() )
2399 : {
2400 0 : pElement->m_xStream->m_bCommited = false;
2401 0 : pElement->m_xStream->Revert();
2402 : }
2403 0 : else if ( pElement->m_xStorage.Is() )
2404 : {
2405 0 : pElement->m_xStorage->m_bCommited = false;
2406 0 : pElement->m_xStorage->Revert();
2407 : }
2408 :
2409 0 : pElement->m_aName = pElement->m_aOriginalName;
2410 0 : pElement->m_bIsRemoved = false;
2411 0 : ++i;
2412 : }
2413 : }
2414 0 : return true;
2415 : }
2416 :
2417 2006 : const OUString& UCBStorage::GetName() const
2418 : {
2419 2006 : return pImp->m_aName; // pImp->m_aURL ?!
2420 : }
2421 :
2422 2036 : bool UCBStorage::IsRoot() const
2423 : {
2424 2036 : return pImp->m_bIsRoot;
2425 : }
2426 :
2427 0 : void UCBStorage::SetDirty()
2428 : {
2429 0 : pImp->m_bDirty = true;
2430 0 : }
2431 :
2432 0 : void UCBStorage::SetClass( const SvGlobalName & rClass, SotClipboardFormatId nOriginalClipFormat, const OUString & rUserTypeName )
2433 : {
2434 0 : pImp->m_aClassId = rClass;
2435 0 : pImp->m_nFormat = nOriginalClipFormat;
2436 0 : pImp->m_aUserTypeName = rUserTypeName;
2437 :
2438 : // in UCB storages only the content type will be stored, all other information can be reconstructed
2439 : // ( see the UCBStorage_Impl::Init() method )
2440 0 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
2441 0 : SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor );
2442 0 : pImp->m_aContentType = aDataFlavor.MimeType;
2443 0 : }
2444 :
2445 0 : void UCBStorage::SetClassId( const ClsId& rClsId )
2446 : {
2447 0 : pImp->m_aClassId = SvGlobalName( rClsId );
2448 0 : if ( pImp->m_aClassId == SvGlobalName() )
2449 0 : return;
2450 :
2451 : // in OLE storages the clipboard format an the user name will be transferred when a storage is copied because both are
2452 : // stored in one the substreams
2453 : // UCB storages store the content type information as content type in the manifest file and so this information must be
2454 : // kept up to date, and also the other type information that is hold only at runtime because it can be reconstructed from
2455 : // the content type
2456 0 : pImp->m_nFormat = GetFormatId_Impl( pImp->m_aClassId );
2457 0 : if ( pImp->m_nFormat != SotClipboardFormatId::NONE )
2458 : {
2459 0 : ::com::sun::star::datatransfer::DataFlavor aDataFlavor;
2460 0 : SotExchange::GetFormatDataFlavor( pImp->m_nFormat, aDataFlavor );
2461 0 : pImp->m_aUserTypeName = aDataFlavor.HumanPresentableName;
2462 0 : pImp->m_aContentType = aDataFlavor.MimeType;
2463 : }
2464 : }
2465 :
2466 0 : const ClsId& UCBStorage::GetClassId() const
2467 : {
2468 0 : return ( const ClsId& ) pImp->m_aClassId.GetCLSID();
2469 : }
2470 :
2471 0 : void UCBStorage::SetConvertClass( const SvGlobalName & /*rConvertClass*/, SotClipboardFormatId /*nOriginalClipFormat*/, const OUString & /*rUserTypeName*/ )
2472 : {
2473 : // ???
2474 0 : }
2475 :
2476 0 : bool UCBStorage::ShouldConvert()
2477 : {
2478 : // ???
2479 0 : return false;
2480 : }
2481 :
2482 0 : SvGlobalName UCBStorage::GetClassName()
2483 : {
2484 0 : return pImp->m_aClassId;
2485 : }
2486 :
2487 0 : SotClipboardFormatId UCBStorage::GetFormat()
2488 : {
2489 0 : return pImp->m_nFormat;
2490 : }
2491 :
2492 0 : OUString UCBStorage::GetUserName()
2493 : {
2494 : OSL_FAIL("UserName is not implemented in UCB storages!" );
2495 0 : return pImp->m_aUserTypeName;
2496 : }
2497 :
2498 0 : void UCBStorage::FillInfoList( SvStorageInfoList* pList ) const
2499 : {
2500 : // put information in childrenlist into StorageInfoList
2501 0 : for ( size_t i = 0; i < pImp->GetChildrenList().size(); ++i )
2502 : {
2503 0 : UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
2504 0 : if ( !pElement->m_bIsRemoved )
2505 : {
2506 : // problem: what about the size of a substorage ?!
2507 0 : sal_uLong nSize = pElement->m_nSize;
2508 0 : if ( pElement->m_xStream.Is() )
2509 0 : nSize = pElement->m_xStream->GetSize();
2510 0 : SvStorageInfo aInfo( pElement->m_aName, nSize, pElement->m_bIsStorage );
2511 0 : pList->push_back( aInfo );
2512 : }
2513 : }
2514 0 : }
2515 :
2516 0 : bool UCBStorage::CopyStorageElement_Impl( UCBStorageElement_Impl& rElement, BaseStorage* pDest, const OUString& rNew ) const
2517 : {
2518 : // insert stream or storage into the list or stream of the destination storage
2519 : // not into the content, this will be done on commit !
2520 : // be aware of name changes !
2521 0 : if ( !rElement.m_bIsStorage )
2522 : {
2523 : // copy the streams data
2524 : // the destination stream must not be open
2525 0 : boost::scoped_ptr<BaseStorageStream> pOtherStream(pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ));
2526 0 : BaseStorageStream* pStream = NULL;
2527 0 : bool bDeleteStream = false;
2528 :
2529 : // if stream is already open, it is allowed to copy it, so be aware of this
2530 0 : if ( rElement.m_xStream.Is() )
2531 0 : pStream = rElement.m_xStream->m_pAntiImpl;
2532 0 : if ( !pStream )
2533 : {
2534 0 : pStream = ( const_cast < UCBStorage* > (this) )->OpenStream( rElement.m_aName, STREAM_STD_READ, pImp->m_bDirect );
2535 0 : bDeleteStream = true;
2536 : }
2537 :
2538 0 : pStream->CopyTo( pOtherStream.get() );
2539 0 : SetError( pStream->GetError() );
2540 0 : if( pOtherStream->GetError() )
2541 0 : pDest->SetError( pOtherStream->GetError() );
2542 : else
2543 0 : pOtherStream->Commit();
2544 :
2545 0 : if ( bDeleteStream )
2546 0 : delete pStream;
2547 : }
2548 : else
2549 : {
2550 : // copy the storage content
2551 : // the destination storage must not be open
2552 0 : BaseStorage* pStorage = NULL;
2553 :
2554 : // if stream is already open, it is allowed to copy it, so be aware of this
2555 0 : bool bDeleteStorage = false;
2556 0 : if ( rElement.m_xStorage.Is() )
2557 0 : pStorage = rElement.m_xStorage->m_pAntiImpl;
2558 0 : if ( !pStorage )
2559 : {
2560 0 : pStorage = ( const_cast < UCBStorage* > (this) )->OpenStorage( rElement.m_aName, pImp->m_nMode, pImp->m_bDirect );
2561 0 : bDeleteStorage = true;
2562 : }
2563 :
2564 0 : UCBStorage* pUCBDest = PTR_CAST( UCBStorage, pDest );
2565 0 : UCBStorage* pUCBCopy = PTR_CAST( UCBStorage, pStorage );
2566 :
2567 0 : bool bOpenUCBStorage = pUCBDest && pUCBCopy;
2568 : boost::scoped_ptr<BaseStorage> pOtherStorage(bOpenUCBStorage ?
2569 0 : pDest->OpenUCBStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ) :
2570 0 : pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pImp->m_bDirect ));
2571 :
2572 : // For UCB storages, the class id and the format id may differ,
2573 : // do passing the class id is not sufficient.
2574 0 : if( bOpenUCBStorage )
2575 0 : pOtherStorage->SetClass( pStorage->GetClassName(),
2576 0 : pStorage->GetFormat(),
2577 0 : pUCBCopy->pImp->m_aUserTypeName );
2578 : else
2579 0 : pOtherStorage->SetClassId( pStorage->GetClassId() );
2580 0 : pStorage->CopyTo( pOtherStorage.get() );
2581 0 : SetError( pStorage->GetError() );
2582 0 : if( pOtherStorage->GetError() )
2583 0 : pDest->SetError( pOtherStorage->GetError() );
2584 : else
2585 0 : pOtherStorage->Commit();
2586 :
2587 0 : if ( bDeleteStorage )
2588 0 : delete pStorage;
2589 : }
2590 :
2591 0 : return Good() && pDest->Good();
2592 : }
2593 :
2594 4012 : UCBStorageElement_Impl* UCBStorage::FindElement_Impl( const OUString& rName ) const
2595 : {
2596 : DBG_ASSERT( !rName.isEmpty(), "Name is empty!" );
2597 4012 : for ( size_t i = 0, n = pImp->GetChildrenList().size(); i < n; ++i )
2598 : {
2599 0 : UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
2600 0 : if ( pElement->m_aName == rName && !pElement->m_bIsRemoved )
2601 0 : return pElement;
2602 : }
2603 4012 : return NULL;
2604 : }
2605 :
2606 0 : bool UCBStorage::CopyTo( BaseStorage* pDestStg ) const
2607 : {
2608 : DBG_ASSERT( pDestStg != static_cast<BaseStorage const *>(this), "Self-Copying is not possible!" );
2609 0 : if ( pDestStg == static_cast<BaseStorage const *>(this) )
2610 0 : return false;
2611 :
2612 : // perhaps it's also a problem if one storage is a parent of the other ?!
2613 : // or if not: could be optimized ?!
2614 :
2615 : // For UCB storages, the class id and the format id may differ,
2616 : // do passing the class id is not sufficient.
2617 0 : if( pDestStg->ISA( UCBStorage ) )
2618 : pDestStg->SetClass( pImp->m_aClassId, pImp->m_nFormat,
2619 0 : pImp->m_aUserTypeName );
2620 : else
2621 0 : pDestStg->SetClassId( GetClassId() );
2622 0 : pDestStg->SetDirty();
2623 :
2624 0 : bool bRet = true;
2625 0 : for ( size_t i = 0; i < pImp->GetChildrenList().size() && bRet; ++i )
2626 : {
2627 0 : UCBStorageElement_Impl* pElement = pImp->GetChildrenList()[ i ];
2628 0 : if ( !pElement->m_bIsRemoved )
2629 0 : bRet = CopyStorageElement_Impl( *pElement, pDestStg, pElement->m_aName );
2630 : }
2631 :
2632 0 : if( !bRet )
2633 0 : SetError( pDestStg->GetError() );
2634 0 : return Good() && pDestStg->Good();
2635 : }
2636 :
2637 0 : bool UCBStorage::CopyTo( const OUString& rElemName, BaseStorage* pDest, const OUString& rNew )
2638 : {
2639 0 : if( rElemName.isEmpty() )
2640 0 : return false;
2641 :
2642 0 : if ( pDest == static_cast<BaseStorage*>(this) )
2643 : {
2644 : // can't double an element
2645 0 : return false;
2646 : }
2647 : else
2648 : {
2649 : // for copying no optimization is useful, because in every case the stream data must be copied
2650 0 : UCBStorageElement_Impl* pElement = FindElement_Impl( rElemName );
2651 0 : if ( pElement )
2652 0 : return CopyStorageElement_Impl( *pElement, pDest, rNew );
2653 : else
2654 : {
2655 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
2656 0 : return false;
2657 : }
2658 : }
2659 : }
2660 :
2661 0 : bool UCBStorage::Commit()
2662 : {
2663 : // mark this storage for sending it on root commit
2664 0 : pImp->m_bCommited = true;
2665 0 : if ( pImp->m_bIsRoot )
2666 : // the root storage coordinates committing by sending a Commit command to its content
2667 0 : return ( pImp->Commit() != COMMIT_RESULT_FAILURE );
2668 : else
2669 0 : return true;
2670 : }
2671 :
2672 0 : bool UCBStorage::Revert()
2673 : {
2674 0 : return pImp->Revert();
2675 : }
2676 :
2677 0 : BaseStorageStream* UCBStorage::OpenStream( const OUString& rEleName, StreamMode nMode, bool bDirect, const OString* pKey )
2678 : {
2679 0 : if( rEleName.isEmpty() )
2680 0 : return NULL;
2681 :
2682 : // try to find the storage element
2683 0 : UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2684 0 : if ( !pElement )
2685 : {
2686 : // element does not exist, check if creation is allowed
2687 0 : if( ( nMode & StreamMode::NOCREATE ) )
2688 : {
2689 0 : SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
2690 0 : OUString aName( pImp->m_aURL );
2691 0 : aName += "/";
2692 0 : aName += rEleName;
2693 0 : UCBStorageStream* pStream = new UCBStorageStream( aName, nMode, bDirect, pKey, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
2694 0 : pStream->SetError( GetError() );
2695 0 : pStream->pImp->m_aName = rEleName;
2696 0 : return pStream;
2697 : }
2698 : else
2699 : {
2700 : // create a new UCBStorageElement and insert it into the list
2701 0 : pElement = new UCBStorageElement_Impl( rEleName );
2702 0 : pElement->m_bIsInserted = true;
2703 0 : pImp->m_aChildrenList.push_back( pElement );
2704 : }
2705 : }
2706 :
2707 0 : if ( !pElement->m_bIsFolder )
2708 : {
2709 : // check if stream is already created
2710 0 : if ( pElement->m_xStream.Is() )
2711 : {
2712 : // stream has already been created; if it has no external reference, it may be opened another time
2713 0 : if ( pElement->m_xStream->m_pAntiImpl )
2714 : {
2715 : OSL_FAIL("Stream is already open!" );
2716 0 : SetError( SVSTREAM_ACCESS_DENIED ); // ???
2717 0 : return NULL;
2718 : }
2719 : else
2720 : {
2721 : // check if stream is opened with the same keyword as before
2722 : // if not, generate a new stream because it could be encrypted vs. decrypted!
2723 0 : OString aKey;
2724 0 : if ( pKey )
2725 0 : aKey = *pKey;
2726 0 : if ( pElement->m_xStream->m_aKey == aKey )
2727 : {
2728 0 : pElement->m_xStream->PrepareCachedForReopen( nMode );
2729 :
2730 0 : return new UCBStorageStream( pElement->m_xStream );
2731 0 : }
2732 : }
2733 : }
2734 :
2735 : // stream is opened the first time
2736 0 : pImp->OpenStream( pElement, nMode, bDirect, pKey );
2737 :
2738 : // if name has been changed before creating the stream: set name!
2739 0 : pElement->m_xStream->m_aName = rEleName;
2740 0 : return new UCBStorageStream( pElement->m_xStream );
2741 : }
2742 :
2743 0 : return NULL;
2744 : }
2745 :
2746 0 : UCBStorageStream_Impl* UCBStorage_Impl::OpenStream( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect, const OString* pKey )
2747 : {
2748 0 : OUString aName( m_aURL );
2749 0 : aName += "/";
2750 0 : aName += pElement->m_aOriginalName;
2751 0 : pElement->m_xStream = new UCBStorageStream_Impl( aName, nMode, NULL, bDirect, pKey, m_bRepairPackage, m_xProgressHandler );
2752 0 : return pElement->m_xStream;
2753 : }
2754 :
2755 0 : BaseStorage* UCBStorage::OpenUCBStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
2756 : {
2757 0 : if( rEleName.isEmpty() )
2758 0 : return NULL;
2759 :
2760 0 : return OpenStorage_Impl( rEleName, nMode, bDirect, true );
2761 : }
2762 :
2763 0 : BaseStorage* UCBStorage::OpenOLEStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
2764 : {
2765 0 : if( rEleName.isEmpty() )
2766 0 : return NULL;
2767 :
2768 0 : return OpenStorage_Impl( rEleName, nMode, bDirect, false );
2769 : }
2770 :
2771 0 : BaseStorage* UCBStorage::OpenStorage( const OUString& rEleName, StreamMode nMode, bool bDirect )
2772 : {
2773 0 : if( rEleName.isEmpty() )
2774 0 : return NULL;
2775 :
2776 0 : return OpenStorage_Impl( rEleName, nMode, bDirect, true );
2777 : }
2778 :
2779 0 : BaseStorage* UCBStorage::OpenStorage_Impl( const OUString& rEleName, StreamMode nMode, bool bDirect, bool bForceUCBStorage )
2780 : {
2781 : // try to find the storage element
2782 0 : UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2783 0 : if ( !pElement )
2784 : {
2785 : // element does not exist, check if creation is allowed
2786 0 : if( ( nMode & StreamMode::NOCREATE ) )
2787 : {
2788 0 : SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
2789 0 : OUString aName( pImp->m_aURL );
2790 0 : aName += "/";
2791 0 : aName += rEleName; // ???
2792 0 : UCBStorage *pStorage = new UCBStorage( aName, nMode, bDirect, false, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
2793 0 : pStorage->pImp->m_bIsRoot = false;
2794 0 : pStorage->pImp->m_bListCreated = true; // the storage is pretty new, nothing to read
2795 0 : pStorage->SetError( GetError() );
2796 0 : return pStorage;
2797 : }
2798 :
2799 : // create a new UCBStorageElement and insert it into the list
2800 : // problem: perhaps an OLEStorage should be created ?!
2801 : // Because nothing is known about the element that should be created, an external parameter is needed !
2802 0 : pElement = new UCBStorageElement_Impl( rEleName );
2803 0 : pElement->m_bIsInserted = true;
2804 0 : pImp->m_aChildrenList.push_back( pElement );
2805 : }
2806 :
2807 0 : if ( !pElement->m_bIsFolder && ( pElement->m_bIsStorage || !bForceUCBStorage ) )
2808 : {
2809 : // create OLE storages on a stream ( see ctor of SotStorage )
2810 : // Such a storage will be created on a UCBStorageStream; it will write into the stream
2811 : // if it is opened in direct mode or when it is committed. In this case the stream will be
2812 : // modified and then it MUST be treated as committed.
2813 0 : if ( !pElement->m_xStream.Is() )
2814 : {
2815 0 : BaseStorageStream* pStr = OpenStream( rEleName, nMode, bDirect );
2816 0 : UCBStorageStream* pStream = PTR_CAST( UCBStorageStream, pStr );
2817 0 : if ( !pStream )
2818 : {
2819 0 : SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
2820 0 : return NULL;
2821 : }
2822 :
2823 0 : pElement->m_xStream = pStream->pImp;
2824 0 : delete pStream;
2825 : }
2826 :
2827 0 : pElement->m_xStream->PrepareCachedForReopen( nMode );
2828 0 : bool bInited = pElement->m_xStream->Init();
2829 0 : if (!bInited)
2830 : {
2831 0 : SetError( ( nMode & StreamMode::WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
2832 0 : return NULL;
2833 : }
2834 :
2835 0 : pElement->m_bIsStorage = true;
2836 0 : return pElement->m_xStream->CreateStorage(); // can only be created in transacted mode
2837 : }
2838 0 : else if ( pElement->m_xStorage.Is() )
2839 : {
2840 : // storage has already been opened; if it has no external reference, it may be opened another time
2841 0 : if ( pElement->m_xStorage->m_pAntiImpl )
2842 : {
2843 : OSL_FAIL("Storage is already open!" );
2844 0 : SetError( SVSTREAM_ACCESS_DENIED ); // ???
2845 : }
2846 : else
2847 : {
2848 0 : bool bIsWritable = bool( pElement->m_xStorage->m_nMode & StreamMode::WRITE );
2849 0 : if ( !bIsWritable && ( nMode & StreamMode::WRITE ) )
2850 : {
2851 0 : OUString aName( pImp->m_aURL );
2852 0 : aName += "/";
2853 0 : aName += pElement->m_aOriginalName;
2854 0 : UCBStorage* pStorage = new UCBStorage( aName, nMode, bDirect, false, pImp->m_bRepairPackage, pImp->m_xProgressHandler );
2855 0 : pElement->m_xStorage = pStorage->pImp;
2856 0 : return pStorage;
2857 : }
2858 : else
2859 : {
2860 0 : return new UCBStorage( pElement->m_xStorage );
2861 : }
2862 : }
2863 : }
2864 0 : else if ( !pElement->m_xStream.Is() )
2865 : {
2866 : // storage is opened the first time
2867 0 : bool bIsWritable = bool(pImp->m_nMode & StreamMode::WRITE);
2868 0 : if ( pImp->m_bIsLinked && pImp->m_bIsRoot && bIsWritable )
2869 : {
2870 : // make sure that the root storage object has been created before substorages will be created
2871 0 : INetURLObject aFolderObj( pImp->m_aURL );
2872 0 : aFolderObj.removeSegment();
2873 :
2874 0 : Content aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ), Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
2875 0 : pImp->m_pContent = new Content;
2876 0 : bool bRet = ::utl::UCBContentHelper::MakeFolder( aFolder, pImp->m_aName, *pImp->m_pContent );
2877 0 : if ( !bRet )
2878 : {
2879 0 : SetError( SVSTREAM_CANNOT_MAKE );
2880 0 : return NULL;
2881 0 : }
2882 : }
2883 :
2884 0 : UCBStorage_Impl* pStor = pImp->OpenStorage( pElement, nMode, bDirect );
2885 0 : if ( pStor )
2886 : {
2887 0 : if ( pElement->m_bIsInserted )
2888 0 : pStor->m_bListCreated = true; // the storage is pretty new, nothing to read
2889 :
2890 0 : return new UCBStorage( pStor );
2891 : }
2892 : }
2893 :
2894 0 : return NULL;
2895 : }
2896 :
2897 0 : UCBStorage_Impl* UCBStorage_Impl::OpenStorage( UCBStorageElement_Impl* pElement, StreamMode nMode, bool bDirect )
2898 : {
2899 0 : UCBStorage_Impl* pRet = NULL;
2900 0 : OUString aName( m_aURL );
2901 0 : aName += "/";
2902 0 : aName += pElement->m_aOriginalName; // ???
2903 :
2904 0 : pElement->m_bIsStorage = pElement->m_bIsFolder = true;
2905 :
2906 0 : if ( m_bIsLinked && !::utl::UCBContentHelper::Exists( aName ) )
2907 : {
2908 0 : Content aNewFolder;
2909 0 : bool bRet = ::utl::UCBContentHelper::MakeFolder( *m_pContent, pElement->m_aOriginalName, aNewFolder );
2910 0 : if ( bRet )
2911 0 : pRet = new UCBStorage_Impl( aNewFolder, aName, nMode, NULL, bDirect, false, m_bRepairPackage, m_xProgressHandler );
2912 : }
2913 : else
2914 : {
2915 0 : pRet = new UCBStorage_Impl( aName, nMode, NULL, bDirect, false, m_bRepairPackage, m_xProgressHandler );
2916 : }
2917 :
2918 0 : if ( pRet )
2919 : {
2920 0 : pRet->m_bIsLinked = m_bIsLinked;
2921 0 : pRet->m_bIsRoot = false;
2922 :
2923 : // if name has been changed before creating the stream: set name!
2924 0 : pRet->m_aName = pElement->m_aOriginalName;
2925 0 : pElement->m_xStorage = pRet;
2926 : }
2927 :
2928 0 : if ( pRet )
2929 0 : pRet->Init();
2930 :
2931 0 : return pRet;
2932 : }
2933 :
2934 0 : bool UCBStorage::IsStorage( const OUString& rEleName ) const
2935 : {
2936 0 : if( rEleName.isEmpty() )
2937 0 : return false;
2938 :
2939 0 : const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2940 0 : return ( pElement && pElement->m_bIsStorage );
2941 : }
2942 :
2943 4012 : bool UCBStorage::IsStream( const OUString& rEleName ) const
2944 : {
2945 4012 : if( rEleName.isEmpty() )
2946 0 : return false;
2947 :
2948 4012 : const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2949 4012 : return ( pElement && !pElement->m_bIsStorage );
2950 : }
2951 :
2952 0 : bool UCBStorage::IsContained( const OUString & rEleName ) const
2953 : {
2954 0 : if( rEleName.isEmpty() )
2955 0 : return false;
2956 0 : const UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2957 0 : return ( pElement != NULL );
2958 : }
2959 :
2960 0 : bool UCBStorage::Remove( const OUString& rEleName )
2961 : {
2962 0 : if( rEleName.isEmpty() )
2963 0 : return false;
2964 :
2965 0 : UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2966 0 : if ( pElement )
2967 : {
2968 0 : pElement->m_bIsRemoved = true;
2969 : }
2970 : else
2971 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
2972 :
2973 0 : return ( pElement != NULL );
2974 : }
2975 :
2976 0 : bool UCBStorage::Rename( const OUString& rEleName, const OUString& rNewName )
2977 : {
2978 0 : if( rEleName.isEmpty()|| rNewName.isEmpty() )
2979 0 : return false;
2980 :
2981 0 : UCBStorageElement_Impl *pAlreadyExisting = FindElement_Impl( rNewName );
2982 0 : if ( pAlreadyExisting )
2983 : {
2984 0 : SetError( SVSTREAM_ACCESS_DENIED );
2985 0 : return false; // can't change to a name that is already used
2986 : }
2987 :
2988 0 : UCBStorageElement_Impl *pElement = FindElement_Impl( rEleName );
2989 0 : if ( pElement )
2990 : {
2991 0 : pElement->m_aName = rNewName;
2992 : }
2993 : else
2994 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
2995 :
2996 0 : return pElement != NULL;
2997 : }
2998 :
2999 0 : bool UCBStorage::MoveTo( const OUString& rEleName, BaseStorage* pNewSt, const OUString& rNewName )
3000 : {
3001 0 : if( rEleName.isEmpty() || rNewName.isEmpty() )
3002 0 : return false;
3003 :
3004 0 : if ( pNewSt == static_cast<BaseStorage*>(this) && !FindElement_Impl( rNewName ) )
3005 : {
3006 0 : return Rename( rEleName, rNewName );
3007 : }
3008 : else
3009 : {
3010 : /*
3011 : if ( PTR_CAST( UCBStorage, pNewSt ) )
3012 : {
3013 : // because the element is moved, not copied, a special optimization is possible :
3014 : // first copy the UCBStorageElement; flag old element as "Removed" and new as "Inserted",
3015 : // clear original name/type of the new element
3016 : // if moved element is open: copy content, but change absolute URL ( and those of all children of the element! ),
3017 : // clear original name/type of new content, keep the old original stream/storage, but forget its working streams,
3018 : // close original UCBContent and original stream, only the TempFile and its stream may remain unchanged, but now
3019 : // belong to the new content
3020 : // if original and editable stream are identical ( readonly element ), it has to be copied to the editable
3021 : // stream of the destination object
3022 : // Not implemented at the moment ( risky?! ), perhaps later
3023 : }
3024 : */
3025 : // MoveTo is done by first copying to the new destination and then removing the old element
3026 0 : bool bRet = CopyTo( rEleName, pNewSt, rNewName );
3027 0 : if ( bRet )
3028 0 : bRet = Remove( rEleName );
3029 0 : return bRet;
3030 : }
3031 : }
3032 :
3033 0 : bool UCBStorage::ValidateFAT()
3034 : {
3035 : // ???
3036 0 : return true;
3037 : }
3038 :
3039 0 : bool UCBStorage::Validate( bool bWrite ) const
3040 : {
3041 : // ???
3042 0 : return ( !bWrite || ( pImp->m_nMode & StreamMode::WRITE ) );
3043 : }
3044 :
3045 0 : bool UCBStorage::ValidateMode( StreamMode m ) const
3046 : {
3047 : // ???
3048 0 : if( m == ( StreamMode::READ | StreamMode::TRUNC ) ) // from stg.cxx
3049 0 : return true;
3050 : // only SHARE_DENYALL allowed
3051 : // storages open in r/o mode are OK, since only
3052 : // the commit may fail
3053 0 : if( m & StreamMode::SHARE_DENYALL )
3054 0 : return true;
3055 :
3056 0 : return true;
3057 : }
3058 :
3059 0 : const SvStream* UCBStorage::GetSvStream() const
3060 : {
3061 : // this would cause a complete download of the file
3062 : // as it looks, this method is NOT used inside of SOT, only exported by class SotStorage - but for what ???
3063 0 : return pImp->m_pSource;
3064 : }
3065 :
3066 0 : bool UCBStorage::Equals( const BaseStorage& rStorage ) const
3067 : {
3068 : // ???
3069 0 : return static_cast<BaseStorage const *>(this) == &rStorage;
3070 : }
3071 :
3072 2545 : bool UCBStorage::IsStorageFile( SvStream* pFile )
3073 : {
3074 2545 : if ( !pFile )
3075 0 : return false;
3076 :
3077 2545 : sal_uLong nPos = pFile->Tell();
3078 2545 : pFile->Seek( STREAM_SEEK_TO_END );
3079 2545 : if ( pFile->Tell() < 4 )
3080 122 : return false;
3081 :
3082 2423 : pFile->Seek(0);
3083 2423 : sal_uInt32 nBytes(0);
3084 2423 : pFile->ReadUInt32( nBytes );
3085 :
3086 : // search for the magic bytes
3087 2423 : bool bRet = ( nBytes == 0x04034b50 );
3088 2423 : if ( !bRet )
3089 : {
3090 : // disk spanned file have an additional header in front of the usual one
3091 2304 : bRet = ( nBytes == 0x08074b50 );
3092 2304 : if ( bRet )
3093 : {
3094 0 : nBytes = 0;
3095 0 : pFile->ReadUInt32( nBytes );
3096 0 : bRet = ( nBytes == 0x04034b50 );
3097 : }
3098 : }
3099 :
3100 2423 : pFile->Seek( nPos );
3101 2423 : return bRet;
3102 : }
3103 :
3104 30 : OUString UCBStorage::GetLinkedFile( SvStream &rStream )
3105 : {
3106 30 : OUString aString;
3107 30 : sal_uLong nPos = rStream.Tell();
3108 30 : rStream.Seek( STREAM_SEEK_TO_END );
3109 30 : if ( !rStream.Tell() )
3110 0 : return aString;
3111 :
3112 30 : rStream.Seek(0);
3113 : sal_uInt32 nBytes;
3114 30 : rStream.ReadUInt32( nBytes );
3115 30 : if( nBytes == 0x04034b50 )
3116 : {
3117 30 : OString aTmp = read_uInt16_lenPrefixed_uInt8s_ToOString(rStream);
3118 30 : if (aTmp.match("ContentURL="))
3119 : {
3120 0 : aString = OStringToOUString(aTmp.copy(11), RTL_TEXTENCODING_UTF8);
3121 30 : }
3122 : }
3123 :
3124 30 : rStream.Seek( nPos );
3125 30 : return aString;
3126 : }
3127 :
3128 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|