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