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 :
21 : #include <sot/storinfo.hxx>
22 : #include <osl/file.hxx>
23 : #include <unotools/tempfile.hxx>
24 : #include <tools/stream.hxx>
25 : #include <tools/debug.hxx>
26 :
27 : #include "sot/stg.hxx"
28 : #include "stgelem.hxx"
29 : #include "stgcache.hxx"
30 : #include "stgstrms.hxx"
31 : #include "stgdir.hxx"
32 : #include "stgio.hxx"
33 : #include "stgole.hxx"
34 :
35 : static long nTmpCount = 0;
36 :
37 : // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly
38 : // by itself. It inhibits the checking of sharing modes and is used
39 : // during CopyTo() and MoveTo() for opening a stream in read mode
40 : // although it may be open in DENYALL mode
41 :
42 : #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC )
43 :
44 : ///////////////////////// class StorageBase
45 :
46 3460 : TYPEINIT0( StorageBase );
47 0 : TYPEINIT1( BaseStorageStream, StorageBase );
48 3460 : TYPEINIT1( BaseStorage, StorageBase );
49 :
50 17532 : StorageBase::StorageBase()
51 17532 : : m_bAutoCommit( false )
52 : {
53 17532 : m_nMode = STREAM_READ;
54 17532 : m_nError = SVSTREAM_OK;
55 17532 : }
56 :
57 17532 : StorageBase::~StorageBase()
58 : {
59 17532 : }
60 :
61 : // The following three methods are declared as const, since they
62 : // may be called from within a const method.
63 :
64 3826968 : sal_uLong StorageBase::GetError() const
65 : {
66 3826968 : sal_uLong n = m_nError;
67 3826968 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
68 3826968 : return n;
69 : }
70 :
71 23100 : void StorageBase::SetError( sal_uLong n ) const
72 : {
73 23100 : if( !m_nError )
74 22974 : ((StorageBase*) this)->m_nError = n;
75 23100 : }
76 :
77 12696 : void StorageBase::ResetError() const
78 : {
79 12696 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
80 12696 : }
81 :
82 : // Retrieve the underlying SvStream for info purposes
83 :
84 0 : const SvStream* OLEStorageBase::GetSvStream_Impl() const
85 : {
86 0 : return pIo ? pIo->GetStrm() : NULL;
87 : }
88 :
89 13830 : OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
90 13830 : : nStreamMode( nMode ), pIo( p ), pEntry( pe )
91 : {
92 13830 : if ( p )
93 13830 : p->IncRef();
94 13830 : if( pe )
95 11580 : pe->nRefCnt++;
96 13830 : }
97 :
98 13830 : OLEStorageBase::~OLEStorageBase()
99 : {
100 13830 : if( pEntry )
101 : {
102 : DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
103 12808 : if( !--pEntry->nRefCnt )
104 : {
105 12762 : if( pEntry->bZombie )
106 0 : delete pEntry;
107 : else
108 12762 : pEntry->Close();
109 : }
110 :
111 12808 : pEntry = NULL;
112 : }
113 :
114 :
115 13830 : if( pIo && !pIo->DecRef() )
116 : {
117 2048 : delete pIo;
118 2048 : pIo = NULL;
119 : }
120 13830 : }
121 :
122 : // Validate the instance for I/O
123 :
124 3880608 : bool OLEStorageBase::Validate_Impl( bool bWrite ) const
125 : {
126 3880608 : if( pIo
127 3880608 : && pIo->pTOC
128 3880488 : && pEntry
129 3879968 : && !pEntry->bInvalid
130 3879968 : && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
131 3879968 : return true;
132 640 : return false;
133 : }
134 :
135 19206 : bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
136 : {
137 19206 : if( m == INTERNAL_MODE )
138 3956 : return true;
139 15250 : sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
140 15250 : if( ( m & 3 ) == STREAM_READ )
141 : {
142 : // only SHARE_DENYWRITE or SHARE_DENYALL allowed
143 9814 : if( ( ( m & STREAM_SHARE_DENYWRITE )
144 96 : && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
145 9718 : || ( ( m & STREAM_SHARE_DENYALL )
146 9718 : && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
147 9814 : return true;
148 : }
149 : else
150 : {
151 : // only SHARE_DENYALL allowed
152 : // storages open in r/o mode are OK, since only
153 : // the commit may fail
154 5436 : if( ( m & STREAM_SHARE_DENYALL )
155 5436 : && ( nCurMode & STREAM_SHARE_DENYALL ) )
156 5436 : return true;
157 : }
158 0 : return false;
159 : }
160 :
161 :
162 : //////////////////////// class StorageStream
163 :
164 7664 : TYPEINIT1( StorageStream, BaseStorageStream );
165 :
166 11214 : StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
167 11214 : : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
168 : {
169 : // The dir entry may be 0; this means that the stream is invalid.
170 11214 : if( q && p )
171 : {
172 22024 : if( q->nRefCnt == 1 )
173 : {
174 11006 : q->nMode = m;
175 11006 : q->OpenStream( *p );
176 : }
177 : }
178 : else
179 202 : m &= ~STREAM_READWRITE;
180 11214 : m_nMode = m;
181 11214 : }
182 :
183 33642 : StorageStream::~StorageStream()
184 : {
185 : // Do an auto-commit if the entry is open in direct mode
186 11214 : if( m_bAutoCommit )
187 10950 : Commit();
188 11214 : if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
189 8 : pEntry->Commit();
190 22428 : }
191 :
192 1916 : bool StorageStream::Equals( const BaseStorageStream& rStream ) const
193 : {
194 1916 : const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
195 1916 : return pOther && ( pOther->pEntry == pEntry );
196 : }
197 :
198 2181092 : sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
199 : {
200 2181092 : if( Validate() )
201 : {
202 2180640 : pEntry->Seek( nPos );
203 2180640 : nSize = pEntry->Read( pData, (sal_Int32) nSize );
204 2180640 : pIo->MoveError( *this );
205 2180640 : nPos += nSize;
206 : }
207 : else
208 452 : nSize = 0L;
209 2181092 : return nSize;
210 : }
211 :
212 21446 : sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
213 : {
214 21446 : if( Validate( true ) )
215 : {
216 21446 : pEntry->Seek( nPos );
217 21446 : nSize = pEntry->Write( pData, (sal_Int32) nSize );
218 21446 : pIo->MoveError( *this );
219 21446 : nPos += nSize;
220 : }
221 : else
222 0 : nSize = 0L;
223 21446 : return nSize;
224 : }
225 :
226 1602922 : sal_uInt64 StorageStream::Seek( sal_uInt64 n )
227 : {
228 1602922 : if( Validate() )
229 1602914 : return nPos = pEntry->Seek( n );
230 : else
231 8 : return n;
232 : }
233 :
234 966 : void StorageStream::Flush()
235 : {
236 : // Flushing means committing, since streams are never transacted
237 966 : Commit();
238 966 : }
239 :
240 2066 : bool StorageStream::SetSize( sal_uLong nNewSize )
241 : {
242 2066 : if( Validate( true ) )
243 : {
244 2066 : bool b = pEntry->SetSize( (sal_Int32) nNewSize );
245 2066 : pIo->MoveError( *this );
246 2066 : return b;
247 : }
248 : else
249 0 : return false;
250 : }
251 :
252 23366 : sal_uLong StorageStream::GetSize() const
253 : {
254 23366 : if( Validate() )
255 23310 : return pEntry->GetSize();
256 56 : return 0;
257 : }
258 :
259 15902 : bool StorageStream::Commit()
260 : {
261 15902 : if( !Validate() )
262 0 : return false;
263 15902 : if( !( m_nMode & STREAM_WRITE ) )
264 : {
265 6558 : SetError( SVSTREAM_ACCESS_DENIED );
266 6558 : return false;
267 : }
268 : else
269 : {
270 9344 : pEntry->Commit();
271 9344 : pIo->MoveError( *this );
272 9344 : return Good();
273 : }
274 : }
275 :
276 0 : bool StorageStream::Revert()
277 : {
278 0 : bool bResult = false;
279 :
280 0 : if ( Validate() )
281 : {
282 0 : pEntry->Revert();
283 0 : pIo->MoveError( *this );
284 0 : bResult = Good();
285 : }
286 :
287 0 : return bResult;
288 : }
289 :
290 1916 : bool StorageStream::CopyTo( BaseStorageStream* pDest )
291 : {
292 1916 : if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
293 0 : return false;
294 1916 : pEntry->Copy( *pDest );
295 1916 : pDest->Commit();
296 1916 : pIo->MoveError( *this );
297 1916 : SetError( pDest->GetError() );
298 1916 : return Good() && pDest->Good();
299 : }
300 :
301 0 : const SvStream* StorageStream::GetSvStream() const
302 : {
303 0 : return GetSvStream_Impl();
304 : }
305 :
306 3850626 : bool StorageStream::Validate( bool bValidate ) const
307 : {
308 3850626 : bool bRet = Validate_Impl( bValidate );
309 3850626 : if ( !bRet )
310 516 : SetError( SVSTREAM_ACCESS_DENIED );
311 3850626 : return bRet;
312 : }
313 :
314 0 : bool StorageStream::ValidateMode( StreamMode nMode ) const
315 : {
316 0 : bool bRet = ValidateMode_Impl( nMode, NULL );
317 0 : if ( !bRet )
318 0 : SetError( SVSTREAM_ACCESS_DENIED );
319 0 : return bRet;
320 : }
321 :
322 : ///////////////////////// class SvStorageInfo
323 :
324 10202 : SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
325 : {
326 10202 : rE.aEntry.GetName( aName );
327 10202 : bStorage = rE.aEntry.GetType() == STG_STORAGE;
328 10202 : bStream = rE.aEntry.GetType() == STG_STREAM;
329 10202 : nSize = bStorage ? 0 : rE.aEntry.GetSize();
330 10202 : }
331 :
332 : /////////////////////////// class Storage
333 :
334 34 : bool Storage::IsStorageFile( const OUString & rFileName )
335 : {
336 34 : StgIo aIo;
337 34 : if( aIo.Open( rFileName, STREAM_STD_READ ) )
338 34 : return aIo.Load();
339 0 : return false;
340 : }
341 :
342 1486 : bool Storage::IsStorageFile( SvStream* pStream )
343 : {
344 1486 : bool bRet = false;
345 :
346 1486 : if ( pStream )
347 : {
348 1486 : StgHeader aHdr;
349 1486 : sal_uLong nPos = pStream->Tell();
350 1486 : bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
351 :
352 : // It's not a stream error if it is too small for a OLE storage header
353 1486 : if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
354 2 : pStream->ResetError();
355 1486 : pStream->Seek( nPos );
356 : }
357 :
358 1486 : return bRet;
359 : }
360 :
361 : // Open the storage file. If writing is permitted and the file is not
362 : // a storage file, initialize it.
363 :
364 6070 : TYPEINIT1( Storage, BaseStorage );
365 :
366 0 : Storage::Storage( const OUString& rFile, StreamMode m, bool bDirect )
367 0 : : OLEStorageBase( new StgIo, NULL, m_nMode )
368 0 : , aName( rFile ), bIsRoot( false )
369 : {
370 0 : bool bTemp = false;
371 0 : if( aName.isEmpty() )
372 : {
373 : // no name = temporary name!
374 0 : aName = utl::TempFile::CreateTempName();
375 0 : bTemp = true;
376 : }
377 : // the root storage creates the I/O system
378 0 : m_nMode = m;
379 0 : if( pIo->Open( aName, m ) )
380 : {
381 0 : Init( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC );
382 0 : if( pEntry )
383 : {
384 0 : pEntry->bDirect = bDirect;
385 0 : pEntry->nMode = m;
386 0 : pEntry->bTemp = bTemp;
387 : }
388 : }
389 : else
390 : {
391 0 : pIo->MoveError( *this );
392 0 : pEntry = NULL;
393 : }
394 0 : }
395 :
396 : // Create a storage on a given stream.
397 :
398 2048 : Storage::Storage( SvStream& r, bool bDirect )
399 2048 : : OLEStorageBase( new StgIo, NULL, m_nMode )
400 4096 : , bIsRoot( false )
401 : {
402 2048 : m_nMode = STREAM_READ;
403 2048 : if( r.IsWritable() )
404 2038 : m_nMode = STREAM_READ | STREAM_WRITE;
405 2048 : if( r.GetError() == SVSTREAM_OK )
406 : {
407 2020 : pIo->SetStrm( &r, false );
408 2020 : sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
409 2020 : r.Seek( 0L );
410 : // Initializing is OK if the stream is empty
411 2020 : Init( nSize == 0 );
412 2020 : if( pEntry )
413 : {
414 1228 : pEntry->bDirect = bDirect;
415 1228 : pEntry->nMode = m_nMode;
416 : }
417 2020 : pIo->MoveError( *this );
418 : }
419 : else
420 : {
421 28 : SetError( r.GetError() );
422 28 : pEntry = NULL;
423 : }
424 2048 : }
425 :
426 :
427 0 : Storage::Storage( UCBStorageStream& rStrm, bool bDirect )
428 0 : : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( false )
429 : {
430 0 : m_nMode = STREAM_READ;
431 :
432 0 : if ( rStrm.GetError() != SVSTREAM_OK )
433 : {
434 0 : SetError( rStrm.GetError() );
435 0 : pEntry = NULL;
436 0 : return;
437 : }
438 :
439 0 : SvStream* pStream = rStrm.GetModifySvStream();
440 0 : if ( !pStream )
441 : {
442 : OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!\n" );
443 0 : SetError( SVSTREAM_GENERALERROR );
444 0 : pEntry = NULL;
445 0 : return;
446 : }
447 :
448 0 : if( pStream->IsWritable() )
449 0 : m_nMode = STREAM_READ | STREAM_WRITE;
450 :
451 0 : pIo->SetStrm( &rStrm );
452 :
453 0 : sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
454 0 : pStream->Seek( 0L );
455 : // Initializing is OK if the stream is empty
456 0 : Init( nSize == 0 );
457 0 : if( pEntry )
458 : {
459 0 : pEntry->bDirect = bDirect;
460 0 : pEntry->nMode = m_nMode;
461 : }
462 :
463 0 : pIo->MoveError( *this );
464 : }
465 :
466 :
467 : // Perform common code for both ctors above.
468 :
469 2020 : void Storage::Init( bool bCreate )
470 : {
471 2020 : pEntry = NULL;
472 2020 : bool bHdrLoaded = false;
473 2020 : bIsRoot = true;
474 :
475 : OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
476 2020 : if( pIo->Good() && pIo->GetStrm() )
477 : {
478 2020 : sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
479 2020 : pIo->GetStrm()->Seek( 0L );
480 2020 : if( nSize )
481 : {
482 1669 : bHdrLoaded = pIo->Load();
483 1669 : if( !bHdrLoaded && !bCreate )
484 : {
485 : // File is not a storage and not empty; do not destroy!
486 792 : SetError( SVSTREAM_FILEFORMAT_ERROR );
487 2812 : return;
488 : }
489 : }
490 : }
491 : // file is a storage, empty or should be overwritten
492 1228 : pIo->ResetError();
493 : // we have to set up the data structures, since
494 : // the file is empty
495 1228 : if( !bHdrLoaded )
496 351 : pIo->Init();
497 1228 : if( pIo->Good() && pIo->pTOC )
498 : {
499 1228 : pEntry = pIo->pTOC->GetRoot();
500 1228 : pEntry->nRefCnt++;
501 : }
502 : }
503 :
504 : // Internal ctor
505 :
506 568 : Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
507 568 : : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
508 : {
509 568 : if( q )
510 568 : q->aEntry.GetName( aName );
511 : else
512 0 : m &= ~STREAM_READWRITE;
513 568 : m_nMode = m;
514 568 : if( q && q->nRefCnt == 1 )
515 528 : q->nMode = m;
516 568 : }
517 :
518 7848 : Storage::~Storage()
519 : {
520 : // Invalidate all open substorages
521 2616 : if( m_bAutoCommit )
522 394 : Commit();
523 2616 : if( pEntry )
524 : {
525 : // Do an auto-commit if the entry is open in direct mode
526 1796 : if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
527 30 : Commit();
528 1796 : if( pEntry->nRefCnt == 1 )
529 1756 : pEntry->Invalidate();
530 : }
531 : // close the stream is root storage
532 2616 : if( bIsRoot )
533 2020 : pIo->Close();
534 : // remove the file if temporary root storage
535 2616 : if( bIsRoot && pEntry && pEntry->bTemp )
536 : {
537 0 : osl::File::remove( GetName() );
538 : }
539 5232 : }
540 :
541 268 : const OUString& Storage::GetName() const
542 : {
543 268 : if( !bIsRoot && Validate() )
544 260 : pEntry->aEntry.GetName( ((Storage*) this)->aName );
545 268 : return aName;
546 : }
547 :
548 : // Fill in the info list for this storage
549 :
550 1950 : void Storage::FillInfoList( SvStorageInfoList* pList ) const
551 : {
552 1950 : if( Validate() && pList )
553 : {
554 1832 : StgIterator aIter( *pEntry );
555 1832 : StgDirEntry* p = aIter.First();
556 13866 : while( p )
557 : {
558 10202 : if( !p->bInvalid )
559 : {
560 10202 : SvStorageInfo aInfo( *p );
561 10202 : pList->push_back( aInfo );
562 : }
563 10202 : p = aIter.Next();
564 : }
565 : }
566 1950 : }
567 :
568 : // Open or create a substorage
569 :
570 0 : BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect )
571 : {
572 : OSL_FAIL("Not supported!");
573 0 : return OpenStorage( rName, m, bDirect );
574 : }
575 :
576 62 : BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
577 : {
578 62 : return OpenStorage( rName, m, bDirect );
579 : }
580 :
581 568 : BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
582 : {
583 568 : if( !Validate() || !ValidateMode( m ) )
584 0 : return new Storage( pIo, NULL, m );
585 568 : if( bDirect && !pEntry->bDirect )
586 0 : bDirect = false;
587 :
588 568 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
589 568 : if( !p )
590 : {
591 134 : if( !( m & STREAM_NOCREATE ) )
592 : {
593 134 : bool bTemp = false;
594 : // create a new storage
595 134 : OUString aNewName = rName;
596 134 : if( aNewName.isEmpty() )
597 : {
598 0 : aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
599 0 : bTemp = true;
600 : }
601 134 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
602 134 : if( p )
603 134 : p->bTemp = bTemp;
604 : }
605 134 : if( !p )
606 0 : pIo->SetError( ( m & STREAM_WRITE )
607 0 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
608 : }
609 434 : else if( !ValidateMode( m, p ) )
610 0 : p = NULL;
611 568 : if( p && p->aEntry.GetType() != STG_STORAGE )
612 : {
613 0 : pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
614 0 : p = NULL;
615 : }
616 :
617 : // Either direct or transacted mode is supported
618 568 : if( p && pEntry->nRefCnt == 1 )
619 568 : p->bDirect = bDirect;
620 :
621 : // Dont check direct conflict if opening readonly
622 568 : if( p && (m & STREAM_WRITE ))
623 : {
624 394 : if( p->bDirect != bDirect )
625 0 : SetError( SVSTREAM_ACCESS_DENIED );
626 : }
627 568 : Storage* pStg = new Storage( pIo, p, m );
628 568 : pIo->MoveError( *pStg );
629 568 : if( m & STREAM_WRITE ) pStg->m_bAutoCommit = true;
630 568 : return pStg;
631 : }
632 :
633 : // Open a stream
634 :
635 11214 : BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool,
636 : const OString*
637 : #ifdef DBG_UTIL
638 : pB
639 : #endif
640 : )
641 : {
642 : DBG_ASSERT(!pB, "Encryption not supported");
643 :
644 11214 : if( !Validate() || !ValidateMode( m ) )
645 4 : return new StorageStream( pIo, NULL, m );
646 11210 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
647 11210 : bool bTemp = false;
648 11210 : if( !p )
649 : {
650 4216 : if( !( m & STREAM_NOCREATE ) )
651 : {
652 : // create a new stream
653 : // make a name if the stream is temporary (has no name)
654 4018 : OUString aNewName( rName );
655 4018 : if( aNewName.isEmpty() )
656 : {
657 0 : aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
658 0 : bTemp = true;
659 : }
660 4018 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
661 : }
662 4216 : if( !p )
663 198 : pIo->SetError( ( m & STREAM_WRITE )
664 198 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
665 : }
666 6994 : else if( !ValidateMode( m, p ) )
667 0 : p = NULL;
668 11210 : if( p && p->aEntry.GetType() != STG_STREAM )
669 : {
670 0 : pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
671 0 : p = NULL;
672 : }
673 11210 : if( p )
674 : {
675 11012 : p->bTemp = bTemp;
676 11012 : p->bDirect = pEntry->bDirect;
677 : }
678 11210 : StorageStream* pStm = new StorageStream( pIo, p, m );
679 11210 : if( p && !p->bDirect )
680 10950 : pStm->SetAutoCommit( true );
681 11210 : pIo->MoveError( *pStm );
682 11210 : return pStm;
683 : }
684 :
685 : // Delete a stream or substorage by setting the temp bit.
686 :
687 28 : bool Storage::Remove( const OUString& rName )
688 : {
689 28 : if( !Validate( true ) )
690 0 : return false;
691 28 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
692 28 : if( p )
693 : {
694 28 : p->Invalidate( true );
695 28 : return true;
696 : }
697 : else
698 : {
699 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
700 0 : return false;
701 : }
702 : }
703 :
704 : // Rename a storage element
705 :
706 0 : bool Storage::Rename( const OUString& rOld, const OUString& rNew )
707 : {
708 0 : if( Validate( true ) )
709 : {
710 0 : bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
711 0 : pIo->MoveError( *this );
712 0 : return b;
713 : }
714 : else
715 0 : return false;
716 : }
717 :
718 : // Copy one element
719 :
720 1978 : bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
721 : {
722 1978 : if( !Validate() || !pDest || !pDest->Validate( true ) )
723 0 : return false;
724 1978 : StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
725 1978 : if( pElem )
726 : {
727 1978 : if( pElem->aEntry.GetType() == STG_STORAGE )
728 : {
729 : // copy the entire storage
730 62 : BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
731 62 : BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
732 :
733 62 : if ( p2 )
734 : {
735 62 : sal_uLong nTmpErr = p2->GetError();
736 62 : if( !nTmpErr )
737 : {
738 62 : p2->SetClassId( p1->GetClassId() );
739 62 : p1->CopyTo( p2 );
740 62 : SetError( p1->GetError() );
741 :
742 62 : nTmpErr = p2->GetError();
743 62 : if( !nTmpErr )
744 62 : p2->Commit();
745 : else
746 0 : pDest->SetError( nTmpErr );
747 : }
748 : else
749 0 : pDest->SetError( nTmpErr );
750 : }
751 :
752 62 : delete p1;
753 62 : delete p2;
754 62 : return Good() && pDest->Good();
755 : }
756 : else
757 : {
758 : // stream copy
759 1916 : BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
760 1916 : BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
761 :
762 1916 : if ( p2 )
763 : {
764 1916 : sal_uLong nTmpErr = p2->GetError();
765 1916 : if( !nTmpErr )
766 : {
767 1916 : p1->CopyTo( p2 );
768 1916 : SetError( p1->GetError() );
769 :
770 1916 : nTmpErr = p2->GetError();
771 1916 : if( !nTmpErr )
772 1916 : p2->Commit();
773 : else
774 0 : pDest->SetError( nTmpErr );
775 : }
776 : else
777 0 : pDest->SetError( nTmpErr );
778 : }
779 :
780 1916 : delete p1;
781 1916 : delete p2;
782 1916 : return Good() && pDest->Good();
783 : }
784 : }
785 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
786 0 : return false;
787 : }
788 :
789 222 : bool Storage::CopyTo( BaseStorage* pDest ) const
790 : {
791 222 : if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
792 : {
793 2 : SetError( SVSTREAM_ACCESS_DENIED );
794 2 : return false;
795 : }
796 220 : Storage* pThis = (Storage*) this;
797 220 : pDest->SetClassId( GetClassId() );
798 220 : pDest->SetDirty();
799 220 : SvStorageInfoList aList;
800 220 : FillInfoList( &aList );
801 220 : bool bRes = true;
802 2198 : for( size_t i = 0; i < aList.size() && bRes; i++ )
803 : {
804 1978 : SvStorageInfo& rInfo = aList[ i ];
805 1978 : bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
806 : }
807 220 : if( !bRes )
808 0 : SetError( pDest->GetError() );
809 220 : return Good() && pDest->Good();
810 : }
811 :
812 : // Move one element
813 :
814 0 : bool Storage::MoveTo( const OUString& rElem, BaseStorage* pODest, const OUString& rNew )
815 : {
816 0 : if( !Validate() || !pODest || !pODest->Validate( true ) || Equals( *pODest ) )
817 : {
818 0 : SetError( SVSTREAM_ACCESS_DENIED );
819 0 : return false;
820 : }
821 :
822 0 : StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
823 0 : if( pElem )
824 : {
825 : // Simplest case: both storages share the same file
826 : bool bRes;
827 0 : Storage *pOther = PTR_CAST( Storage, pODest );
828 0 : if( pOther && pIo == pOther->pIo && rElem == rNew )
829 : {
830 0 : Storage *p = static_cast<Storage*>(pODest);
831 0 : Storage *pDest = p;
832 : // both storages are conventional storages, use implementation dependent code
833 0 : if( !pElem->IsContained( pDest->pEntry ) )
834 : {
835 : // cyclic move
836 0 : SetError( SVSTREAM_ACCESS_DENIED );
837 0 : return false;
838 : }
839 0 : bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
840 0 : if( !bRes )
841 : {
842 0 : pIo->MoveError( *this );
843 0 : pDest->pIo->MoveError( *pDest );
844 0 : sal_uLong nErr = GetError();
845 0 : if( !nErr )
846 0 : nErr = pDest->GetError();
847 0 : SetError( nErr );
848 0 : pDest->SetError( nErr );
849 : }
850 : }
851 : else
852 : {
853 0 : bRes = CopyTo( rElem, pODest, rNew );
854 0 : if( bRes )
855 0 : bRes = Remove( rElem );
856 : }
857 0 : if( !bRes )
858 0 : SetError( pIo->GetError() );
859 0 : return bRes;
860 : }
861 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
862 0 : return false;
863 : }
864 :
865 3218 : bool Storage::IsStorage( const OUString& rName ) const
866 : {
867 3218 : if( Validate() )
868 : {
869 3218 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
870 3218 : if( p )
871 3218 : return p->aEntry.GetType() == STG_STORAGE;
872 : }
873 0 : return false;
874 : }
875 :
876 424 : bool Storage::IsStream( const OUString& rName ) const
877 : {
878 424 : if( Validate() )
879 : {
880 424 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
881 424 : if( p )
882 314 : return p->aEntry.GetType() == STG_STREAM;
883 : }
884 110 : return false;
885 : }
886 :
887 7032 : bool Storage::IsContained( const OUString& rName ) const
888 : {
889 7032 : if( Validate() )
890 7032 : return pIo->pTOC->Find( *pEntry, rName ) != NULL;
891 : else
892 0 : return false;
893 : }
894 :
895 : // Commit all sub-elements within this storage. If this is
896 : // the root, commit the FAT, the TOC and the header as well.
897 :
898 826 : bool Storage::Commit()
899 : {
900 826 : bool bRes = true;
901 826 : if( !Validate() )
902 0 : return false;
903 826 : if( !( m_nMode & STREAM_WRITE ) )
904 : {
905 0 : SetError( SVSTREAM_ACCESS_DENIED );
906 0 : return false;
907 : }
908 : else
909 : {
910 : // Also commit the sub-streams and Storages
911 826 : StgIterator aIter( *pEntry );
912 7456 : for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
913 6630 : bRes = p->Commit();
914 826 : if( bRes && bIsRoot )
915 : {
916 370 : bRes = pEntry->Commit();
917 370 : if( bRes )
918 370 : bRes = pIo->CommitAll();
919 : }
920 826 : pIo->MoveError( *this );
921 : }
922 826 : return bRes;
923 : }
924 :
925 0 : bool Storage::Revert()
926 : {
927 0 : return true;
928 : }
929 :
930 : ///////////////////////////// OLE Support
931 :
932 : // Set the storage type
933 :
934 62 : void Storage::SetClass( const SvGlobalName & rClass,
935 : sal_uLong nOriginalClipFormat,
936 : const OUString & rUserTypeName )
937 : {
938 62 : if( Validate( true ) )
939 : {
940 : // set the class name in the root entry
941 62 : pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
942 62 : pEntry->SetDirty();
943 : // then create the streams
944 62 : StgCompObjStream aCompObj( *this, true );
945 62 : aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
946 62 : aCompObj.GetCbFormat() = nOriginalClipFormat;
947 62 : aCompObj.GetUserName() = rUserTypeName;
948 62 : if( !aCompObj.Store() )
949 0 : SetError( aCompObj.GetError() );
950 : else
951 : {
952 62 : StgOleStream aOle(*this, true);
953 62 : if( !aOle.Store() )
954 0 : SetError( aOle.GetError() );
955 62 : }
956 : }
957 : else
958 0 : SetError( SVSTREAM_ACCESS_DENIED );
959 62 : }
960 :
961 0 : void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
962 : sal_uLong nOriginalClipFormat,
963 : const OUString & rUserTypeName )
964 : {
965 0 : if( Validate( true ) )
966 : {
967 0 : SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
968 : // plus the convert flag:
969 0 : StgOleStream aOle( *this, true );
970 0 : aOle.GetFlags() |= 4;
971 0 : if( !aOle.Store() )
972 0 : SetError( aOle.GetError() );
973 : }
974 0 : }
975 :
976 48 : SvGlobalName Storage::GetClassName()
977 : {
978 48 : StgCompObjStream aCompObj( *this, false );
979 48 : if( aCompObj.Load() )
980 48 : return SvGlobalName( aCompObj.GetClsId() );
981 0 : pIo->ResetError();
982 :
983 0 : if ( pEntry )
984 0 : return SvGlobalName( pEntry->aEntry.GetClassId() );
985 :
986 0 : return SvGlobalName();
987 : }
988 :
989 0 : sal_uLong Storage::GetFormat()
990 : {
991 0 : StgCompObjStream aCompObj( *this, false );
992 0 : if( aCompObj.Load() )
993 0 : return aCompObj.GetCbFormat();
994 0 : pIo->ResetError();
995 0 : return 0;
996 : }
997 :
998 0 : OUString Storage::GetUserName()
999 : {
1000 0 : StgCompObjStream aCompObj( *this, false );
1001 0 : if( aCompObj.Load() )
1002 0 : return aCompObj.GetUserName();
1003 0 : pIo->ResetError();
1004 0 : return OUString();
1005 : }
1006 :
1007 0 : bool Storage::ShouldConvert()
1008 : {
1009 0 : StgOleStream aOle( *this, false );
1010 0 : if( aOle.Load() )
1011 0 : return ( aOle.GetFlags() & 4 ) != 0;
1012 : else
1013 : {
1014 0 : pIo->ResetError();
1015 0 : return false;
1016 0 : }
1017 : }
1018 :
1019 8 : bool Storage::ValidateFAT()
1020 : {
1021 8 : Link aLink = StgIo::GetErrorLink();
1022 8 : ErrCode nErr = pIo->ValidateFATs();
1023 8 : StgIo::SetErrorLink( aLink );
1024 8 : return nErr == ERRCODE_NONE;
1025 : }
1026 :
1027 220 : void Storage::SetDirty()
1028 : {
1029 220 : if ( pEntry )
1030 220 : pEntry->SetDirty();
1031 220 : }
1032 :
1033 282 : void Storage::SetClassId( const ClsId& rId )
1034 : {
1035 282 : if ( pEntry )
1036 282 : pEntry->aEntry.SetClassId( rId );
1037 282 : }
1038 :
1039 282 : const ClsId& Storage::GetClassId() const
1040 : {
1041 282 : if ( pEntry )
1042 282 : return pEntry->aEntry.GetClassId();
1043 :
1044 : static ClsId aDummyId = {0,0,0,{0,0,0,0,0,0,0,0}};
1045 0 : return aDummyId;
1046 : }
1047 :
1048 0 : const SvStream* Storage::GetSvStream() const
1049 : {
1050 0 : return GetSvStream_Impl();
1051 : }
1052 :
1053 29982 : bool Storage::Validate( bool bValidate ) const
1054 : {
1055 29982 : bool bRet = Validate_Impl( bValidate );
1056 29982 : if ( !bRet )
1057 124 : SetError( SVSTREAM_ACCESS_DENIED );
1058 29982 : return bRet;
1059 : }
1060 :
1061 11778 : bool Storage::ValidateMode( StreamMode nMode ) const
1062 : {
1063 11778 : bool bRet = ValidateMode_Impl( nMode );
1064 11778 : if ( !bRet )
1065 0 : SetError( SVSTREAM_ACCESS_DENIED );
1066 11778 : return bRet;
1067 : }
1068 :
1069 7428 : bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1070 : {
1071 7428 : bool bRet = ValidateMode_Impl( nMode, p );
1072 7428 : if ( !bRet )
1073 0 : SetError( SVSTREAM_ACCESS_DENIED );
1074 7428 : return bRet;
1075 : }
1076 :
1077 220 : bool Storage::Equals( const BaseStorage& rStorage ) const
1078 : {
1079 220 : const Storage* pOther = PTR_CAST( Storage, &rStorage );
1080 220 : return pOther && ( pOther->pEntry == pEntry );
1081 : }
1082 :
1083 :
1084 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|