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 0 : TYPEINIT0( StorageBase );
47 0 : TYPEINIT1( BaseStorageStream, StorageBase );
48 0 : TYPEINIT1( BaseStorage, StorageBase );
49 :
50 0 : StorageBase::StorageBase()
51 0 : : m_bAutoCommit( false )
52 : {
53 0 : m_nMode = STREAM_READ;
54 0 : m_nError = SVSTREAM_OK;
55 0 : }
56 :
57 0 : StorageBase::~StorageBase()
58 : {
59 0 : }
60 :
61 : // The following three methods are declared as const, since they
62 : // may be called from within a const method.
63 :
64 0 : sal_uLong StorageBase::GetError() const
65 : {
66 0 : sal_uLong n = m_nError;
67 0 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
68 0 : return n;
69 : }
70 :
71 0 : void StorageBase::SetError( sal_uLong n ) const
72 : {
73 0 : if( !m_nError )
74 0 : ((StorageBase*) this)->m_nError = n;
75 0 : }
76 :
77 0 : void StorageBase::ResetError() const
78 : {
79 0 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
80 0 : }
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 0 : OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
90 0 : : nStreamMode( nMode ), pIo( p ), pEntry( pe )
91 : {
92 0 : if ( p )
93 0 : p->IncRef();
94 0 : if( pe )
95 0 : pe->nRefCnt++;
96 0 : }
97 :
98 0 : OLEStorageBase::~OLEStorageBase()
99 : {
100 0 : if( pEntry )
101 : {
102 : DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
103 0 : if( !--pEntry->nRefCnt )
104 : {
105 0 : if( pEntry->bZombie )
106 0 : delete pEntry;
107 : else
108 0 : pEntry->Close();
109 : }
110 :
111 0 : pEntry = NULL;
112 : }
113 :
114 :
115 0 : if( pIo && !pIo->DecRef() )
116 : {
117 0 : delete pIo;
118 0 : pIo = NULL;
119 : }
120 0 : }
121 :
122 : // Validate the instance for I/O
123 :
124 0 : bool OLEStorageBase::Validate_Impl( bool bWrite ) const
125 : {
126 0 : if( pIo
127 0 : && pIo->pTOC
128 0 : && pEntry
129 0 : && !pEntry->bInvalid
130 0 : && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
131 0 : return true;
132 0 : return false;
133 : }
134 :
135 0 : bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
136 : {
137 0 : if( m == INTERNAL_MODE )
138 0 : return true;
139 0 : sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
140 0 : if( ( m & 3 ) == STREAM_READ )
141 : {
142 : // only SHARE_DENYWRITE or SHARE_DENYALL allowed
143 0 : if( ( ( m & STREAM_SHARE_DENYWRITE )
144 0 : && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
145 0 : || ( ( m & STREAM_SHARE_DENYALL )
146 0 : && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
147 0 : 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 0 : if( ( m & STREAM_SHARE_DENYALL )
155 0 : && ( nCurMode & STREAM_SHARE_DENYALL ) )
156 0 : return true;
157 : }
158 0 : return false;
159 : }
160 :
161 :
162 : //////////////////////// class StorageStream
163 :
164 0 : TYPEINIT1( StorageStream, BaseStorageStream );
165 :
166 0 : StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
167 0 : : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
168 : {
169 : // The dir entry may be 0; this means that the stream is invalid.
170 0 : if( q && p )
171 : {
172 0 : if( q->nRefCnt == 1 )
173 : {
174 0 : q->nMode = m;
175 0 : q->OpenStream( *p );
176 : }
177 : }
178 : else
179 0 : m &= ~STREAM_READWRITE;
180 0 : m_nMode = m;
181 0 : }
182 :
183 0 : StorageStream::~StorageStream()
184 : {
185 : // Do an auto-commit if the entry is open in direct mode
186 0 : if( m_bAutoCommit )
187 0 : Commit();
188 0 : if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
189 0 : pEntry->Commit();
190 0 : }
191 :
192 0 : bool StorageStream::Equals( const BaseStorageStream& rStream ) const
193 : {
194 0 : const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
195 0 : return pOther && ( pOther->pEntry == pEntry );
196 : }
197 :
198 0 : sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
199 : {
200 0 : if( Validate() )
201 : {
202 0 : pEntry->Seek( nPos );
203 0 : nSize = pEntry->Read( pData, (sal_Int32) nSize );
204 0 : pIo->MoveError( *this );
205 0 : nPos += nSize;
206 : }
207 : else
208 0 : nSize = 0L;
209 0 : return nSize;
210 : }
211 :
212 0 : sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
213 : {
214 0 : if( Validate( true ) )
215 : {
216 0 : pEntry->Seek( nPos );
217 0 : nSize = pEntry->Write( pData, (sal_Int32) nSize );
218 0 : pIo->MoveError( *this );
219 0 : nPos += nSize;
220 : }
221 : else
222 0 : nSize = 0L;
223 0 : return nSize;
224 : }
225 :
226 0 : sal_uInt64 StorageStream::Seek( sal_uInt64 n )
227 : {
228 0 : if( Validate() )
229 0 : return nPos = pEntry->Seek( n );
230 : else
231 0 : return n;
232 : }
233 :
234 0 : void StorageStream::Flush()
235 : {
236 : // Flushing means committing, since streams are never transacted
237 0 : Commit();
238 0 : }
239 :
240 0 : bool StorageStream::SetSize( sal_uLong nNewSize )
241 : {
242 0 : if( Validate( true ) )
243 : {
244 0 : bool b = pEntry->SetSize( (sal_Int32) nNewSize );
245 0 : pIo->MoveError( *this );
246 0 : return b;
247 : }
248 : else
249 0 : return false;
250 : }
251 :
252 0 : sal_uLong StorageStream::GetSize() const
253 : {
254 0 : if( Validate() )
255 0 : return pEntry->GetSize();
256 0 : return 0;
257 : }
258 :
259 0 : bool StorageStream::Commit()
260 : {
261 0 : if( !Validate() )
262 0 : return false;
263 0 : if( !( m_nMode & STREAM_WRITE ) )
264 : {
265 0 : SetError( SVSTREAM_ACCESS_DENIED );
266 0 : return false;
267 : }
268 : else
269 : {
270 0 : pEntry->Commit();
271 0 : pIo->MoveError( *this );
272 0 : 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 0 : bool StorageStream::CopyTo( BaseStorageStream* pDest )
291 : {
292 0 : if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
293 0 : return false;
294 0 : pEntry->Copy( *pDest );
295 0 : pDest->Commit();
296 0 : pIo->MoveError( *this );
297 0 : SetError( pDest->GetError() );
298 0 : return Good() && pDest->Good();
299 : }
300 :
301 0 : const SvStream* StorageStream::GetSvStream() const
302 : {
303 0 : return GetSvStream_Impl();
304 : }
305 :
306 0 : bool StorageStream::Validate( bool bValidate ) const
307 : {
308 0 : bool bRet = Validate_Impl( bValidate );
309 0 : if ( !bRet )
310 0 : SetError( SVSTREAM_ACCESS_DENIED );
311 0 : 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 0 : SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
325 : {
326 0 : rE.aEntry.GetName( aName );
327 0 : bStorage = rE.aEntry.GetType() == STG_STORAGE;
328 0 : bStream = rE.aEntry.GetType() == STG_STREAM;
329 0 : nSize = bStorage ? 0 : rE.aEntry.GetSize();
330 0 : }
331 :
332 : /////////////////////////// class Storage
333 :
334 0 : bool Storage::IsStorageFile( const OUString & rFileName )
335 : {
336 0 : StgIo aIo;
337 0 : if( aIo.Open( rFileName, STREAM_STD_READ ) )
338 0 : return aIo.Load();
339 0 : return false;
340 : }
341 :
342 0 : bool Storage::IsStorageFile( SvStream* pStream )
343 : {
344 0 : bool bRet = false;
345 :
346 0 : if ( pStream )
347 : {
348 0 : StgHeader aHdr;
349 0 : sal_uLong nPos = pStream->Tell();
350 0 : 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 0 : if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
354 0 : pStream->ResetError();
355 0 : pStream->Seek( nPos );
356 : }
357 :
358 0 : 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 0 : 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 0 : Storage::Storage( SvStream& r, bool bDirect )
399 0 : : OLEStorageBase( new StgIo, NULL, m_nMode )
400 0 : , bIsRoot( false )
401 : {
402 0 : m_nMode = STREAM_READ;
403 0 : if( r.IsWritable() )
404 0 : m_nMode = STREAM_READ | STREAM_WRITE;
405 0 : if( r.GetError() == SVSTREAM_OK )
406 : {
407 0 : pIo->SetStrm( &r, false );
408 0 : sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
409 0 : r.Seek( 0L );
410 : // Initializing is OK if the stream is empty
411 0 : Init( nSize == 0 );
412 0 : if( pEntry )
413 : {
414 0 : pEntry->bDirect = bDirect;
415 0 : pEntry->nMode = m_nMode;
416 : }
417 0 : pIo->MoveError( *this );
418 : }
419 : else
420 : {
421 0 : SetError( r.GetError() );
422 0 : pEntry = NULL;
423 : }
424 0 : }
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 0 : void Storage::Init( bool bCreate )
470 : {
471 0 : pEntry = NULL;
472 0 : bool bHdrLoaded = false;
473 0 : bIsRoot = true;
474 :
475 : OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
476 0 : if( pIo->Good() && pIo->GetStrm() )
477 : {
478 0 : sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
479 0 : pIo->GetStrm()->Seek( 0L );
480 0 : if( nSize )
481 : {
482 0 : bHdrLoaded = pIo->Load();
483 0 : if( !bHdrLoaded && !bCreate )
484 : {
485 : // File is not a storage and not empty; do not destroy!
486 0 : SetError( SVSTREAM_FILEFORMAT_ERROR );
487 0 : return;
488 : }
489 : }
490 : }
491 : // file is a storage, empty or should be overwritten
492 0 : pIo->ResetError();
493 : // we have to set up the data structures, since
494 : // the file is empty
495 0 : if( !bHdrLoaded )
496 0 : pIo->Init();
497 0 : if( pIo->Good() && pIo->pTOC )
498 : {
499 0 : pEntry = pIo->pTOC->GetRoot();
500 0 : pEntry->nRefCnt++;
501 : }
502 : }
503 :
504 : // Internal ctor
505 :
506 0 : Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
507 0 : : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
508 : {
509 0 : if( q )
510 0 : q->aEntry.GetName( aName );
511 : else
512 0 : m &= ~STREAM_READWRITE;
513 0 : m_nMode = m;
514 0 : if( q && q->nRefCnt == 1 )
515 0 : q->nMode = m;
516 0 : }
517 :
518 0 : Storage::~Storage()
519 : {
520 : // Invalidate all open substorages
521 0 : if( m_bAutoCommit )
522 0 : Commit();
523 0 : if( pEntry )
524 : {
525 : // Do an auto-commit if the entry is open in direct mode
526 0 : if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
527 0 : Commit();
528 0 : if( pEntry->nRefCnt == 1 )
529 0 : pEntry->Invalidate();
530 : }
531 : // close the stream is root storage
532 0 : if( bIsRoot )
533 0 : pIo->Close();
534 : // remove the file if temporary root storage
535 0 : if( bIsRoot && pEntry && pEntry->bTemp )
536 : {
537 0 : osl::File::remove( GetName() );
538 : }
539 0 : }
540 :
541 0 : const OUString& Storage::GetName() const
542 : {
543 0 : if( !bIsRoot && Validate() )
544 0 : pEntry->aEntry.GetName( ((Storage*) this)->aName );
545 0 : return aName;
546 : }
547 :
548 : // Fill in the info list for this storage
549 :
550 0 : void Storage::FillInfoList( SvStorageInfoList* pList ) const
551 : {
552 0 : if( Validate() && pList )
553 : {
554 0 : StgIterator aIter( *pEntry );
555 0 : StgDirEntry* p = aIter.First();
556 0 : while( p )
557 : {
558 0 : if( !p->bInvalid )
559 : {
560 0 : SvStorageInfo aInfo( *p );
561 0 : pList->push_back( aInfo );
562 : }
563 0 : p = aIter.Next();
564 : }
565 : }
566 0 : }
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 0 : BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
577 : {
578 0 : return OpenStorage( rName, m, bDirect );
579 : }
580 :
581 0 : BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
582 : {
583 0 : if( !Validate() || !ValidateMode( m ) )
584 0 : return new Storage( pIo, NULL, m );
585 0 : if( bDirect && !pEntry->bDirect )
586 0 : bDirect = false;
587 :
588 0 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
589 0 : if( !p )
590 : {
591 0 : if( !( m & STREAM_NOCREATE ) )
592 : {
593 0 : bool bTemp = false;
594 : // create a new storage
595 0 : OUString aNewName = rName;
596 0 : if( aNewName.isEmpty() )
597 : {
598 0 : aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
599 0 : bTemp = true;
600 : }
601 0 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
602 0 : if( p )
603 0 : p->bTemp = bTemp;
604 : }
605 0 : if( !p )
606 0 : pIo->SetError( ( m & STREAM_WRITE )
607 0 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
608 : }
609 0 : else if( !ValidateMode( m, p ) )
610 0 : p = NULL;
611 0 : 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 0 : if( p && pEntry->nRefCnt == 1 )
619 0 : p->bDirect = bDirect;
620 :
621 : // Dont check direct conflict if opening readonly
622 0 : if( p && (m & STREAM_WRITE ))
623 : {
624 0 : if( p->bDirect != bDirect )
625 0 : SetError( SVSTREAM_ACCESS_DENIED );
626 : }
627 0 : Storage* pStg = new Storage( pIo, p, m );
628 0 : pIo->MoveError( *pStg );
629 0 : if( m & STREAM_WRITE ) pStg->m_bAutoCommit = true;
630 0 : return pStg;
631 : }
632 :
633 : // Open a stream
634 :
635 0 : 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 0 : if( !Validate() || !ValidateMode( m ) )
645 0 : return new StorageStream( pIo, NULL, m );
646 0 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
647 0 : bool bTemp = false;
648 0 : if( !p )
649 : {
650 0 : if( !( m & STREAM_NOCREATE ) )
651 : {
652 : // create a new stream
653 : // make a name if the stream is temporary (has no name)
654 0 : OUString aNewName( rName );
655 0 : if( aNewName.isEmpty() )
656 : {
657 0 : aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
658 0 : bTemp = true;
659 : }
660 0 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
661 : }
662 0 : if( !p )
663 0 : pIo->SetError( ( m & STREAM_WRITE )
664 0 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
665 : }
666 0 : else if( !ValidateMode( m, p ) )
667 0 : p = NULL;
668 0 : if( p && p->aEntry.GetType() != STG_STREAM )
669 : {
670 0 : pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
671 0 : p = NULL;
672 : }
673 0 : if( p )
674 : {
675 0 : p->bTemp = bTemp;
676 0 : p->bDirect = pEntry->bDirect;
677 : }
678 0 : StorageStream* pStm = new StorageStream( pIo, p, m );
679 0 : if( p && !p->bDirect )
680 0 : pStm->SetAutoCommit( true );
681 0 : pIo->MoveError( *pStm );
682 0 : return pStm;
683 : }
684 :
685 : // Delete a stream or substorage by setting the temp bit.
686 :
687 0 : bool Storage::Remove( const OUString& rName )
688 : {
689 0 : if( !Validate( true ) )
690 0 : return false;
691 0 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
692 0 : if( p )
693 : {
694 0 : p->Invalidate( true );
695 0 : 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 0 : bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
721 : {
722 0 : if( !Validate() || !pDest || !pDest->Validate( true ) )
723 0 : return false;
724 0 : StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
725 0 : if( pElem )
726 : {
727 0 : if( pElem->aEntry.GetType() == STG_STORAGE )
728 : {
729 : // copy the entire storage
730 0 : BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
731 0 : BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
732 :
733 0 : if ( p2 )
734 : {
735 0 : sal_uLong nTmpErr = p2->GetError();
736 0 : if( !nTmpErr )
737 : {
738 0 : p2->SetClassId( p1->GetClassId() );
739 0 : p1->CopyTo( p2 );
740 0 : SetError( p1->GetError() );
741 :
742 0 : nTmpErr = p2->GetError();
743 0 : if( !nTmpErr )
744 0 : p2->Commit();
745 : else
746 0 : pDest->SetError( nTmpErr );
747 : }
748 : else
749 0 : pDest->SetError( nTmpErr );
750 : }
751 :
752 0 : delete p1;
753 0 : delete p2;
754 0 : return Good() && pDest->Good();
755 : }
756 : else
757 : {
758 : // stream copy
759 0 : BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
760 0 : BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
761 :
762 0 : if ( p2 )
763 : {
764 0 : sal_uLong nTmpErr = p2->GetError();
765 0 : if( !nTmpErr )
766 : {
767 0 : p1->CopyTo( p2 );
768 0 : SetError( p1->GetError() );
769 :
770 0 : nTmpErr = p2->GetError();
771 0 : if( !nTmpErr )
772 0 : p2->Commit();
773 : else
774 0 : pDest->SetError( nTmpErr );
775 : }
776 : else
777 0 : pDest->SetError( nTmpErr );
778 : }
779 :
780 0 : delete p1;
781 0 : delete p2;
782 0 : return Good() && pDest->Good();
783 : }
784 : }
785 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
786 0 : return false;
787 : }
788 :
789 0 : bool Storage::CopyTo( BaseStorage* pDest ) const
790 : {
791 0 : if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
792 : {
793 0 : SetError( SVSTREAM_ACCESS_DENIED );
794 0 : return false;
795 : }
796 0 : Storage* pThis = (Storage*) this;
797 0 : pDest->SetClassId( GetClassId() );
798 0 : pDest->SetDirty();
799 0 : SvStorageInfoList aList;
800 0 : FillInfoList( &aList );
801 0 : bool bRes = true;
802 0 : for( size_t i = 0; i < aList.size() && bRes; i++ )
803 : {
804 0 : SvStorageInfo& rInfo = aList[ i ];
805 0 : bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
806 : }
807 0 : if( !bRes )
808 0 : SetError( pDest->GetError() );
809 0 : 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 = (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 0 : bool Storage::IsStorage( const OUString& rName ) const
866 : {
867 0 : if( Validate() )
868 : {
869 0 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
870 0 : if( p )
871 0 : return p->aEntry.GetType() == STG_STORAGE;
872 : }
873 0 : return false;
874 : }
875 :
876 0 : bool Storage::IsStream( const OUString& rName ) const
877 : {
878 0 : if( Validate() )
879 : {
880 0 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
881 0 : if( p )
882 0 : return p->aEntry.GetType() == STG_STREAM;
883 : }
884 0 : return false;
885 : }
886 :
887 0 : bool Storage::IsContained( const OUString& rName ) const
888 : {
889 0 : if( Validate() )
890 0 : 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 0 : bool Storage::Commit()
899 : {
900 0 : bool bRes = true;
901 0 : if( !Validate() )
902 0 : return false;
903 0 : 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 0 : StgIterator aIter( *pEntry );
912 0 : for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
913 0 : bRes = p->Commit();
914 0 : if( bRes && bIsRoot )
915 : {
916 0 : bRes = pEntry->Commit();
917 0 : if( bRes )
918 0 : bRes = pIo->CommitAll();
919 : }
920 0 : pIo->MoveError( *this );
921 : }
922 0 : 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 0 : void Storage::SetClass( const SvGlobalName & rClass,
935 : sal_uLong nOriginalClipFormat,
936 : const OUString & rUserTypeName )
937 : {
938 0 : if( Validate( true ) )
939 : {
940 : // set the class name in the root entry
941 0 : pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
942 0 : pEntry->SetDirty();
943 : // then create the streams
944 0 : StgCompObjStream aCompObj( *this, true );
945 0 : aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
946 0 : aCompObj.GetCbFormat() = nOriginalClipFormat;
947 0 : aCompObj.GetUserName() = rUserTypeName;
948 0 : if( !aCompObj.Store() )
949 0 : SetError( aCompObj.GetError() );
950 : else
951 : {
952 0 : StgOleStream aOle(*this, true);
953 0 : if( !aOle.Store() )
954 0 : SetError( aOle.GetError() );
955 0 : }
956 : }
957 : else
958 0 : SetError( SVSTREAM_ACCESS_DENIED );
959 0 : }
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 0 : SvGlobalName Storage::GetClassName()
977 : {
978 0 : StgCompObjStream aCompObj( *this, false );
979 0 : if( aCompObj.Load() )
980 0 : return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
981 0 : pIo->ResetError();
982 :
983 0 : if ( pEntry )
984 0 : return SvGlobalName( (const CLSID&) 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 0 : bool Storage::ValidateFAT()
1020 : {
1021 0 : Link aLink = StgIo::GetErrorLink();
1022 0 : ErrCode nErr = pIo->ValidateFATs();
1023 0 : StgIo::SetErrorLink( aLink );
1024 0 : return nErr == ERRCODE_NONE;
1025 : }
1026 :
1027 0 : void Storage::SetDirty()
1028 : {
1029 0 : if ( pEntry )
1030 0 : pEntry->SetDirty();
1031 0 : }
1032 :
1033 0 : void Storage::SetClassId( const ClsId& rId )
1034 : {
1035 0 : if ( pEntry )
1036 0 : pEntry->aEntry.SetClassId( rId );
1037 0 : }
1038 :
1039 0 : const ClsId& Storage::GetClassId() const
1040 : {
1041 0 : if ( pEntry )
1042 0 : 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 0 : bool Storage::Validate( bool bValidate ) const
1054 : {
1055 0 : bool bRet = Validate_Impl( bValidate );
1056 0 : if ( !bRet )
1057 0 : SetError( SVSTREAM_ACCESS_DENIED );
1058 0 : return bRet;
1059 : }
1060 :
1061 0 : bool Storage::ValidateMode( StreamMode nMode ) const
1062 : {
1063 0 : bool bRet = ValidateMode_Impl( nMode );
1064 0 : if ( !bRet )
1065 0 : SetError( SVSTREAM_ACCESS_DENIED );
1066 0 : return bRet;
1067 : }
1068 :
1069 0 : bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1070 : {
1071 0 : bool bRet = ValidateMode_Impl( nMode, p );
1072 0 : if ( !bRet )
1073 0 : SetError( SVSTREAM_ACCESS_DENIED );
1074 0 : return bRet;
1075 : }
1076 :
1077 0 : bool Storage::Equals( const BaseStorage& rStorage ) const
1078 : {
1079 0 : const Storage* pOther = PTR_CAST( Storage, &rStorage );
1080 0 : return pOther && ( pOther->pEntry == pEntry );
1081 : }
1082 :
1083 :
1084 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|