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