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