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