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