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 : #include <config_features.h>
21 :
22 : #include <sfx2/docfile.hxx>
23 : #include <sfx2/signaturestate.hxx>
24 :
25 : #include <uno/mapping.hxx>
26 : #include <com/sun/star/task/InteractionHandler.hpp>
27 : #include <com/sun/star/uno/Reference.h>
28 : #include <com/sun/star/ucb/XContent.hpp>
29 : #include <com/sun/star/container/XChild.hpp>
30 : #include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
31 : #include <com/sun/star/document/LockedDocumentRequest.hpp>
32 : #include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
33 : #include <com/sun/star/document/LockFileIgnoreRequest.hpp>
34 : #include <com/sun/star/document/ChangedByOthersRequest.hpp>
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 : #include <com/sun/star/embed/XTransactedObject.hpp>
37 : #include <com/sun/star/embed/ElementModes.hpp>
38 : #include <com/sun/star/embed/UseBackupException.hpp>
39 : #include <com/sun/star/embed/XOptimizedStorage.hpp>
40 : #include <com/sun/star/ucb/InteractiveIOException.hpp>
41 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
42 : #include <com/sun/star/ucb/CommandFailedException.hpp>
43 : #include <com/sun/star/ucb/CommandAbortedException.hpp>
44 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
45 : #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
46 : #include <com/sun/star/ucb/XContentProvider.hpp>
47 : #include <com/sun/star/ucb/XProgressHandler.hpp>
48 : #include <com/sun/star/ucb/XCommandInfo.hpp>
49 : #include <com/sun/star/io/XOutputStream.hpp>
50 : #include <com/sun/star/io/XInputStream.hpp>
51 : #include <com/sun/star/io/XTruncate.hpp>
52 : #include <com/sun/star/io/XStreamListener.hpp>
53 : #include <com/sun/star/io/XSeekable.hpp>
54 : #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
55 : #include <com/sun/star/lang/XInitialization.hpp>
56 : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
57 : #include <com/sun/star/ucb/NameClash.hpp>
58 : #include <com/sun/star/ucb/TransferInfo.hpp>
59 : #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
60 : #include <com/sun/star/ucb/OpenMode.hpp>
61 : #include <com/sun/star/logging/DocumentIOLogRing.hpp>
62 : #include <com/sun/star/logging/XSimpleLogRing.hpp>
63 : #include <cppuhelper/implbase1.hxx>
64 : #include <com/sun/star/beans/PropertyValue.hpp>
65 : #include <com/sun/star/security/DocumentSignatureInformation.hpp>
66 : #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
67 : #include <tools/urlobj.hxx>
68 : #include <unotools/tempfile.hxx>
69 : #include <comphelper/processfactory.hxx>
70 : #include <comphelper/interaction.hxx>
71 : #include <framework/interaction.hxx>
72 : #include <unotools/streamhelper.hxx>
73 : #include <unotools/localedatawrapper.hxx>
74 : #include <vcl/msgbox.hxx>
75 : #include <svl/stritem.hxx>
76 : #include <svl/eitem.hxx>
77 : #include <svl/lckbitem.hxx>
78 : #include <svtools/sfxecode.hxx>
79 : #include <svl/itemset.hxx>
80 : #include <svl/intitem.hxx>
81 : #include <svtools/svparser.hxx>
82 : #include <cppuhelper/weakref.hxx>
83 :
84 : #include <unotools/streamwrap.hxx>
85 :
86 : #include <osl/file.hxx>
87 :
88 : #include <comphelper/storagehelper.hxx>
89 : #include <unotools/mediadescriptor.hxx>
90 : #include <comphelper/docpasswordhelper.hxx>
91 : #include <tools/datetime.hxx>
92 : #include <tools/inetmime.hxx>
93 : #include <unotools/pathoptions.hxx>
94 : #include <svtools/asynclink.hxx>
95 : #include <svl/inettype.hxx>
96 : #include <ucbhelper/commandenvironment.hxx>
97 : #include <unotools/localfilehelper.hxx>
98 : #include <unotools/ucbstreamhelper.hxx>
99 : #include <unotools/ucbhelper.hxx>
100 : #include <unotools/progresshandlerwrap.hxx>
101 : #include <ucbhelper/content.hxx>
102 : #include <ucbhelper/interactionrequest.hxx>
103 : #include <sot/stg.hxx>
104 : #include <sot/storage.hxx>
105 : #include <unotools/saveopt.hxx>
106 : #include <svl/documentlockfile.hxx>
107 : #include <com/sun/star/document/DocumentRevisionListPersistence.hpp>
108 :
109 : #include "helper.hxx"
110 : #include <sfx2/request.hxx>
111 : #include <sfx2/app.hxx>
112 : #include <sfx2/frame.hxx>
113 : #include <sfx2/fcontnr.hxx>
114 : #include <sfx2/docfilt.hxx>
115 : #include <sfx2/objsh.hxx>
116 : #include <sfx2/docfac.hxx>
117 : #include "doc.hrc"
118 : #include "openflag.hxx"
119 : #include <sfx2/sfxresid.hxx>
120 : #include "sfxacldetect.hxx"
121 : #include <officecfg/Office/Common.hxx>
122 :
123 : #include <boost/noncopyable.hpp>
124 : #include <boost/scoped_ptr.hpp>
125 :
126 : using namespace ::com::sun::star;
127 : using namespace ::com::sun::star::uno;
128 : using namespace ::com::sun::star::ucb;
129 : using namespace ::com::sun::star::beans;
130 : using namespace ::com::sun::star::io;
131 :
132 : namespace {
133 :
134 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
135 :
136 : static const sal_Int8 LOCK_UI_NOLOCK = 0;
137 : static const sal_Int8 LOCK_UI_SUCCEEDED = 1;
138 : static const sal_Int8 LOCK_UI_TRY = 2;
139 :
140 32 : bool IsSystemFileLockingUsed()
141 : {
142 : #if HAVE_FEATURE_MACOSX_SANDBOX
143 : return true;
144 : #else
145 32 : return officecfg::Office::Common::Misc::UseDocumentSystemFileLocking::get();
146 : #endif
147 : }
148 :
149 :
150 0 : bool IsOOoLockFileUsed()
151 : {
152 : #if HAVE_FEATURE_MACOSX_SANDBOX
153 : return false;
154 : #else
155 0 : return officecfg::Office::Common::Misc::UseDocumentOOoLockFile::get();
156 : #endif
157 : }
158 :
159 5666 : bool IsLockingUsed()
160 : {
161 5666 : return officecfg::Office::Common::Misc::UseLocking::get();
162 : }
163 :
164 : #endif
165 :
166 : } // anonymous namespace
167 :
168 : class SfxMedium_Impl : boost::noncopyable
169 : {
170 : public:
171 : StreamMode m_nStorOpenMode;
172 : sal_uInt32 m_eError;
173 :
174 : ::ucbhelper::Content aContent;
175 : bool bUpdatePickList:1;
176 : bool bIsTemp:1;
177 : bool bDownloadDone:1;
178 : bool bIsStorage:1;
179 : bool bUseInteractionHandler:1;
180 : bool bAllowDefaultIntHdl:1;
181 : bool bDisposeStorage:1;
182 : bool bStorageBasedOnInStream:1;
183 : bool m_bSalvageMode:1;
184 : bool m_bVersionsAlreadyLoaded:1;
185 : bool m_bLocked:1;
186 : bool m_bGotDateTime:1;
187 : bool m_bRemoveBackup:1;
188 : bool m_bOriginallyReadOnly:1;
189 : bool m_bTriedStorage:1;
190 : bool m_bRemote:1;
191 : bool m_bInputStreamIsReadOnly:1;
192 : bool m_bInCheckIn:1;
193 :
194 : OUString m_aName;
195 : OUString m_aLogicName;
196 : OUString m_aLongName;
197 :
198 : mutable SfxItemSet* m_pSet;
199 : mutable INetURLObject* m_pURLObj;
200 :
201 : const SfxFilter* m_pFilter;
202 : boost::scoped_ptr<SfxFilter> m_pCustomFilter;
203 :
204 : SfxMedium* pAntiImpl;
205 : SvStream* m_pInStream;
206 : SvStream* m_pOutStream;
207 :
208 : const SfxFilter* pOrigFilter;
209 : OUString aOrigURL;
210 : DateTime aExpireTime;
211 : SfxFrameWeakRef wLoadTargetFrame;
212 : SvKeyValueIteratorRef xAttributes;
213 :
214 : svtools::AsynchronLink aDoneLink;
215 :
216 : uno::Sequence < util::RevisionTag > aVersions;
217 :
218 : ::utl::TempFile* pTempFile;
219 :
220 : uno::Reference<embed::XStorage> xStorage;
221 : uno::Reference<embed::XStorage> m_xZipStorage;
222 : uno::Reference<io::XInputStream> m_xInputStreamToLoadFrom;
223 : uno::Reference<io::XInputStream> xInputStream;
224 : uno::Reference<io::XStream> xStream;
225 : uno::Reference<io::XStream> m_xLockingStream;
226 : uno::Reference<task::XInteractionHandler> xInteraction;
227 : uno::Reference<logging::XSimpleLogRing> m_xLogRing;
228 :
229 : sal_uInt32 nLastStorageError;
230 :
231 : OUString m_aBackupURL;
232 :
233 : // the following member is changed and makes sense only during saving
234 : // TODO/LATER: in future the signature state should be controlled by the medium not by the document
235 : // in this case the member will hold this information
236 : SignatureState m_nSignatureState;
237 :
238 : util::DateTime m_aDateTime;
239 :
240 : SfxMedium_Impl( SfxMedium* pAntiImplP );
241 : ~SfxMedium_Impl();
242 :
243 3552 : OUString getFilterMimeType()
244 3552 : { return m_pFilter == 0 ? OUString() : m_pFilter->GetMimeType(); }
245 : };
246 :
247 :
248 12371 : SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP ) :
249 24742 : m_nStorOpenMode(SFX_STREAM_READWRITE),
250 : m_eError(SVSTREAM_OK),
251 : bUpdatePickList(true),
252 : bIsTemp( false ),
253 : bDownloadDone( true ),
254 : bIsStorage( false ),
255 : bUseInteractionHandler( true ),
256 : bAllowDefaultIntHdl( false ),
257 : bDisposeStorage( false ),
258 : bStorageBasedOnInStream( false ),
259 : m_bSalvageMode( false ),
260 : m_bVersionsAlreadyLoaded( false ),
261 : m_bLocked( false ),
262 : m_bGotDateTime( false ),
263 : m_bRemoveBackup( false ),
264 : m_bOriginallyReadOnly(false),
265 : m_bTriedStorage(false),
266 : m_bRemote(false),
267 : m_bInputStreamIsReadOnly(false),
268 : m_bInCheckIn(false),
269 : m_pSet(NULL),
270 : m_pURLObj(NULL),
271 : m_pFilter(NULL),
272 : pAntiImpl( pAntiImplP ),
273 : m_pInStream(NULL),
274 : m_pOutStream(NULL),
275 : pOrigFilter( 0 ),
276 24742 : aExpireTime( Date( Date::SYSTEM ) + 10, tools::Time( tools::Time::SYSTEM ) ),
277 : pTempFile( NULL ),
278 : nLastStorageError( 0 ),
279 61855 : m_nSignatureState( SignatureState::NOSIGNATURES )
280 : {
281 12371 : aDoneLink.CreateMutex();
282 12371 : }
283 :
284 :
285 24704 : SfxMedium_Impl::~SfxMedium_Impl()
286 : {
287 12352 : aDoneLink.ClearPendingCall();
288 :
289 12352 : delete pTempFile;
290 12352 : delete m_pSet;
291 12352 : delete m_pURLObj;
292 12352 : }
293 :
294 4759 : void SfxMedium::ResetError()
295 : {
296 4759 : pImp->m_eError = SVSTREAM_OK;
297 4759 : if( pImp->m_pInStream )
298 3155 : pImp->m_pInStream->ResetError();
299 4759 : if( pImp->m_pOutStream )
300 0 : pImp->m_pOutStream->ResetError();
301 4759 : }
302 :
303 :
304 497 : sal_uInt32 SfxMedium::GetLastStorageCreationState()
305 : {
306 497 : return pImp->nLastStorageError;
307 : }
308 :
309 :
310 373 : void SfxMedium::AddLog( const OUString& aMessage )
311 : {
312 373 : if ( !pImp->m_xLogRing.is() )
313 : {
314 : try
315 : {
316 373 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
317 373 : pImp->m_xLogRing.set( logging::DocumentIOLogRing::get(xContext) );
318 : }
319 5 : catch( const uno::Exception& )
320 : {}
321 : }
322 :
323 373 : if ( pImp->m_xLogRing.is() )
324 368 : pImp->m_xLogRing->logString( aMessage );
325 373 : }
326 :
327 :
328 373 : void SfxMedium::SetError( sal_uInt32 nError, const OUString& aLogMessage )
329 : {
330 373 : pImp->m_eError = nError;
331 373 : if ( pImp->m_eError != ERRCODE_NONE && !aLogMessage.isEmpty() )
332 373 : AddLog( aLogMessage );
333 373 : }
334 :
335 :
336 76914 : sal_uInt32 SfxMedium::GetErrorCode() const
337 : {
338 76914 : sal_uInt32 lError = pImp->m_eError;
339 76914 : if(!lError && pImp->m_pInStream)
340 38127 : lError = pImp->m_pInStream->GetErrorCode();
341 76914 : if(!lError && pImp->m_pOutStream)
342 687 : lError = pImp->m_pOutStream->GetErrorCode();
343 76914 : return lError;
344 : }
345 :
346 :
347 2 : void SfxMedium::CheckFileDate( const util::DateTime& aInitDate )
348 : {
349 2 : GetInitFileDate( true );
350 2 : if ( pImp->m_aDateTime.Seconds != aInitDate.Seconds
351 2 : || pImp->m_aDateTime.Minutes != aInitDate.Minutes
352 2 : || pImp->m_aDateTime.Hours != aInitDate.Hours
353 2 : || pImp->m_aDateTime.Day != aInitDate.Day
354 2 : || pImp->m_aDateTime.Month != aInitDate.Month
355 2 : || pImp->m_aDateTime.Year != aInitDate.Year )
356 : {
357 0 : uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
358 :
359 0 : if ( xHandler.is() )
360 : {
361 : try
362 : {
363 : ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
364 0 : document::ChangedByOthersRequest() ) );
365 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
366 0 : aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
367 0 : aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
368 0 : xInteractionRequestImpl->setContinuations( aContinuations );
369 :
370 0 : xHandler->handle( xInteractionRequestImpl.get() );
371 :
372 0 : ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
373 0 : if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
374 : {
375 0 : SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
376 0 : }
377 : }
378 0 : catch ( const uno::Exception& )
379 : {}
380 0 : }
381 : }
382 2 : }
383 :
384 1491 : bool SfxMedium::DocNeedsFileDateCheck() const
385 : {
386 1491 : return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
387 : }
388 :
389 921 : util::DateTime SfxMedium::GetInitFileDate( bool bIgnoreOldValue )
390 : {
391 921 : if ( ( bIgnoreOldValue || !pImp->m_bGotDateTime ) && !pImp->m_aLogicName.isEmpty() )
392 : {
393 : try
394 : {
395 920 : uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
396 1840 : ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, comphelper::getProcessComponentContext() );
397 :
398 920 : aContent.getPropertyValue("DateModified") >>= pImp->m_aDateTime;
399 1829 : pImp->m_bGotDateTime = true;
400 : }
401 11 : catch ( const ::com::sun::star::uno::Exception& )
402 : {
403 : }
404 : }
405 :
406 921 : return pImp->m_aDateTime;
407 : }
408 :
409 :
410 36636 : Reference < XContent > SfxMedium::GetContent() const
411 : {
412 36636 : if ( !pImp->aContent.get().is() )
413 : {
414 15256 : Reference < ::com::sun::star::ucb::XContent > xContent;
415 30512 : Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
416 :
417 15256 : SFX_ITEMSET_ARG( pImp->m_pSet, pItem, SfxUnoAnyItem, SID_CONTENT, false);
418 15256 : if ( pItem )
419 2517 : pItem->GetValue() >>= xContent;
420 :
421 15256 : if ( xContent.is() )
422 : {
423 : try
424 : {
425 2517 : pImp->aContent = ::ucbhelper::Content( xContent, xEnv, comphelper::getProcessComponentContext() );
426 : }
427 0 : catch ( const Exception& )
428 : {
429 : }
430 : }
431 : else
432 : {
433 : // TODO: SAL_WARN( "sfx.doc", "SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
434 12739 : OUString aURL;
435 12739 : if ( !pImp->m_aName.isEmpty() )
436 7425 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->m_aName, aURL );
437 5314 : else if ( !pImp->m_aLogicName.isEmpty() )
438 33 : aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
439 12739 : if (!aURL.isEmpty() )
440 7458 : (void)::ucbhelper::Content::create( aURL, xEnv, comphelper::getProcessComponentContext(), pImp->aContent );
441 15256 : }
442 : }
443 :
444 36636 : return pImp->aContent.get();
445 : }
446 :
447 5674 : OUString SfxMedium::GetBaseURL( bool bForSaving )
448 : {
449 5674 : OUString aBaseURL;
450 5674 : const SfxStringItem* pBaseURLItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_DOC_BASEURL) );
451 5674 : if ( pBaseURLItem )
452 1592 : aBaseURL = pBaseURLItem->GetValue();
453 4082 : else if ( GetContent().is() )
454 : {
455 : try
456 : {
457 3789 : Any aAny = pImp->aContent.getPropertyValue("BaseURI");
458 3785 : aAny >>= aBaseURL;
459 : }
460 2 : catch ( const ::com::sun::star::uno::Exception& )
461 : {
462 : }
463 :
464 3787 : if ( aBaseURL.isEmpty() )
465 3787 : aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
466 : }
467 :
468 5674 : if ( bForSaving )
469 : {
470 1458 : SvtSaveOptions aOpt;
471 1458 : bool bIsRemote = IsRemote();
472 1458 : if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!pImp->m_bRemote && !aOpt.IsSaveRelFSys()) )
473 0 : return OUString();
474 : }
475 :
476 5674 : return aBaseURL;
477 : }
478 :
479 487 : bool SfxMedium::IsSkipImages()
480 : {
481 487 : const SfxStringItem* pSkipImagesItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_FILE_FILTEROPTIONS) );
482 487 : return pSkipImagesItem && pSkipImagesItem->GetValue() == "SkipImages";
483 : }
484 :
485 9423 : SvStream* SfxMedium::GetInStream()
486 : {
487 9423 : if ( pImp->m_pInStream )
488 1095 : return pImp->m_pInStream;
489 :
490 8328 : if ( pImp->pTempFile )
491 : {
492 1 : pImp->m_pInStream = new SvFileStream(pImp->m_aName, pImp->m_nStorOpenMode);
493 :
494 1 : pImp->m_eError = pImp->m_pInStream->GetError();
495 :
496 3 : if (!pImp->m_eError && (pImp->m_nStorOpenMode & StreamMode::WRITE)
497 3 : && ! pImp->m_pInStream->IsWritable() )
498 : {
499 0 : pImp->m_eError = ERRCODE_IO_ACCESSDENIED;
500 0 : delete pImp->m_pInStream;
501 0 : pImp->m_pInStream = NULL;
502 : }
503 : else
504 1 : return pImp->m_pInStream;
505 : }
506 :
507 8327 : GetMedium_Impl();
508 :
509 8327 : if ( GetError() )
510 364 : return NULL;
511 :
512 7963 : return pImp->m_pInStream;
513 : }
514 :
515 :
516 10710 : void SfxMedium::CloseInStream()
517 : {
518 10710 : CloseInStream_Impl();
519 10710 : }
520 :
521 29047 : void SfxMedium::CloseInStream_Impl()
522 : {
523 : // if there is a storage based on the InStream, we have to
524 : // close the storage, too, because otherwise the storage
525 : // would use an invalid ( deleted ) stream.
526 29047 : if ( pImp->m_pInStream && pImp->xStorage.is() )
527 : {
528 2180 : if ( pImp->bStorageBasedOnInStream )
529 2180 : CloseStorage();
530 : }
531 :
532 29047 : if ( pImp->m_pInStream && !GetContent().is() )
533 : {
534 4995 : CreateTempFile( true );
535 34042 : return;
536 : }
537 :
538 24052 : DELETEZ( pImp->m_pInStream );
539 24052 : if ( pImp->m_pSet )
540 23770 : pImp->m_pSet->ClearItem( SID_INPUTSTREAM );
541 :
542 24052 : CloseZipStorage_Impl();
543 24052 : pImp->xInputStream.clear();
544 :
545 24052 : if ( !pImp->m_pOutStream )
546 : {
547 : // output part of the stream is not used so the whole stream can be closed
548 : // TODO/LATER: is it correct?
549 18326 : pImp->xStream.clear();
550 18326 : if ( pImp->m_pSet )
551 18044 : pImp->m_pSet->ClearItem( SID_STREAM );
552 : }
553 : }
554 :
555 :
556 6434 : SvStream* SfxMedium::GetOutStream()
557 : {
558 6434 : if ( !pImp->m_pOutStream )
559 : {
560 : // Create a temp. file if there is none because we always
561 : // need one.
562 5774 : CreateTempFile( false );
563 :
564 5774 : if ( pImp->pTempFile )
565 : {
566 : // On windows we try to re-use XOutStream from xStream if that exists;
567 : // because opening new SvFileStream in this situation may fail with ERROR_SHARING_VIOLATION
568 : // TODO: this is a horrible hack that should probably be removed,
569 : // somebody needs to investigate this more thoroughly...
570 5774 : if (getenv("SFX_MEDIUM_REUSE_STREAM") && pImp->xStream.is())
571 : {
572 : assert(pImp->xStream->getOutputStream().is()); // need that...
573 : pImp->m_pOutStream = utl::UcbStreamHelper::CreateStream(
574 0 : pImp->xStream, false);
575 : }
576 : else
577 : {
578 : // On Unix don't try to re-use XOutStream from xStream if that exists;
579 : // it causes fdo#59022 (fails opening files via SMB on Linux)
580 : pImp->m_pOutStream = new SvFileStream(
581 5774 : pImp->m_aName, STREAM_STD_READWRITE);
582 : }
583 5774 : CloseStorage();
584 : }
585 : }
586 :
587 6434 : return pImp->m_pOutStream;
588 : }
589 :
590 :
591 2779 : bool SfxMedium::CloseOutStream()
592 : {
593 2779 : CloseOutStream_Impl();
594 2779 : return true;
595 : }
596 :
597 26391 : bool SfxMedium::CloseOutStream_Impl()
598 : {
599 26391 : if ( pImp->m_pOutStream )
600 : {
601 : // if there is a storage based on the OutStream, we have to
602 : // close the storage, too, because otherwise the storage
603 : // would use an invalid ( deleted ) stream.
604 : //TODO/MBA: how to deal with this?!
605 : //maybe we need a new flag when the storage was created from the outstream
606 5774 : if ( pImp->xStorage.is() )
607 : {
608 0 : CloseStorage();
609 : }
610 :
611 5774 : delete pImp->m_pOutStream;
612 5774 : pImp->m_pOutStream = NULL;
613 : }
614 :
615 26391 : if ( !pImp->m_pInStream )
616 : {
617 : // input part of the stream is not used so the whole stream can be closed
618 : // TODO/LATER: is it correct?
619 23659 : pImp->xStream.clear();
620 23659 : if ( pImp->m_pSet )
621 23377 : pImp->m_pSet->ClearItem( SID_STREAM );
622 : }
623 :
624 26391 : return true;
625 : }
626 :
627 :
628 102 : const OUString& SfxMedium::GetPhysicalName() const
629 : {
630 102 : if ( pImp->m_aName.isEmpty() && !pImp->m_aLogicName.isEmpty() )
631 1 : const_cast<SfxMedium*>(this)->CreateFileStream();
632 :
633 : // return the name then
634 102 : return pImp->m_aName;
635 : }
636 :
637 :
638 1 : void SfxMedium::CreateFileStream()
639 : {
640 1 : ForceSynchronStream_Impl( true );
641 1 : GetInStream();
642 1 : if( pImp->m_pInStream )
643 : {
644 1 : CreateTempFile( false );
645 1 : pImp->bIsTemp = true;
646 1 : CloseInStream_Impl();
647 : }
648 1 : }
649 :
650 :
651 839 : bool SfxMedium::Commit()
652 : {
653 839 : if( pImp->xStorage.is() )
654 105 : StorageCommit_Impl();
655 734 : else if( pImp->m_pOutStream )
656 685 : pImp->m_pOutStream->Flush();
657 49 : else if( pImp->m_pInStream )
658 0 : pImp->m_pInStream->Flush();
659 :
660 839 : if ( GetError() == SVSTREAM_OK )
661 : {
662 : // does something only in case there is a temporary file ( means aName points to different location than aLogicName )
663 839 : Transfer_Impl();
664 : }
665 :
666 839 : bool bResult = ( GetError() == SVSTREAM_OK );
667 :
668 839 : if ( bResult && DocNeedsFileDateCheck() )
669 837 : GetInitFileDate( true );
670 :
671 : // remove truncation mode from the flags
672 839 : pImp->m_nStorOpenMode &= (~StreamMode::TRUNC);
673 839 : return bResult;
674 : }
675 :
676 :
677 1637 : bool SfxMedium::IsStorage()
678 : {
679 1637 : if ( pImp->xStorage.is() )
680 782 : return true;
681 :
682 855 : if ( pImp->m_bTriedStorage )
683 155 : return pImp->bIsStorage;
684 :
685 700 : if ( pImp->pTempFile )
686 : {
687 48 : OUString aURL;
688 48 : if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->m_aName, aURL ) )
689 : {
690 : SAL_WARN( "sfx.doc", "Physical name not convertible!");
691 : }
692 48 : pImp->bIsStorage = SotStorage::IsStorageFile( aURL ) && !SotStorage::IsOLEStorage( aURL);
693 48 : if ( !pImp->bIsStorage )
694 48 : pImp->m_bTriedStorage = true;
695 : }
696 652 : else if ( GetInStream() )
697 : {
698 301 : pImp->bIsStorage = SotStorage::IsStorageFile( pImp->m_pInStream ) && !SotStorage::IsOLEStorage( pImp->m_pInStream );
699 301 : if ( !pImp->m_pInStream->GetError() && !pImp->bIsStorage )
700 279 : pImp->m_bTriedStorage = true;
701 : }
702 :
703 700 : return pImp->bIsStorage;
704 : }
705 :
706 :
707 0 : bool SfxMedium::IsPreview_Impl()
708 : {
709 0 : bool bPreview = false;
710 0 : SFX_ITEMSET_ARG( GetItemSet(), pPreview, SfxBoolItem, SID_PREVIEW, false);
711 0 : if ( pPreview )
712 0 : bPreview = pPreview->GetValue();
713 : else
714 : {
715 0 : SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, false);
716 0 : if ( pFlags )
717 : {
718 0 : OUString aFileFlags = pFlags->GetValue();
719 0 : aFileFlags = aFileFlags.toAsciiUpperCase();
720 0 : if ( -1 != aFileFlags.indexOf( 'B' ) )
721 0 : bPreview = true;
722 : }
723 : }
724 :
725 0 : return bPreview;
726 : }
727 :
728 :
729 1 : void SfxMedium::StorageBackup_Impl()
730 : {
731 1 : ::ucbhelper::Content aOriginalContent;
732 2 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
733 :
734 2 : bool bBasedOnOriginalFile = ( !pImp->pTempFile && !( !pImp->m_aLogicName.isEmpty() && pImp->m_bSalvageMode )
735 3 : && !GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).isEmpty()
736 2 : && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
737 3 : && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
738 :
739 3 : if ( bBasedOnOriginalFile && pImp->m_aBackupURL.isEmpty()
740 4 : && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, comphelper::getProcessComponentContext(), aOriginalContent ) )
741 : {
742 1 : DoInternalBackup_Impl( aOriginalContent );
743 1 : if( pImp->m_aBackupURL.isEmpty() )
744 0 : SetError( ERRCODE_SFX_CANTCREATEBACKUP, OUString( OSL_LOG_PREFIX ) );
745 1 : }
746 1 : }
747 :
748 :
749 1 : OUString SfxMedium::GetBackup_Impl()
750 : {
751 1 : if ( pImp->m_aBackupURL.isEmpty() )
752 1 : StorageBackup_Impl();
753 :
754 1 : return pImp->m_aBackupURL;
755 : }
756 :
757 :
758 849 : uno::Reference < embed::XStorage > SfxMedium::GetOutputStorage()
759 : {
760 849 : if ( GetError() )
761 0 : return uno::Reference< embed::XStorage >();
762 :
763 : // if the medium was constructed with a Storage: use this one, not a temp. storage
764 : // if a temporary storage already exists: use it
765 849 : if ( pImp->xStorage.is() && ( pImp->m_aLogicName.isEmpty() || pImp->pTempFile ) )
766 744 : return pImp->xStorage;
767 :
768 : // if necessary close stream that was used for reading
769 105 : if ( pImp->m_pInStream && !pImp->m_pInStream->IsWritable() )
770 0 : CloseInStream();
771 :
772 : DBG_ASSERT( !pImp->m_pOutStream, "OutStream in a readonly Medium?!" );
773 :
774 : // TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
775 : // in future it should be stored directly and then copied to the temporary location, since in this case no
776 : // file attributes have to be preserved and system copying mechanics could be used instead of streaming.
777 105 : CreateTempFileNoCopy();
778 :
779 105 : return GetStorage();
780 : }
781 :
782 :
783 2370 : void SfxMedium::SetEncryptionDataToStorage_Impl()
784 : {
785 : // in case media-descriptor contains password it should be used on opening
786 2370 : if ( pImp->xStorage.is() && pImp->m_pSet )
787 : {
788 2370 : uno::Sequence< beans::NamedValue > aEncryptionData;
789 2370 : if ( GetEncryptionData_Impl( pImp->m_pSet, aEncryptionData ) )
790 : {
791 : // replace the password with encryption data
792 6 : pImp->m_pSet->ClearItem( SID_PASSWORD );
793 6 : pImp->m_pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
794 :
795 : try
796 : {
797 6 : ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp->xStorage, aEncryptionData );
798 : }
799 0 : catch( const uno::Exception& )
800 : {
801 : SAL_WARN( "sfx.doc", "It must be possible to set a common password for the storage" );
802 : // TODO/LATER: set the error code in case of problem
803 : // SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
804 : }
805 2370 : }
806 : }
807 2370 : }
808 :
809 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
810 :
811 : // FIXME: Hmm actually lock files should be used for sftp: documents
812 : // even if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT. Only the use of lock
813 : // files for *local* documents is unnecessary in that case. But
814 : // actually, the checks for sftp: here are just wishful thinking; I
815 : // don't this there is any support for actually editing documents
816 : // behind sftp: URLs anyway.
817 :
818 : // Sure, there could perhaps be a 3rd-party extension that brings UCB
819 : // the potential to handle files behind sftp:. But there could also be
820 : // an extension that handles some arbitrary foobar: scheme *and* it
821 : // could be that lock files would be the correct thing to use for
822 : // foobar: documents, too. But the hardcoded test below won't know
823 : // that. Clearly the knowledge whether lock files should be used or
824 : // not for some URL scheme belongs in UCB, not here.
825 :
826 :
827 0 : sal_Int8 SfxMedium::ShowLockedDocumentDialog( const LockFileEntry& aData, bool bIsLoading, bool bOwnLock )
828 : {
829 0 : sal_Int8 nResult = LOCK_UI_NOLOCK;
830 :
831 : // show the interaction regarding the document opening
832 0 : uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
833 :
834 0 : if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || bOwnLock ) )
835 : {
836 0 : OUString aDocumentURL = GetURLObject().GetLastName();
837 0 : OUString aInfo;
838 0 : ::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
839 :
840 0 : if ( bOwnLock )
841 : {
842 0 : aInfo = aData[LockFileComponent::EDITTIME];
843 :
844 0 : xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
845 0 : document::OwnLockOnDocumentRequest( OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo, !bIsLoading ) ) );
846 : }
847 : else /*logically therefore bIsLoading is set */
848 : {
849 0 : if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
850 0 : aInfo = aData[LockFileComponent::OOOUSERNAME];
851 : else
852 0 : aInfo = aData[LockFileComponent::SYSUSERNAME];
853 :
854 0 : if ( !aInfo.isEmpty() && !aData[LockFileComponent::EDITTIME].isEmpty() )
855 : {
856 0 : aInfo += " ( " ;
857 0 : aInfo += aData[LockFileComponent::EDITTIME];
858 0 : aInfo += " )";
859 : }
860 :
861 0 : xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
862 0 : document::LockedDocumentRequest( OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
863 : }
864 :
865 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
866 0 : aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
867 0 : aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
868 0 : aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
869 0 : xInteractionRequestImpl->setContinuations( aContinuations );
870 :
871 0 : xHandler->handle( xInteractionRequestImpl.get() );
872 :
873 0 : ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
874 0 : if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
875 : {
876 0 : SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
877 : }
878 0 : else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
879 : {
880 : // own lock on loading, user has selected to ignore the lock
881 : // own lock on saving, user has selected to ignore the lock
882 : // alien lock on loading, user has selected to edit a copy of document
883 : // TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
884 0 : if ( bIsLoading && !bOwnLock )
885 : {
886 : // means that a copy of the document should be opened
887 0 : GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, true ) );
888 : }
889 0 : else if ( bOwnLock )
890 0 : nResult = LOCK_UI_SUCCEEDED;
891 : }
892 : else // if ( XSelected == aContinuations[1] )
893 : {
894 : // own lock on loading, user has selected to open readonly
895 : // own lock on saving, user has selected to open readonly
896 : // alien lock on loading, user has selected to retry saving
897 : // TODO/LATER: alien lock on saving, user has selected to retry saving
898 :
899 0 : if ( bIsLoading )
900 0 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
901 : else
902 0 : nResult = LOCK_UI_TRY;
903 0 : }
904 : }
905 : else
906 : {
907 0 : if ( bIsLoading )
908 : {
909 : // if no interaction handler is provided the default answer is open readonly
910 : // that usually happens in case the document is loaded per API
911 : // so the document must be opened readonly for backward compatibility
912 0 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
913 : }
914 : else
915 0 : SetError( ERRCODE_IO_ACCESSDENIED, OUString( OSL_LOG_PREFIX ) );
916 :
917 : }
918 :
919 0 : return nResult;
920 : }
921 :
922 : namespace
923 : {
924 32 : bool isSuitableProtocolForLocking(const OUString & rLogicName)
925 : {
926 32 : INetURLObject aUrl( rLogicName );
927 32 : INetProtocol eProt = aUrl.GetProtocol();
928 : #if HAVE_FEATURE_MACOSX_SANDBOX
929 : return eProt == INetProtocol::Sftp;
930 : #else
931 32 : return eProt == INetProtocol::File || eProt == INetProtocol::Sftp;
932 : #endif
933 : }
934 : }
935 :
936 : #endif // HAVE_FEATURE_MULTIUSER_ENVIRONMENT
937 :
938 : // sets SID_DOC_READONLY if the document cannot be opened for editing
939 : // if user cancel the loading the ERROR_ABORT is set
940 5666 : void SfxMedium::LockOrigFileOnDemand( bool bLoading, bool bNoUI )
941 : {
942 : #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
943 : (void) bLoading;
944 : (void) bNoUI;
945 : #else
946 5666 : if (!IsLockingUsed() || GetURLObject().HasError())
947 5618 : return;
948 :
949 : try
950 : {
951 48 : if ( pImp->m_bLocked && bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
952 : {
953 : // if the document is already locked the system locking might be temporarely off after storing
954 : // check whether the system file locking should be taken again
955 8 : GetLockingStream_Impl();
956 : }
957 :
958 48 : bool bResult = pImp->m_bLocked;
959 :
960 48 : if ( !bResult )
961 : {
962 : // no read-write access is necessary on loading if the document is explicitly opened as copy
963 40 : SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, false);
964 40 : bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
965 : }
966 :
967 48 : if ( !bResult && !IsReadOnly() )
968 : {
969 32 : bool bContentReadonly = false;
970 32 : if ( bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
971 : {
972 : // let the original document be opened to check the possibility to open it for editing
973 : // and to let the writable stream stay open to hold the lock on the document
974 21 : GetLockingStream_Impl();
975 : }
976 :
977 : // "IsReadOnly" property does not allow to detect whether the file is readonly always
978 : // so we try always to open the file for editing
979 : // the file is readonly only in case the read-write stream can not be opened
980 32 : if ( bLoading && !pImp->m_xLockingStream.is() )
981 : {
982 : try
983 : {
984 : // MediaDescriptor does this check also, the duplication should be avoided in future
985 0 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
986 0 : ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, comphelper::getProcessComponentContext() );
987 0 : aContent.getPropertyValue("IsReadOnly") >>= bContentReadonly;
988 : }
989 0 : catch( const uno::Exception& ) {}
990 :
991 : #if EXTRA_ACL_CHECK
992 : // This block was introduced as a fix to i#102464, but removing
993 : // this does not make the problem re-appear. But leaving this
994 : // part would interfere with documents saved in samba share. This
995 : // affects Windows only.
996 : if ( !bContentReadonly )
997 : {
998 : // the file is not readonly, check the ACL
999 :
1000 : OUString aPhysPath;
1001 : if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aPhysPath ) )
1002 : bContentReadonly = IsReadonlyAccordingACL( aPhysPath.getStr() );
1003 : }
1004 : #endif
1005 : }
1006 :
1007 : // do further checks only if the file not readonly in fs
1008 32 : if ( !bContentReadonly )
1009 : {
1010 : // the special file locking should be used only for suitable URLs
1011 32 : if ( isSuitableProtocolForLocking( pImp->m_aLogicName ) )
1012 : {
1013 :
1014 : // in case of storing the document should request the output before locking
1015 32 : if ( bLoading )
1016 : {
1017 : // let the stream be opened to check the system file locking
1018 21 : GetMedium_Impl();
1019 21 : if (GetError() != ERRCODE_NONE) {
1020 0 : return;
1021 : }
1022 : }
1023 :
1024 32 : sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
1025 :
1026 : // check whether system file locking has been used, the default value is false
1027 32 : bool bUseSystemLock = ::utl::LocalFileHelper::IsLocalFile( pImp->m_aLogicName ) && IsSystemFileLockingUsed();
1028 :
1029 : // TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
1030 : // if system lock is used the writeable stream should be available
1031 32 : bool bHandleSysLocked = ( bLoading && bUseSystemLock && !pImp->xStream.is() && !pImp->m_pOutStream );
1032 :
1033 32 : do
1034 : {
1035 : try
1036 : {
1037 32 : ::svt::DocumentLockFile aLockFile( pImp->m_aLogicName );
1038 32 : if ( !bHandleSysLocked )
1039 : {
1040 : try
1041 : {
1042 32 : bResult = aLockFile.CreateOwnLockFile();
1043 : }
1044 0 : catch ( const ucb::InteractiveIOException& e )
1045 : {
1046 : // exception means that the lock file can not be successfully accessed
1047 : // in this case it should be ignored if system file locking is anyway active
1048 0 : if ( bUseSystemLock || !IsOOoLockFileUsed() )
1049 : {
1050 0 : bResult = true;
1051 : // take the ownership over the lock file
1052 0 : aLockFile.OverwriteOwnLockFile();
1053 : }
1054 0 : else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
1055 : {
1056 : // system file locking is not active, ask user whether he wants to open the document without any locking
1057 0 : uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
1058 :
1059 0 : if ( xHandler.is() )
1060 : {
1061 : ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
1062 0 : = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
1063 :
1064 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
1065 0 : aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
1066 0 : aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
1067 0 : xIgnoreRequestImpl->setContinuations( aContinuations );
1068 :
1069 0 : xHandler->handle( xIgnoreRequestImpl.get() );
1070 :
1071 0 : ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
1072 0 : bResult = uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is();
1073 0 : }
1074 : }
1075 : }
1076 0 : catch ( const uno::Exception& )
1077 : {
1078 : // exception means that the lock file can not be successfully accessed
1079 : // in this case it should be ignored if system file locking is anyway active
1080 0 : if ( bUseSystemLock || !IsOOoLockFileUsed() )
1081 : {
1082 0 : bResult = true;
1083 : // take the ownership over the lock file
1084 0 : aLockFile.OverwriteOwnLockFile();
1085 : }
1086 : }
1087 :
1088 : // in case OOo locking is turned off the lock file is still written if possible
1089 : // but it is ignored while deciding whether the document should be opened for editing or not
1090 32 : if ( !bResult && !IsOOoLockFileUsed() )
1091 : {
1092 0 : bResult = true;
1093 : // take the ownership over the lock file
1094 0 : aLockFile.OverwriteOwnLockFile();
1095 : }
1096 : }
1097 :
1098 :
1099 32 : if ( !bResult )
1100 : {
1101 0 : LockFileEntry aData;
1102 : try
1103 : {
1104 : // impossibility to get data is no real problem
1105 0 : aData = aLockFile.GetLockData();
1106 : }
1107 0 : catch( const uno::Exception& )
1108 : {
1109 : }
1110 :
1111 0 : bool bOwnLock = false;
1112 :
1113 0 : if ( !bHandleSysLocked )
1114 : {
1115 0 : LockFileEntry aOwnData = svt::LockFileCommon::GenerateOwnEntry();
1116 0 : bOwnLock = aOwnData[LockFileComponent::SYSUSERNAME].equals( aData[LockFileComponent::SYSUSERNAME] );
1117 :
1118 0 : if ( bOwnLock
1119 0 : && aOwnData[LockFileComponent::LOCALHOST].equals( aData[LockFileComponent::LOCALHOST] )
1120 0 : && aOwnData[LockFileComponent::USERURL].equals( aData[LockFileComponent::USERURL] ) )
1121 : {
1122 : // this is own lock from the same installation, it could remain because of crash
1123 0 : bResult = true;
1124 0 : }
1125 : }
1126 :
1127 0 : if ( !bResult && !bNoUI )
1128 : {
1129 0 : bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
1130 0 : if ( bUIStatus == LOCK_UI_SUCCEEDED )
1131 : {
1132 : // take the ownership over the lock file
1133 0 : bResult = aLockFile.OverwriteOwnLockFile();
1134 : }
1135 : }
1136 :
1137 0 : bHandleSysLocked = false;
1138 32 : }
1139 : }
1140 0 : catch( const uno::Exception& )
1141 : {
1142 : }
1143 32 : } while( !bResult && bUIStatus == LOCK_UI_TRY );
1144 :
1145 32 : pImp->m_bLocked = bResult;
1146 : }
1147 : else
1148 : {
1149 : // this is no file URL, check whether the file is readonly
1150 0 : bResult = !bContentReadonly;
1151 : }
1152 : }
1153 : }
1154 :
1155 48 : if ( !bResult && GetError() == ERRCODE_NONE )
1156 : {
1157 : // the error should be set in case it is storing process
1158 : // or the document has been opened for editing explicitly
1159 7 : SFX_ITEMSET_ARG( pImp->m_pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, false );
1160 :
1161 7 : if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
1162 0 : SetError( ERRCODE_IO_ACCESSDENIED, OUString( OSL_LOG_PREFIX ) );
1163 : else
1164 7 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
1165 : }
1166 :
1167 : // when the file is locked, get the current file date
1168 48 : if ( bResult && DocNeedsFileDateCheck() )
1169 41 : GetInitFileDate( true );
1170 : }
1171 0 : catch( const uno::Exception& )
1172 : {
1173 : SAL_WARN( "sfx.doc", "Locking exception: high probability, that the content has not been created" );
1174 : }
1175 : #endif
1176 : }
1177 :
1178 :
1179 16562 : uno::Reference < embed::XStorage > SfxMedium::GetStorage( bool bCreateTempIfNo )
1180 : {
1181 16562 : if ( pImp->xStorage.is() || pImp->m_bTriedStorage )
1182 13694 : return pImp->xStorage;
1183 :
1184 2868 : uno::Sequence< uno::Any > aArgs( 2 );
1185 :
1186 : // the medium should be retrieved before temporary file creation
1187 : // to let the MediaDescriptor be filled with the streams
1188 2868 : GetMedium_Impl();
1189 :
1190 2868 : if ( bCreateTempIfNo )
1191 2842 : CreateTempFile( false );
1192 :
1193 2868 : GetMedium_Impl();
1194 :
1195 2868 : if ( GetError() )
1196 6 : return pImp->xStorage;
1197 :
1198 2862 : SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, false);
1199 2862 : if ( pRepairItem && pRepairItem->GetValue() )
1200 : {
1201 : // the storage should be created for repairing mode
1202 0 : CreateTempFile( false );
1203 0 : GetMedium_Impl();
1204 :
1205 0 : Reference< ::com::sun::star::ucb::XProgressHandler > xProgressHandler;
1206 0 : Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
1207 :
1208 0 : SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, false );
1209 0 : if( pxProgressItem && ( pxProgressItem->GetValue() >>= xStatusIndicator ) )
1210 0 : xProgressHandler = Reference< ::com::sun::star::ucb::XProgressHandler >(
1211 0 : new utl::ProgressHandlerWrap( xStatusIndicator ) );
1212 :
1213 0 : uno::Sequence< beans::PropertyValue > aAddProps( 2 );
1214 0 : aAddProps[0].Name = "RepairPackage";
1215 0 : aAddProps[0].Value <<= true;
1216 0 : aAddProps[1].Name = "StatusIndicator";
1217 0 : aAddProps[1].Value <<= xProgressHandler;
1218 :
1219 : // the first arguments will be filled later
1220 0 : aArgs.realloc( 3 );
1221 0 : aArgs[2] <<= aAddProps;
1222 : }
1223 :
1224 2862 : if ( pImp->xStream.is() )
1225 : {
1226 : // since the storage is based on temporary stream we open it always read-write
1227 2836 : aArgs[0] <<= pImp->xStream;
1228 2836 : aArgs[1] <<= embed::ElementModes::READWRITE;
1229 2836 : pImp->bStorageBasedOnInStream = true;
1230 : }
1231 26 : else if ( pImp->xInputStream.is() )
1232 : {
1233 : // since the storage is based on temporary stream we open it always read-write
1234 26 : aArgs[0] <<= pImp->xInputStream;
1235 26 : aArgs[1] <<= embed::ElementModes::READ;
1236 26 : pImp->bStorageBasedOnInStream = true;
1237 : }
1238 : else
1239 : {
1240 0 : CloseStreams_Impl();
1241 0 : aArgs[0] <<= pImp->m_aName;
1242 0 : aArgs[1] <<= embed::ElementModes::READ;
1243 0 : pImp->bStorageBasedOnInStream = false;
1244 : }
1245 :
1246 : try
1247 : {
1248 5231 : pImp->xStorage = uno::Reference< embed::XStorage >(
1249 5723 : ::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
1250 2370 : uno::UNO_QUERY );
1251 : }
1252 492 : catch( const uno::Exception& )
1253 : {
1254 : // impossibility to create the storage is no error
1255 : }
1256 :
1257 2862 : if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
1258 : {
1259 0 : pImp->xStorage = 0;
1260 0 : if ( pImp->m_pInStream )
1261 0 : pImp->m_pInStream->Seek(0);
1262 0 : return uno::Reference< embed::XStorage >();
1263 : }
1264 :
1265 2862 : pImp->m_bTriedStorage = true;
1266 :
1267 : // TODO/LATER: Get versionlist on demand
1268 2862 : if ( pImp->xStorage.is() )
1269 : {
1270 2370 : SetEncryptionDataToStorage_Impl();
1271 2370 : GetVersionList();
1272 : }
1273 :
1274 2862 : SFX_ITEMSET_ARG( pImp->m_pSet, pVersion, SfxInt16Item, SID_VERSION, false);
1275 :
1276 2862 : bool bResetStorage = false;
1277 2862 : if ( pVersion && pVersion->GetValue() )
1278 : {
1279 : // Read all available versions
1280 0 : if ( pImp->aVersions.getLength() )
1281 : {
1282 : // Search for the version fits the comment
1283 : // The versions are numbered startign with 1, versions with
1284 : // negative versions numbers are counted backwards from the
1285 : // current version
1286 0 : short nVersion = pVersion ? pVersion->GetValue() : 0;
1287 0 : if ( nVersion<0 )
1288 0 : nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
1289 0 : else if ( nVersion )
1290 0 : nVersion--;
1291 :
1292 0 : util::RevisionTag& rTag = pImp->aVersions[nVersion];
1293 : {
1294 : // Open SubStorage for all versions
1295 0 : uno::Reference < embed::XStorage > xSub = pImp->xStorage->openStorageElement( "Versions",
1296 0 : embed::ElementModes::READ );
1297 :
1298 : DBG_ASSERT( xSub.is(), "Version list, but no Versions!" );
1299 :
1300 : // There the version is stored as packed Stream
1301 0 : uno::Reference < io::XStream > xStr = xSub->openStreamElement( rTag.Identifier, embed::ElementModes::READ );
1302 0 : SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStr );
1303 0 : if ( pStream && pStream->GetError() == SVSTREAM_OK )
1304 : {
1305 : // Unpack Stream in TempDir
1306 0 : ::utl::TempFile aTempFile;
1307 0 : OUString aTmpName = aTempFile.GetURL();
1308 0 : SvFileStream aTmpStream( aTmpName, SFX_STREAM_READWRITE );
1309 :
1310 0 : pStream->ReadStream( aTmpStream );
1311 0 : aTmpStream.Close();
1312 :
1313 : // Open data as Storage
1314 0 : pImp->m_nStorOpenMode = SFX_STREAM_READONLY;
1315 0 : pImp->xStorage = comphelper::OStorageHelper::GetStorageFromURL( aTmpName, embed::ElementModes::READ );
1316 0 : pImp->bStorageBasedOnInStream = false;
1317 0 : OUString aTemp;
1318 0 : ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
1319 0 : SetPhysicalName_Impl( aTemp );
1320 :
1321 0 : pImp->bIsTemp = true;
1322 0 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
1323 : // TODO/MBA
1324 0 : pImp->aVersions.realloc(0);
1325 : }
1326 : else
1327 0 : bResetStorage = true;
1328 : }
1329 : }
1330 : else
1331 0 : bResetStorage = true;
1332 : }
1333 :
1334 2862 : if ( bResetStorage )
1335 : {
1336 0 : pImp->xStorage.clear();
1337 0 : if ( pImp->m_pInStream )
1338 0 : pImp->m_pInStream->Seek( 0L );
1339 : }
1340 :
1341 2862 : pImp->bIsStorage = pImp->xStorage.is();
1342 2862 : return pImp->xStorage;
1343 : }
1344 :
1345 :
1346 214 : uno::Reference< embed::XStorage > SfxMedium::GetZipStorageToSign_Impl( bool bReadOnly )
1347 : {
1348 214 : if ( !GetError() && !pImp->m_xZipStorage.is() )
1349 : {
1350 214 : GetMedium_Impl();
1351 :
1352 : try
1353 : {
1354 : // we can not sign document if there is no stream
1355 : // should it be possible at all?
1356 214 : if ( !bReadOnly && pImp->xStream.is() )
1357 : {
1358 0 : pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream, embed::ElementModes::READWRITE );
1359 : }
1360 214 : else if ( pImp->xInputStream.is() )
1361 : {
1362 214 : pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING, pImp->xInputStream );
1363 : }
1364 : }
1365 0 : catch( const uno::Exception& )
1366 : {
1367 : SAL_WARN( "sfx.doc", "No possibility to get readonly version of storage from medium!" );
1368 : }
1369 :
1370 214 : if ( GetError() ) // do not remove warnings
1371 0 : ResetError();
1372 : }
1373 :
1374 214 : return pImp->m_xZipStorage;
1375 : }
1376 :
1377 :
1378 29294 : void SfxMedium::CloseZipStorage_Impl()
1379 : {
1380 29294 : if ( pImp->m_xZipStorage.is() )
1381 : {
1382 : try {
1383 210 : pImp->m_xZipStorage->dispose();
1384 0 : } catch( const uno::Exception& )
1385 : {}
1386 :
1387 210 : pImp->m_xZipStorage.clear();
1388 : }
1389 29294 : }
1390 :
1391 17938 : void SfxMedium::CloseStorage()
1392 : {
1393 17938 : if ( pImp->xStorage.is() )
1394 : {
1395 3503 : uno::Reference < lang::XComponent > xComp( pImp->xStorage, uno::UNO_QUERY );
1396 : // in the salvage mode the medium does not own the storage
1397 3503 : if ( pImp->bDisposeStorage && !pImp->m_bSalvageMode )
1398 : {
1399 : try {
1400 1995 : xComp->dispose();
1401 0 : } catch( const uno::Exception& )
1402 : {
1403 : SAL_WARN( "sfx.doc", "Medium's storage is already disposed!" );
1404 : }
1405 : }
1406 :
1407 3503 : pImp->xStorage.clear();
1408 3503 : pImp->bStorageBasedOnInStream = false;
1409 : }
1410 :
1411 17938 : pImp->m_bTriedStorage = false;
1412 17938 : pImp->bIsStorage = false;
1413 17938 : }
1414 :
1415 6094 : void SfxMedium::CanDisposeStorage_Impl( bool bDisposeStorage )
1416 : {
1417 6094 : pImp->bDisposeStorage = bDisposeStorage;
1418 6094 : }
1419 :
1420 0 : bool SfxMedium::WillDisposeStorageOnClose_Impl()
1421 : {
1422 0 : return pImp->bDisposeStorage;
1423 : }
1424 :
1425 26621 : StreamMode SfxMedium::GetOpenMode() const
1426 : {
1427 26621 : return pImp->m_nStorOpenMode;
1428 : }
1429 :
1430 49 : void SfxMedium::SetOpenMode( StreamMode nStorOpen,
1431 : bool bDontClose )
1432 : {
1433 49 : if ( pImp->m_nStorOpenMode != nStorOpen )
1434 : {
1435 0 : pImp->m_nStorOpenMode = nStorOpen;
1436 :
1437 0 : if( !bDontClose )
1438 : {
1439 0 : if ( pImp->xStorage.is() )
1440 0 : CloseStorage();
1441 :
1442 0 : CloseStreams_Impl();
1443 : }
1444 : }
1445 49 : }
1446 :
1447 :
1448 0 : bool SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content& aOriginalContent,
1449 : const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1450 : {
1451 : try
1452 : {
1453 0 : ::ucbhelper::Content aTransactCont( pImp->m_aBackupURL, xComEnv, comphelper::getProcessComponentContext() );
1454 :
1455 0 : Reference< XInputStream > aOrigInput = aTransactCont.openStream();
1456 0 : aOriginalContent.writeStream( aOrigInput, true );
1457 0 : return true;
1458 : }
1459 0 : catch( const Exception& )
1460 : {
1461 : // in case of failure here the backup file should not be removed
1462 : // TODO/LATER: a message should be used to let user know about the backup
1463 0 : pImp->m_bRemoveBackup = false;
1464 : // TODO/LATER: needs a specific error code
1465 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1466 : }
1467 :
1468 0 : return false;
1469 : }
1470 :
1471 :
1472 105 : bool SfxMedium::StorageCommit_Impl()
1473 : {
1474 105 : bool bResult = false;
1475 105 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1476 210 : ::ucbhelper::Content aOriginalContent;
1477 :
1478 105 : if ( pImp->xStorage.is() )
1479 : {
1480 105 : if ( !GetError() )
1481 : {
1482 105 : uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
1483 105 : if ( xTrans.is() )
1484 : {
1485 : try
1486 : {
1487 105 : xTrans->commit();
1488 105 : CloseZipStorage_Impl();
1489 105 : bResult = true;
1490 : }
1491 0 : catch ( const embed::UseBackupException& aBackupExc )
1492 : {
1493 : // since the temporary file is created always now, the scenario is close to be impossible
1494 0 : if ( !pImp->pTempFile )
1495 : {
1496 : OSL_ENSURE( !pImp->m_aBackupURL.isEmpty(), "No backup on storage commit!\n" );
1497 0 : if ( !pImp->m_aBackupURL.isEmpty()
1498 0 : && ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
1499 : xDummyEnv, comphelper::getProcessComponentContext(),
1500 0 : aOriginalContent ) )
1501 : {
1502 : // use backup to restore the file
1503 : // the storage has already disconnected from original location
1504 0 : CloseAndReleaseStreams_Impl();
1505 0 : if ( !UseBackupToRestore_Impl( aOriginalContent, xDummyEnv ) )
1506 : {
1507 : // connect the medium to the temporary file of the storage
1508 0 : pImp->aContent = ::ucbhelper::Content();
1509 0 : pImp->m_aName = aBackupExc.TemporaryFileURL;
1510 : OSL_ENSURE( !pImp->m_aName.isEmpty(), "The exception _must_ contain the temporary URL!\n" );
1511 : }
1512 : }
1513 :
1514 0 : if ( !GetError() )
1515 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1516 : }
1517 : }
1518 0 : catch ( const uno::Exception& )
1519 : {
1520 : //TODO/LATER: improve error handling
1521 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1522 : }
1523 105 : }
1524 : }
1525 : }
1526 :
1527 210 : return bResult;
1528 : }
1529 :
1530 :
1531 836 : bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
1532 : const INetURLObject& aDest,
1533 : const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
1534 : {
1535 836 : bool bResult = false;
1536 836 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
1537 1672 : Reference< XOutputStream > aDestStream;
1538 1672 : ::ucbhelper::Content aOriginalContent;
1539 :
1540 : try
1541 : {
1542 836 : aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv, comphelper::getProcessComponentContext() );
1543 : }
1544 0 : catch ( const ::com::sun::star::ucb::CommandAbortedException& )
1545 : {
1546 0 : pImp->m_eError = ERRCODE_ABORT;
1547 : }
1548 0 : catch ( const ::com::sun::star::ucb::CommandFailedException& )
1549 : {
1550 0 : pImp->m_eError = ERRCODE_ABORT;
1551 : }
1552 0 : catch (const ::com::sun::star::ucb::ContentCreationException& ex)
1553 : {
1554 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1555 0 : if (
1556 0 : (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
1557 0 : (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
1558 : )
1559 : {
1560 0 : pImp->m_eError = ERRCODE_IO_NOTEXISTSPATH;
1561 : }
1562 : }
1563 0 : catch (const ::com::sun::star::uno::Exception&)
1564 : {
1565 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1566 : }
1567 :
1568 836 : if( !pImp->m_eError || (pImp->m_eError & ERRCODE_WARNING_MASK) )
1569 : {
1570 836 : if ( pImp->xStorage.is() )
1571 105 : CloseStorage();
1572 :
1573 836 : CloseStreams_Impl();
1574 :
1575 836 : ::ucbhelper::Content aTempCont;
1576 836 : if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, comphelper::getProcessComponentContext(), aTempCont ) )
1577 : {
1578 836 : bool bTransactStarted = false;
1579 836 : SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, false );
1580 836 : SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, false );
1581 836 : bool bRename = pRename && pRename->GetValue();
1582 836 : bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
1583 :
1584 : try
1585 : {
1586 836 : if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
1587 : {
1588 819 : if( pImp->m_aBackupURL.isEmpty() )
1589 818 : DoInternalBackup_Impl( aOriginalContent );
1590 :
1591 819 : if( !pImp->m_aBackupURL.isEmpty() )
1592 : {
1593 819 : Reference< XInputStream > aTempInput = aTempCont.openStream();
1594 819 : bTransactStarted = true;
1595 819 : aOriginalContent.setPropertyValue( "Size", uno::makeAny( (sal_Int64)0 ) );
1596 819 : aOriginalContent.writeStream( aTempInput, bOverWrite );
1597 819 : bResult = true;
1598 : }
1599 : else
1600 : {
1601 0 : pImp->m_eError = ERRCODE_SFX_CANTCREATEBACKUP;
1602 : }
1603 : }
1604 : else
1605 : {
1606 17 : Reference< XInputStream > aTempInput = aTempCont.openStream();
1607 17 : aOriginalContent.writeStream( aTempInput, bOverWrite );
1608 17 : bResult = true;
1609 : }
1610 : }
1611 0 : catch ( const ::com::sun::star::ucb::CommandAbortedException& )
1612 : {
1613 0 : pImp->m_eError = ERRCODE_ABORT;
1614 : }
1615 0 : catch ( const ::com::sun::star::ucb::CommandFailedException& )
1616 : {
1617 0 : pImp->m_eError = ERRCODE_ABORT;
1618 : }
1619 0 : catch ( const ::com::sun::star::ucb::InteractiveIOException& r )
1620 : {
1621 0 : if ( r.Code == IOErrorCode_ACCESS_DENIED )
1622 0 : pImp->m_eError = ERRCODE_IO_ACCESSDENIED;
1623 0 : else if ( r.Code == IOErrorCode_NOT_EXISTING )
1624 0 : pImp->m_eError = ERRCODE_IO_NOTEXISTS;
1625 0 : else if ( r.Code == IOErrorCode_CANT_READ )
1626 0 : pImp->m_eError = ERRCODE_IO_CANTREAD;
1627 : else
1628 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1629 : }
1630 0 : catch ( const ::com::sun::star::uno::Exception& )
1631 : {
1632 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1633 : }
1634 :
1635 836 : if ( bResult )
1636 : {
1637 836 : if ( pImp->pTempFile )
1638 : {
1639 836 : pImp->pTempFile->EnableKillingFile( true );
1640 836 : delete pImp->pTempFile;
1641 836 : pImp->pTempFile = NULL;
1642 : }
1643 : }
1644 0 : else if ( bTransactStarted )
1645 : {
1646 0 : UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
1647 : }
1648 : }
1649 : else
1650 0 : pImp->m_eError = ERRCODE_IO_CANTREAD;
1651 : }
1652 :
1653 1672 : return bResult;
1654 : }
1655 :
1656 :
1657 0 : bool SfxMedium::TryDirectTransfer( const OUString& aURL, SfxItemSet& aTargetSet )
1658 : {
1659 0 : if ( GetError() )
1660 0 : return false;
1661 :
1662 : // if the document had no password it should be stored without password
1663 : // if the document had password it should be stored with the same password
1664 : // otherwise the stream copying can not be done
1665 0 : SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, false );
1666 0 : SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, false );
1667 0 : if ( ( !pNewPassItem && !pOldPassItem )
1668 0 : || ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue() == pOldPassItem->GetValue() ) )
1669 : {
1670 : // the filter must be the same
1671 0 : SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, false );
1672 0 : SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, false );
1673 0 : if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue() == pOldFilterItem->GetValue() )
1674 : {
1675 : // get the input stream and copy it
1676 : // in case of success return true
1677 0 : uno::Reference< io::XInputStream > xInStream = GetInputStream();
1678 :
1679 0 : ResetError();
1680 0 : if ( xInStream.is() )
1681 : {
1682 : try
1683 : {
1684 0 : uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1685 0 : sal_Int64 nPos = 0;
1686 0 : if ( xSeek.is() )
1687 : {
1688 0 : nPos = xSeek->getPosition();
1689 0 : xSeek->seek( 0 );
1690 : }
1691 :
1692 0 : uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
1693 0 : ::ucbhelper::Content aTargetContent( aURL, xEnv, comphelper::getProcessComponentContext() );
1694 :
1695 0 : InsertCommandArgument aInsertArg;
1696 0 : aInsertArg.Data = xInStream;
1697 0 : SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, false );
1698 0 : SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, false );
1699 0 : if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
1700 0 : || (pRename && pRename->GetValue()) ) // argument says: rename file
1701 0 : aInsertArg.ReplaceExisting = false;
1702 : else
1703 0 : aInsertArg.ReplaceExisting = true; // default is overwrite existing files
1704 :
1705 0 : Any aCmdArg;
1706 0 : aCmdArg <<= aInsertArg;
1707 : aTargetContent.executeCommand( OUString( "insert" ),
1708 0 : aCmdArg );
1709 :
1710 0 : if ( xSeek.is() )
1711 0 : xSeek->seek( nPos );
1712 :
1713 0 : return true;
1714 : }
1715 0 : catch( const uno::Exception& )
1716 : {}
1717 0 : }
1718 : }
1719 : }
1720 :
1721 0 : return false;
1722 : }
1723 :
1724 :
1725 839 : void SfxMedium::Transfer_Impl()
1726 : {
1727 : // The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
1728 839 : OUString aNameURL;
1729 839 : if ( pImp->pTempFile )
1730 838 : aNameURL = pImp->pTempFile->GetURL();
1731 1 : else if ( !pImp->m_aLogicName.isEmpty() && pImp->m_bSalvageMode )
1732 : {
1733 : // makes sense only in case logic name is set
1734 0 : if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->m_aName, aNameURL ) )
1735 : SAL_WARN( "sfx.doc", "The medium name is not convertible!" );
1736 : }
1737 :
1738 839 : if ( !aNameURL.isEmpty() && ( !pImp->m_eError || (pImp->m_eError & ERRCODE_WARNING_MASK) ) )
1739 : {
1740 : SAL_INFO( "sfx.doc", "SfxMedium::Transfer_Impl, copying to target" );
1741 :
1742 838 : Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
1743 1674 : Reference< XOutputStream > rOutStream;
1744 :
1745 : // in case an output stream is provided from outside and the URL is correct
1746 : // commit to the stream
1747 838 : if (pImp->m_aLogicName.startsWith("private:stream"))
1748 : {
1749 : // TODO/LATER: support storing to SID_STREAM
1750 2 : SFX_ITEMSET_ARG( pImp->m_pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, false);
1751 2 : if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
1752 : {
1753 2 : if ( pImp->xStorage.is() )
1754 0 : CloseStorage();
1755 :
1756 2 : CloseStreams_Impl();
1757 :
1758 2 : INetURLObject aSource( aNameURL );
1759 4 : ::ucbhelper::Content aTempCont;
1760 2 : if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, comphelper::getProcessComponentContext(), aTempCont ) )
1761 : {
1762 : try
1763 : {
1764 : sal_Int32 nRead;
1765 2 : sal_Int32 nBufferSize = 32767;
1766 2 : Sequence < sal_Int8 > aSequence ( nBufferSize );
1767 4 : Reference< XInputStream > aTempInput = aTempCont.openStream();
1768 :
1769 2 : do
1770 : {
1771 2 : nRead = aTempInput->readBytes ( aSequence, nBufferSize );
1772 2 : if ( nRead < nBufferSize )
1773 : {
1774 2 : Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
1775 2 : rOutStream->writeBytes ( aTempBuf );
1776 : }
1777 : else
1778 0 : rOutStream->writeBytes ( aSequence );
1779 : }
1780 : while ( nRead == nBufferSize );
1781 :
1782 : // remove temporary file
1783 2 : if ( pImp->pTempFile )
1784 : {
1785 2 : pImp->pTempFile->EnableKillingFile( true );
1786 2 : delete pImp->pTempFile;
1787 2 : pImp->pTempFile = NULL;
1788 2 : }
1789 : }
1790 0 : catch( const Exception& )
1791 : {}
1792 2 : }
1793 : }
1794 : else
1795 : {
1796 : SAL_WARN( "sfx.doc", "Illegal Output stream parameter!" );
1797 0 : SetError( ERRCODE_IO_GENERAL, OUString( OSL_LOG_PREFIX ) );
1798 : }
1799 :
1800 : // free the reference
1801 2 : if ( pImp->m_pSet )
1802 2 : pImp->m_pSet->ClearItem( SID_OUTPUTSTREAM );
1803 :
1804 2 : return;
1805 : }
1806 :
1807 836 : GetContent();
1808 836 : if ( !pImp->aContent.get().is() )
1809 : {
1810 0 : pImp->m_eError = ERRCODE_IO_NOTEXISTS;
1811 0 : return;
1812 : }
1813 :
1814 836 : SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, false);
1815 836 : if ( pSegmentSize )
1816 : {
1817 : // this file must be stored into a disk spanned package
1818 : try
1819 : {
1820 0 : uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
1821 0 : embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
1822 :
1823 : // set segment size property; package will automatically be divided in pieces fitting
1824 : // into this size
1825 0 : ::com::sun::star::uno::Any aAny;
1826 0 : aAny <<= pSegmentSize->GetValue();
1827 :
1828 0 : uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
1829 0 : xSet->setPropertyValue("SegmentSize", aAny );
1830 :
1831 : // copy the temporary storage into the disk spanned package
1832 0 : GetStorage()->copyToStorage( xStor );
1833 0 : uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
1834 0 : if ( xTrans.is() )
1835 0 : xTrans->commit();
1836 :
1837 : }
1838 0 : catch ( const uno::Exception& )
1839 : {
1840 : //TODO/MBA: error handling
1841 : }
1842 0 : return;
1843 : }
1844 :
1845 1672 : INetURLObject aDest( GetURLObject() );
1846 :
1847 : // source is the temp file written so far
1848 1672 : INetURLObject aSource( aNameURL );
1849 :
1850 : // a special case, an interaction handler should be used for
1851 : // authentication in case it is available
1852 1672 : Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
1853 1672 : Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
1854 836 : if (xInteractionHandler.is())
1855 2073 : xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
1856 1382 : Reference< ::com::sun::star::ucb::XProgressHandler >() );
1857 :
1858 1672 : OUString aDestURL( aDest.GetMainURL( INetURLObject::NO_DECODE ) );
1859 :
1860 836 : if ( ::utl::LocalFileHelper::IsLocalFile( aDestURL ) || !aDest.removeSegment() )
1861 : {
1862 836 : TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
1863 :
1864 : // Hideous - no clean way to do this, so we re-open the file just to fsync it
1865 836 : osl::File aFile( aDestURL );
1866 836 : if ( aFile.open( osl_File_OpenFlag_Write ) == osl::FileBase::E_None )
1867 : {
1868 836 : aFile.sync();
1869 : SAL_INFO( "sfx.doc", "fsync'd saved file '" << aDestURL << "'" );
1870 836 : aFile.close();
1871 836 : }
1872 : }
1873 : else
1874 : {
1875 : // create content for the parent folder and call transfer on that content with the source content
1876 : // and the destination file name as parameters
1877 0 : ::ucbhelper::Content aSourceContent;
1878 0 : ::ucbhelper::Content aTransferContent;
1879 :
1880 0 : ::ucbhelper::Content aDestContent;
1881 0 : (void)::ucbhelper::Content::create( aDestURL, xComEnv, comphelper::getProcessComponentContext(), aDestContent );
1882 : // For checkin, we need the object URL, not the parent folder:
1883 0 : if ( !IsInCheckIn( ) )
1884 : {
1885 : // Get the parent URL from the XChild if possible: why would the URL necessarily have
1886 : // a hierarchical path? It's not always the case for CMIS.
1887 0 : Reference< ::com::sun::star::container::XChild> xChild( aDestContent.get(), uno::UNO_QUERY );
1888 0 : OUString sParentUrl;
1889 0 : if ( xChild.is( ) )
1890 : {
1891 0 : Reference< ::com::sun::star::ucb::XContent > xParent( xChild->getParent( ), uno::UNO_QUERY );
1892 0 : if ( xParent.is( ) )
1893 : {
1894 0 : sParentUrl = xParent->getIdentifier( )->getContentIdentifier();
1895 0 : }
1896 : }
1897 :
1898 0 : if ( sParentUrl.isEmpty() )
1899 0 : aDestURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
1900 : // adjust to above aDest.removeSegment()
1901 : else
1902 0 : aDestURL = sParentUrl;
1903 : }
1904 :
1905 : // LongName wasn't defined anywhere, only used here... get the Title instead
1906 : // as it's less probably empty
1907 0 : OUString aFileName;
1908 0 : Any aAny = aDestContent.getPropertyValue("Title");
1909 0 : aAny >>= aFileName;
1910 0 : aAny = aDestContent.getPropertyValue( OUString("ObjectId" ) );
1911 0 : OUString sObjectId;
1912 0 : aAny >>= sObjectId;
1913 0 : if ( aFileName.isEmpty() )
1914 0 : aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1915 :
1916 : try
1917 : {
1918 0 : aTransferContent = ::ucbhelper::Content( aDestURL, xComEnv, comphelper::getProcessComponentContext() );
1919 : }
1920 0 : catch (const ::com::sun::star::ucb::ContentCreationException& ex)
1921 : {
1922 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1923 0 : if (
1924 0 : (ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
1925 0 : (ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
1926 : )
1927 : {
1928 0 : pImp->m_eError = ERRCODE_IO_NOTEXISTSPATH;
1929 : }
1930 : }
1931 0 : catch (const ::com::sun::star::uno::Exception&)
1932 : {
1933 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1934 : }
1935 :
1936 0 : if ( !pImp->m_eError || (pImp->m_eError & ERRCODE_WARNING_MASK) )
1937 : {
1938 : // free resources, otherwise the transfer may fail
1939 0 : if ( pImp->xStorage.is() )
1940 0 : CloseStorage();
1941 :
1942 0 : CloseStreams_Impl();
1943 :
1944 0 : (void)::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, comphelper::getProcessComponentContext(), aSourceContent );
1945 :
1946 : // check for external parameters that may customize the handling of NameClash situations
1947 0 : SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, false );
1948 0 : SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, false );
1949 : sal_Int32 nNameClash;
1950 0 : if ( pOverWrite && !pOverWrite->GetValue() )
1951 : // argument says: never overwrite
1952 0 : nNameClash = NameClash::ERROR;
1953 0 : else if ( pRename && pRename->GetValue() )
1954 : // argument says: rename file
1955 0 : nNameClash = NameClash::RENAME;
1956 : else
1957 : // default is overwrite existing files
1958 0 : nNameClash = NameClash::OVERWRITE;
1959 :
1960 : try
1961 : {
1962 0 : OUString aMimeType = pImp->getFilterMimeType();
1963 0 : ::ucbhelper::InsertOperation eOperation = ::ucbhelper::InsertOperation_COPY;
1964 0 : bool bMajor = false;
1965 0 : OUString sComment;
1966 0 : if ( IsInCheckIn( ) )
1967 : {
1968 0 : eOperation = ::ucbhelper::InsertOperation_CHECKIN;
1969 0 : SFX_ITEMSET_ARG( GetItemSet(), pMajor, SfxBoolItem, SID_DOCINFO_MAJOR, false );
1970 0 : bMajor = pMajor && pMajor->GetValue( );
1971 0 : SFX_ITEMSET_ARG( GetItemSet(), pComments, SfxStringItem, SID_DOCINFO_COMMENTS, false );
1972 0 : if ( pComments )
1973 0 : sComment = pComments->GetValue( );
1974 : }
1975 0 : OUString sResultURL;
1976 0 : if (!aTransferContent.transferContent( aSourceContent, eOperation,
1977 0 : aFileName, nNameClash, aMimeType, bMajor, sComment, &sResultURL, sObjectId))
1978 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
1979 0 : else if ( !sResultURL.isEmpty( ) ) // Likely to happen only for checkin
1980 0 : SwitchDocumentToFile( sResultURL );
1981 : }
1982 0 : catch ( const ::com::sun::star::ucb::CommandAbortedException& )
1983 : {
1984 0 : pImp->m_eError = ERRCODE_ABORT;
1985 : }
1986 0 : catch ( const ::com::sun::star::ucb::CommandFailedException& )
1987 : {
1988 0 : pImp->m_eError = ERRCODE_ABORT;
1989 : }
1990 0 : catch ( const ::com::sun::star::ucb::InteractiveIOException& r )
1991 : {
1992 0 : if ( r.Code == IOErrorCode_ACCESS_DENIED )
1993 0 : pImp->m_eError = ERRCODE_IO_ACCESSDENIED;
1994 0 : else if ( r.Code == IOErrorCode_NOT_EXISTING )
1995 0 : pImp->m_eError = ERRCODE_IO_NOTEXISTS;
1996 0 : else if ( r.Code == IOErrorCode_CANT_READ )
1997 0 : pImp->m_eError = ERRCODE_IO_CANTREAD;
1998 : else
1999 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
2000 : }
2001 0 : catch ( const ::com::sun::star::uno::Exception& )
2002 : {
2003 0 : pImp->m_eError = ERRCODE_IO_GENERAL;
2004 : }
2005 :
2006 : // do not switch from temporary file in case of nonfile protocol
2007 0 : }
2008 : }
2009 :
2010 836 : if ( ( !pImp->m_eError || (pImp->m_eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
2011 : {
2012 : // without a TempFile the physical and logical name should be the same after successful transfer
2013 : ::utl::LocalFileHelper::ConvertURLToPhysicalName(
2014 836 : GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), pImp->m_aName );
2015 836 : pImp->m_bSalvageMode = false;
2016 836 : }
2017 837 : }
2018 : }
2019 :
2020 :
2021 819 : void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
2022 : const OUString& aPrefix,
2023 : const OUString& aExtension,
2024 : const OUString& aDestDir )
2025 : {
2026 819 : if ( !pImp->m_aBackupURL.isEmpty() )
2027 819 : return; // the backup was done already
2028 :
2029 819 : ::utl::TempFile aTransactTemp( aPrefix, true, &aExtension, &aDestDir );
2030 :
2031 1638 : INetURLObject aBackObj( aTransactTemp.GetURL() );
2032 1638 : OUString aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2033 :
2034 1638 : Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
2035 1638 : ::ucbhelper::Content aBackupCont;
2036 819 : if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, comphelper::getProcessComponentContext(), aBackupCont ) )
2037 : {
2038 : try
2039 : {
2040 819 : OUString sMimeType = pImp->getFilterMimeType();
2041 1638 : if( aBackupCont.transferContent( aOriginalContent,
2042 : ::ucbhelper::InsertOperation_COPY,
2043 : aBackupName,
2044 : NameClash::OVERWRITE,
2045 1638 : sMimeType ) )
2046 : {
2047 819 : pImp->m_aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
2048 819 : pImp->m_bRemoveBackup = true;
2049 819 : }
2050 : }
2051 0 : catch( const Exception& )
2052 : {}
2053 : }
2054 :
2055 819 : if ( pImp->m_aBackupURL.isEmpty() )
2056 819 : aTransactTemp.EnableKillingFile();
2057 : }
2058 :
2059 :
2060 819 : void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
2061 : {
2062 819 : if ( !pImp->m_aBackupURL.isEmpty() )
2063 819 : return; // the backup was done already
2064 :
2065 819 : OUString aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT,
2066 : true,
2067 819 : INetURLObject::NO_DECODE );
2068 :
2069 819 : sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
2070 1638 : OUString aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
2071 1638 : OUString aExtension = ( nPrefixLen == -1 ) ? OUString() : aFileName.copy( nPrefixLen );
2072 1638 : OUString aBakDir = SvtPathOptions().GetBackupPath();
2073 :
2074 : // create content for the parent folder ( = backup folder )
2075 1638 : ::ucbhelper::Content aContent;
2076 1638 : Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2077 819 : if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv, aBakDir, aContent) )
2078 819 : DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
2079 :
2080 819 : if ( pImp->m_aBackupURL.isEmpty() )
2081 : {
2082 : // the copiing to the backup catalog failed ( for example because
2083 : // of using an encrypted partition as target catalog )
2084 : // since the user did not specify to make backup explicitly
2085 : // office should try to make backup in another place,
2086 : // target catalog does not look bad for this case ( and looks
2087 : // to be the only way for encrypted partitions )
2088 :
2089 0 : INetURLObject aDest = GetURLObject();
2090 0 : if ( aDest.removeSegment() )
2091 0 : DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
2092 819 : }
2093 : }
2094 :
2095 :
2096 :
2097 0 : void SfxMedium::DoBackup_Impl()
2098 : {
2099 : // source file name is the logical name of this medium
2100 0 : INetURLObject aSource( GetURLObject() );
2101 :
2102 : // there is nothing to backup in case source file does not exist
2103 0 : if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
2104 0 : return;
2105 :
2106 0 : bool bSuccess = false;
2107 :
2108 : // get path for backups
2109 0 : OUString aBakDir = SvtPathOptions().GetBackupPath();
2110 0 : if( !aBakDir.isEmpty() )
2111 : {
2112 : // create content for the parent folder ( = backup folder )
2113 0 : ::ucbhelper::Content aContent;
2114 0 : Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
2115 0 : if( ::utl::UCBContentHelper::ensureFolder(comphelper::getProcessComponentContext(), xEnv, aBakDir, aContent) )
2116 : {
2117 : // save as ".bak" file
2118 0 : INetURLObject aDest( aBakDir );
2119 0 : aDest.insertName( aSource.getName() );
2120 0 : aDest.setExtension( "bak" );
2121 0 : OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
2122 :
2123 : // create a content for the source file
2124 0 : ::ucbhelper::Content aSourceContent;
2125 0 : if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, comphelper::getProcessComponentContext(), aSourceContent ) )
2126 : {
2127 : try
2128 : {
2129 : // do the transfer ( copy source file to backup dir )
2130 0 : OUString sMimeType = pImp->getFilterMimeType();
2131 : bSuccess = aContent.transferContent( aSourceContent,
2132 : ::ucbhelper::InsertOperation_COPY,
2133 : aFileName,
2134 : NameClash::OVERWRITE,
2135 0 : sMimeType );
2136 0 : if( bSuccess )
2137 : {
2138 0 : pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
2139 0 : pImp->m_bRemoveBackup = false;
2140 0 : }
2141 : }
2142 0 : catch ( const ::com::sun::star::uno::Exception& )
2143 : {
2144 : }
2145 0 : }
2146 0 : }
2147 : }
2148 :
2149 0 : if ( !bSuccess )
2150 : {
2151 0 : pImp->m_eError = ERRCODE_SFX_CANTCREATEBACKUP;
2152 0 : }
2153 : }
2154 :
2155 :
2156 14218 : void SfxMedium::ClearBackup_Impl()
2157 : {
2158 14218 : if( pImp->m_bRemoveBackup )
2159 : {
2160 : // currently a document is always stored in a new medium,
2161 : // thus if a backup can not be removed the backup URL should not be cleaned
2162 819 : if ( !pImp->m_aBackupURL.isEmpty() )
2163 : {
2164 819 : if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
2165 : {
2166 819 : pImp->m_bRemoveBackup = false;
2167 819 : pImp->m_aBackupURL.clear();
2168 : }
2169 : else
2170 : {
2171 :
2172 : SAL_WARN( "sfx.doc", "Couldn't remove backup file!");
2173 : }
2174 : }
2175 : }
2176 : else
2177 13399 : pImp->m_aBackupURL.clear();
2178 14218 : }
2179 :
2180 :
2181 29 : void SfxMedium::GetLockingStream_Impl()
2182 : {
2183 87 : if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
2184 87 : && !pImp->m_xLockingStream.is() )
2185 : {
2186 26 : SFX_ITEMSET_ARG( pImp->m_pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, false);
2187 26 : if ( pWriteStreamItem )
2188 22 : pWriteStreamItem->GetValue() >>= pImp->m_xLockingStream;
2189 :
2190 26 : if ( !pImp->m_xLockingStream.is() )
2191 : {
2192 : // open the original document
2193 4 : uno::Sequence< beans::PropertyValue > xProps;
2194 4 : TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2195 8 : utl::MediaDescriptor aMedium( xProps );
2196 :
2197 4 : aMedium.addInputStreamOwnLock();
2198 :
2199 8 : uno::Reference< io::XInputStream > xInputStream;
2200 4 : aMedium[utl::MediaDescriptor::PROP_STREAM()] >>= pImp->m_xLockingStream;
2201 4 : aMedium[utl::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
2202 :
2203 4 : if ( !pImp->pTempFile && pImp->m_aName.isEmpty() )
2204 : {
2205 : // the medium is still based on the original file, it makes sense to initialize the streams
2206 0 : if ( pImp->m_xLockingStream.is() )
2207 0 : pImp->xStream = pImp->m_xLockingStream;
2208 :
2209 0 : if ( xInputStream.is() )
2210 0 : pImp->xInputStream = xInputStream;
2211 :
2212 0 : if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2213 0 : pImp->xInputStream = pImp->xStream->getInputStream();
2214 4 : }
2215 : }
2216 : }
2217 29 : }
2218 :
2219 :
2220 15249 : void SfxMedium::GetMedium_Impl()
2221 : {
2222 15249 : if ( !pImp->m_pInStream )
2223 : {
2224 12286 : pImp->bDownloadDone = false;
2225 12286 : Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
2226 :
2227 : //TODO/MBA: need support for SID_STREAM
2228 12286 : SFX_ITEMSET_ARG( pImp->m_pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, false);
2229 12286 : SFX_ITEMSET_ARG( pImp->m_pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, false);
2230 12286 : if ( pWriteStreamItem )
2231 : {
2232 22 : pWriteStreamItem->GetValue() >>= pImp->xStream;
2233 :
2234 22 : if ( pInStreamItem )
2235 22 : pInStreamItem->GetValue() >>= pImp->xInputStream;
2236 :
2237 22 : if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2238 0 : pImp->xInputStream = pImp->xStream->getInputStream();
2239 : }
2240 12264 : else if ( pInStreamItem )
2241 : {
2242 2827 : pInStreamItem->GetValue() >>= pImp->xInputStream;
2243 : }
2244 : else
2245 : {
2246 9437 : uno::Sequence < beans::PropertyValue > xProps;
2247 18874 : OUString aFileName;
2248 9437 : if (!pImp->m_aName.isEmpty())
2249 : {
2250 4434 : if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->m_aName, aFileName ) )
2251 : {
2252 : SAL_WARN( "sfx.doc", "Physical name not convertible!");
2253 : }
2254 : }
2255 : else
2256 5003 : aFileName = GetName();
2257 :
2258 : // in case the temporary file exists the streams should be initialized from it,
2259 : // but the original MediaDescriptor should not be changed
2260 9437 : bool bFromTempFile = ( pImp->pTempFile != NULL );
2261 :
2262 9437 : if ( !bFromTempFile )
2263 : {
2264 6584 : GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
2265 6584 : if( !(pImp->m_nStorOpenMode & StreamMode::WRITE) )
2266 1535 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
2267 6584 : if (xInteractionHandler.is())
2268 15 : GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
2269 : }
2270 :
2271 9437 : if ( pImp->m_xInputStreamToLoadFrom.is() )
2272 : {
2273 4994 : pImp->xInputStream = pImp->m_xInputStreamToLoadFrom;
2274 4994 : pImp->xInputStream->skipBytes(0);
2275 4994 : if (pImp->m_bInputStreamIsReadOnly)
2276 4994 : GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
2277 : }
2278 : else
2279 : {
2280 4443 : TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
2281 4443 : utl::MediaDescriptor aMedium( xProps );
2282 :
2283 4443 : if ( pImp->m_xLockingStream.is() && !bFromTempFile )
2284 : {
2285 : // the medium is not based on the temporary file, so the original stream can be used
2286 0 : pImp->xStream = pImp->m_xLockingStream;
2287 : }
2288 : else
2289 : {
2290 4443 : if ( bFromTempFile )
2291 : {
2292 2853 : aMedium[utl::MediaDescriptor::PROP_URL()] <<= OUString( aFileName );
2293 2853 : aMedium.erase( utl::MediaDescriptor::PROP_READONLY() );
2294 2853 : aMedium.addInputStream();
2295 : }
2296 1590 : else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
2297 : {
2298 : // use the special locking approach only for file URLs
2299 1581 : aMedium.addInputStreamOwnLock();
2300 : }
2301 : else
2302 9 : aMedium.addInputStream();
2303 :
2304 : // the ReadOnly property set in aMedium is ignored
2305 : // the check is done in LockOrigFileOnDemand() for file and non-file URLs
2306 :
2307 : //TODO/MBA: what happens if property is not there?!
2308 4443 : aMedium[utl::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
2309 4443 : aMedium[utl::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
2310 : }
2311 :
2312 4443 : GetContent();
2313 4443 : if ( !pImp->xInputStream.is() && pImp->xStream.is() )
2314 0 : pImp->xInputStream = pImp->xStream->getInputStream();
2315 : }
2316 :
2317 9437 : if ( !bFromTempFile )
2318 : {
2319 : //TODO/MBA: need support for SID_STREAM
2320 6584 : if ( pImp->xStream.is() )
2321 5 : GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
2322 :
2323 6584 : GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
2324 9437 : }
2325 : }
2326 :
2327 : //TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
2328 12286 : if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
2329 372 : SetError( ERRCODE_IO_ACCESSDENIED, OUString( OSL_LOG_PREFIX ) );
2330 :
2331 12286 : if ( !GetError() )
2332 : {
2333 11550 : if ( pImp->xStream.is() )
2334 2874 : pImp->m_pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
2335 8676 : else if ( pImp->xInputStream.is() )
2336 8676 : pImp->m_pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
2337 : }
2338 :
2339 12286 : pImp->bDownloadDone = true;
2340 12286 : pImp->aDoneLink.ClearPendingCall();
2341 12286 : sal_uIntPtr nError = GetError();
2342 12286 : pImp->aDoneLink.Call( reinterpret_cast<void*>(nError) );
2343 : }
2344 15249 : }
2345 :
2346 1857 : bool SfxMedium::IsRemote() const
2347 : {
2348 1857 : return pImp->m_bRemote;
2349 : }
2350 :
2351 2491 : void SfxMedium::SetUpdatePickList(bool bVal)
2352 : {
2353 2491 : pImp->bUpdatePickList = bVal;
2354 2491 : }
2355 :
2356 3195 : bool SfxMedium::IsUpdatePickList() const
2357 : {
2358 3195 : return pImp->bUpdatePickList;
2359 : }
2360 :
2361 2 : void SfxMedium::SetLongName(const OUString &rName)
2362 : {
2363 2 : pImp->m_aLongName = rName;
2364 2 : }
2365 :
2366 2 : const OUString& SfxMedium::GetLongName() const
2367 : {
2368 2 : return pImp->m_aLongName;
2369 : }
2370 :
2371 543 : void SfxMedium::SetDoneLink( const Link<>& rLink )
2372 : {
2373 543 : pImp->aDoneLink = rLink;
2374 543 : }
2375 :
2376 535 : void SfxMedium::Download( const Link<>& aLink )
2377 : {
2378 535 : SetDoneLink( aLink );
2379 535 : GetInStream();
2380 535 : if ( pImp->m_pInStream && !aLink.IsSet() )
2381 : {
2382 1034 : while( !pImp->bDownloadDone )
2383 0 : Application::Yield();
2384 : }
2385 535 : }
2386 :
2387 :
2388 12469 : void SfxMedium::Init_Impl()
2389 : /* [Description]
2390 : Includes a valid:: sun:: com:: star:: util:: URL (If a file name was
2391 : previously in there) in the logical name and if available sets the
2392 : physical name as the file name.
2393 : */
2394 :
2395 : {
2396 12469 : Reference< XOutputStream > rOutStream;
2397 :
2398 : // TODO/LATER: handle lifetime of storages
2399 12469 : pImp->bDisposeStorage = false;
2400 :
2401 12469 : SFX_ITEMSET_ARG( pImp->m_pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, false);
2402 12469 : if ( pSalvageItem && pSalvageItem->GetValue().isEmpty() )
2403 : {
2404 0 : pSalvageItem = NULL;
2405 0 : pImp->m_pSet->ClearItem( SID_DOC_SALVAGE );
2406 : }
2407 :
2408 12469 : if (!pImp->m_aLogicName.isEmpty())
2409 : {
2410 4882 : INetURLObject aUrl( pImp->m_aLogicName );
2411 4882 : INetProtocol eProt = aUrl.GetProtocol();
2412 4882 : if ( eProt == INetProtocol::NotValid )
2413 : {
2414 : SAL_WARN( "sfx.doc", "Unknown protocol!" );
2415 : }
2416 : else
2417 : {
2418 4882 : if ( aUrl.HasMark() )
2419 : {
2420 0 : pImp->m_aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
2421 0 : GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
2422 : }
2423 :
2424 : // try to convert the URL into a physical name - but never change a physical name
2425 : // physical name may be set if the logical name is changed after construction
2426 4882 : if ( pImp->m_aName.isEmpty() )
2427 4882 : ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), pImp->m_aName );
2428 : else
2429 : {
2430 : DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
2431 : }
2432 4882 : }
2433 : }
2434 :
2435 12469 : if ( pSalvageItem && !pSalvageItem->GetValue().isEmpty() )
2436 : {
2437 0 : pImp->m_aLogicName = pSalvageItem->GetValue();
2438 0 : DELETEZ( pImp->m_pURLObj );
2439 0 : pImp->m_bSalvageMode = true;
2440 : }
2441 :
2442 : // in case output stream is by mistake here
2443 : // clear the reference
2444 12469 : SFX_ITEMSET_ARG( pImp->m_pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, false);
2445 37405 : if( pOutStreamItem
2446 24940 : && ( !( pOutStreamItem->GetValue() >>= rOutStream )
2447 2 : || !pImp->m_aLogicName.startsWith("private:stream")) )
2448 : {
2449 0 : pImp->m_pSet->ClearItem( SID_OUTPUTSTREAM );
2450 : SAL_WARN( "sfx.doc", "Unexpected Output stream parameter!\n" );
2451 : }
2452 :
2453 12469 : if (!pImp->m_aLogicName.isEmpty())
2454 : {
2455 : // if the logic name is set it should be set in MediaDescriptor as well
2456 4882 : SFX_ITEMSET_ARG( pImp->m_pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, false );
2457 4882 : if ( !pFileNameItem )
2458 : {
2459 : // let the ItemSet be created if necessary
2460 : GetItemSet()->Put(
2461 : SfxStringItem(
2462 1685 : SID_FILE_NAME, INetURLObject( pImp->m_aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
2463 : }
2464 : }
2465 :
2466 12469 : SetIsRemote_Impl();
2467 :
2468 24938 : osl::DirectoryItem item;
2469 12469 : if (osl::DirectoryItem::get(GetName(), item) == osl::FileBase::E_None) {
2470 4477 : osl::FileStatus stat(osl_FileStatus_Mask_Attributes);
2471 8954 : if (item.getFileStatus(stat) == osl::FileBase::E_None
2472 4477 : && stat.isValid(osl_FileStatus_Mask_Attributes))
2473 : {
2474 4477 : if ((stat.getAttributes() & osl_File_Attribute_ReadOnly) != 0) {
2475 0 : pImp->m_bOriginallyReadOnly = true;
2476 : }
2477 4477 : }
2478 12469 : }
2479 12469 : }
2480 :
2481 :
2482 6344 : SfxMedium::SfxMedium() : pImp(new SfxMedium_Impl(this))
2483 : {
2484 6344 : Init_Impl();
2485 6344 : }
2486 :
2487 :
2488 :
2489 5247 : void SfxMedium::UseInteractionHandler( bool bUse )
2490 : {
2491 5247 : pImp->bAllowDefaultIntHdl = bUse;
2492 5247 : }
2493 :
2494 :
2495 :
2496 : ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
2497 22486 : SfxMedium::GetInteractionHandler()
2498 : {
2499 : // if interaction isn't allowed explicitly ... return empty reference!
2500 22486 : if ( !pImp->bUseInteractionHandler )
2501 11 : return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2502 :
2503 : // search a possible existing handler inside cached item set
2504 22475 : if ( pImp->m_pSet )
2505 : {
2506 17481 : ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
2507 17481 : SFX_ITEMSET_ARG( pImp->m_pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, false);
2508 17481 : if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
2509 14291 : return xHandler;
2510 : }
2511 :
2512 : // if default interaction isn't allowed explicitly ... return empty reference!
2513 8184 : if ( !pImp->bAllowDefaultIntHdl )
2514 8180 : return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
2515 :
2516 : // otherwise return cached default handler ... if it exist.
2517 4 : if ( pImp->xInteraction.is() )
2518 0 : return pImp->xInteraction;
2519 :
2520 : // create default handler and cache it!
2521 4 : Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
2522 : pImp->xInteraction.set(
2523 4 : task::InteractionHandler::createWithParent(xContext, 0), UNO_QUERY_THROW );
2524 4 : return pImp->xInteraction;
2525 : }
2526 :
2527 :
2528 :
2529 4697 : void SfxMedium::SetFilter( const SfxFilter* pFilterP, bool /*bResetOrig*/ )
2530 : {
2531 4697 : pImp->m_pFilter = pFilterP;
2532 4697 : }
2533 :
2534 75562109 : const SfxFilter* SfxMedium::GetFilter() const
2535 : {
2536 75562109 : return pImp->m_pFilter;
2537 : }
2538 :
2539 :
2540 :
2541 9536 : const SfxFilter* SfxMedium::GetOrigFilter( bool bNotCurrent ) const
2542 : {
2543 9536 : return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pImp->m_pFilter;
2544 : }
2545 :
2546 :
2547 :
2548 0 : sal_uInt32 SfxMedium::CreatePasswordToModifyHash( const OUString& aPasswd, bool bWriter )
2549 : {
2550 0 : sal_uInt32 nHash = 0;
2551 :
2552 0 : if ( !aPasswd.isEmpty() )
2553 : {
2554 0 : if ( bWriter )
2555 : {
2556 0 : nHash = ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd );
2557 : }
2558 : else
2559 : {
2560 0 : rtl_TextEncoding nEncoding = osl_getThreadTextEncoding();
2561 0 : nHash = ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd, nEncoding );
2562 : }
2563 : }
2564 :
2565 0 : return nHash;
2566 : }
2567 :
2568 :
2569 :
2570 12361 : void SfxMedium::Close()
2571 : {
2572 12361 : if ( pImp->xStorage.is() )
2573 : {
2574 1215 : CloseStorage();
2575 : }
2576 :
2577 12361 : CloseStreams_Impl();
2578 :
2579 12361 : UnlockFile( false );
2580 12361 : }
2581 :
2582 833 : void SfxMedium::CloseAndRelease()
2583 : {
2584 833 : if ( pImp->xStorage.is() )
2585 : {
2586 2 : CloseStorage();
2587 : }
2588 :
2589 833 : CloseAndReleaseStreams_Impl();
2590 :
2591 833 : UnlockFile( true );
2592 833 : }
2593 :
2594 13194 : void SfxMedium::UnlockFile( bool bReleaseLockStream )
2595 : {
2596 : #if !HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2597 : (void) bReleaseLockStream;
2598 : #else
2599 13194 : if ( pImp->m_xLockingStream.is() )
2600 : {
2601 23 : if ( bReleaseLockStream )
2602 : {
2603 : try
2604 : {
2605 0 : uno::Reference< io::XInputStream > xInStream = pImp->m_xLockingStream->getInputStream();
2606 0 : uno::Reference< io::XOutputStream > xOutStream = pImp->m_xLockingStream->getOutputStream();
2607 0 : if ( xInStream.is() )
2608 0 : xInStream->closeInput();
2609 0 : if ( xOutStream.is() )
2610 0 : xOutStream->closeOutput();
2611 : }
2612 0 : catch( const uno::Exception& )
2613 : {}
2614 : }
2615 :
2616 23 : pImp->m_xLockingStream.clear();
2617 : }
2618 :
2619 13194 : if ( pImp->m_bLocked )
2620 : {
2621 : try
2622 : {
2623 31 : pImp->m_bLocked = false;
2624 31 : ::svt::DocumentLockFile aLockFile( pImp->m_aLogicName );
2625 : // TODO/LATER: A warning could be shown in case the file is not the own one
2626 31 : aLockFile.RemoveFile();
2627 : }
2628 0 : catch( const uno::Exception& )
2629 : {}
2630 : }
2631 : #endif
2632 13194 : }
2633 :
2634 5137 : void SfxMedium::CloseAndReleaseStreams_Impl()
2635 : {
2636 5137 : CloseZipStorage_Impl();
2637 :
2638 5137 : uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
2639 10274 : uno::Reference< io::XOutputStream > xOutToClose;
2640 5137 : if ( pImp->xStream.is() )
2641 : {
2642 2643 : xOutToClose = pImp->xStream->getOutputStream();
2643 :
2644 : // if the locking stream is closed here the related member should be cleaned
2645 2643 : if ( pImp->xStream == pImp->m_xLockingStream )
2646 2 : pImp->m_xLockingStream.clear();
2647 : }
2648 :
2649 : // The probably exsisting SvStream wrappers should be closed first
2650 5137 : CloseStreams_Impl();
2651 :
2652 : // in case of salvage mode the storage is based on the streams
2653 5137 : if ( !pImp->m_bSalvageMode )
2654 : {
2655 : try
2656 : {
2657 5137 : if ( xInToClose.is() )
2658 2725 : xInToClose->closeInput();
2659 5137 : if ( xOutToClose.is() )
2660 2643 : xOutToClose->closeOutput();
2661 : }
2662 0 : catch ( const uno::Exception& )
2663 : {
2664 : }
2665 5137 : }
2666 5137 : }
2667 :
2668 :
2669 18336 : void SfxMedium::CloseStreams_Impl()
2670 : {
2671 18336 : CloseInStream_Impl();
2672 18336 : CloseOutStream_Impl();
2673 :
2674 18336 : if ( pImp->m_pSet )
2675 18054 : pImp->m_pSet->ClearItem( SID_CONTENT );
2676 :
2677 18336 : pImp->aContent = ::ucbhelper::Content();
2678 18336 : }
2679 :
2680 :
2681 :
2682 12469 : void SfxMedium::SetIsRemote_Impl()
2683 : {
2684 12469 : INetURLObject aObj( GetName() );
2685 12469 : switch( aObj.GetProtocol() )
2686 : {
2687 : case INetProtocol::Ftp:
2688 : case INetProtocol::Http:
2689 : case INetProtocol::Https:
2690 8 : pImp->m_bRemote = true;
2691 8 : break;
2692 : default:
2693 12461 : pImp->m_bRemote = GetName().startsWith("private:msgid");
2694 12461 : break;
2695 : }
2696 :
2697 : // As files that are written to the remote transmission must also be able
2698 : // to be read.
2699 12469 : if (pImp->m_bRemote)
2700 8 : pImp->m_nStorOpenMode |= StreamMode::READ;
2701 12469 : }
2702 :
2703 :
2704 :
2705 49 : void SfxMedium::SetName( const OUString& aNameP, bool bSetOrigURL )
2706 : {
2707 49 : if (pImp->aOrigURL.isEmpty())
2708 49 : pImp->aOrigURL = pImp->m_aLogicName;
2709 49 : if( bSetOrigURL )
2710 49 : pImp->aOrigURL = aNameP;
2711 49 : pImp->m_aLogicName = aNameP;
2712 49 : DELETEZ( pImp->m_pURLObj );
2713 49 : pImp->aContent = ::ucbhelper::Content();
2714 49 : Init_Impl();
2715 49 : }
2716 :
2717 :
2718 16797 : const OUString& SfxMedium::GetOrigURL() const
2719 : {
2720 16797 : return pImp->aOrigURL.isEmpty() ? pImp->m_aLogicName : pImp->aOrigURL;
2721 : }
2722 :
2723 :
2724 :
2725 0 : void SfxMedium::SetPhysicalName_Impl( const OUString& rNameP )
2726 : {
2727 0 : if ( rNameP != pImp->m_aName )
2728 : {
2729 0 : if( pImp->pTempFile )
2730 : {
2731 0 : delete pImp->pTempFile;
2732 0 : pImp->pTempFile = NULL;
2733 : }
2734 :
2735 0 : if ( !pImp->m_aName.isEmpty() || !rNameP.isEmpty() )
2736 0 : pImp->aContent = ::ucbhelper::Content();
2737 :
2738 0 : pImp->m_aName = rNameP;
2739 0 : pImp->m_bTriedStorage = false;
2740 0 : pImp->bIsStorage = false;
2741 : }
2742 0 : }
2743 :
2744 :
2745 :
2746 561 : void SfxMedium::ReOpen()
2747 : {
2748 561 : bool bUseInteractionHandler = pImp->bUseInteractionHandler;
2749 561 : pImp->bUseInteractionHandler = false;
2750 561 : GetMedium_Impl();
2751 561 : pImp->bUseInteractionHandler = bUseInteractionHandler;
2752 561 : }
2753 :
2754 :
2755 :
2756 0 : void SfxMedium::CompleteReOpen()
2757 : {
2758 : // do not use temporary file for reopen and in case of success throw the temporary file away
2759 0 : bool bUseInteractionHandler = pImp->bUseInteractionHandler;
2760 0 : pImp->bUseInteractionHandler = false;
2761 :
2762 0 : ::utl::TempFile* pTmpFile = NULL;
2763 0 : if ( pImp->pTempFile )
2764 : {
2765 0 : pTmpFile = pImp->pTempFile;
2766 0 : pImp->pTempFile = NULL;
2767 0 : pImp->m_aName.clear();
2768 : }
2769 :
2770 0 : GetMedium_Impl();
2771 :
2772 0 : if ( GetError() )
2773 : {
2774 0 : if ( pImp->pTempFile )
2775 : {
2776 0 : pImp->pTempFile->EnableKillingFile( true );
2777 0 : delete pImp->pTempFile;
2778 : }
2779 0 : pImp->pTempFile = pTmpFile;
2780 0 : if ( pImp->pTempFile )
2781 0 : pImp->m_aName = pImp->pTempFile->GetFileName();
2782 : }
2783 0 : else if (pTmpFile)
2784 : {
2785 0 : pTmpFile->EnableKillingFile( true );
2786 0 : delete pTmpFile;
2787 :
2788 : }
2789 :
2790 0 : pImp->bUseInteractionHandler = bUseInteractionHandler;
2791 0 : }
2792 :
2793 1866 : SfxMedium::SfxMedium(const OUString &rName, StreamMode nOpenMode, const SfxFilter *pFlt, SfxItemSet *pInSet) :
2794 1866 : pImp(new SfxMedium_Impl(this))
2795 : {
2796 1866 : pImp->m_pSet = pInSet;
2797 1866 : pImp->m_pFilter = pFlt;
2798 1866 : pImp->m_aLogicName = rName;
2799 1866 : pImp->m_nStorOpenMode = nOpenMode;
2800 1866 : Init_Impl();
2801 1866 : }
2802 :
2803 522 : SfxMedium::SfxMedium(const OUString &rName, const OUString &rReferer, StreamMode nOpenMode, const SfxFilter *pFlt, SfxItemSet *pInSet) :
2804 522 : pImp(new SfxMedium_Impl(this))
2805 : {
2806 522 : pImp->m_pSet = pInSet;
2807 522 : SfxItemSet * s = GetItemSet();
2808 522 : if (s->GetItem(SID_REFERER) == 0) {
2809 522 : s->Put(SfxStringItem(SID_REFERER, rReferer));
2810 : }
2811 522 : pImp->m_pFilter = pFlt;
2812 522 : pImp->m_aLogicName = rName;
2813 522 : pImp->m_nStorOpenMode = nOpenMode;
2814 522 : Init_Impl();
2815 522 : }
2816 :
2817 2495 : SfxMedium::SfxMedium( const uno::Sequence<beans::PropertyValue>& aArgs ) :
2818 2495 : pImp(new SfxMedium_Impl(this))
2819 : {
2820 2495 : SfxAllItemSet *pParams = new SfxAllItemSet( SfxGetpApp()->GetPool() );
2821 2495 : pImp->m_pSet = pParams;
2822 2495 : TransformParameters( SID_OPENDOC, aArgs, *pParams );
2823 :
2824 4990 : OUString aFilterProvider, aFilterName;
2825 : {
2826 2495 : const SfxPoolItem* pItem = NULL;
2827 2495 : if (pImp->m_pSet->HasItem(SID_FILTER_PROVIDER, &pItem))
2828 0 : aFilterProvider = static_cast<const SfxStringItem*>(pItem)->GetValue();
2829 :
2830 2495 : if (pImp->m_pSet->HasItem(SID_FILTER_NAME, &pItem))
2831 2491 : aFilterName = static_cast<const SfxStringItem*>(pItem)->GetValue();
2832 : }
2833 :
2834 2495 : if (aFilterProvider.isEmpty())
2835 : {
2836 : // This is a conventional filter type.
2837 2495 : pImp->m_pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
2838 : }
2839 : else
2840 : {
2841 : // This filter is from an external provider such as orcus.
2842 0 : pImp->m_pCustomFilter.reset(new SfxFilter(aFilterProvider, aFilterName));
2843 0 : pImp->m_pFilter = pImp->m_pCustomFilter.get();
2844 : }
2845 :
2846 2495 : SFX_ITEMSET_ARG( pImp->m_pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, false );
2847 2495 : if( pSalvageItem )
2848 : {
2849 : // QUESTION: there is some treatment of Salvage in Init_Impl; align!
2850 0 : if ( !pSalvageItem->GetValue().isEmpty() )
2851 : {
2852 : // if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
2853 : // that must be copied here
2854 :
2855 0 : SFX_ITEMSET_ARG( pImp->m_pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, false );
2856 0 : if (!pFileNameItem) throw uno::RuntimeException();
2857 0 : OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
2858 0 : if ( !aNewTempFileURL.isEmpty() )
2859 : {
2860 0 : pImp->m_pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
2861 0 : pImp->m_pSet->ClearItem( SID_INPUTSTREAM );
2862 0 : pImp->m_pSet->ClearItem( SID_STREAM );
2863 0 : pImp->m_pSet->ClearItem( SID_CONTENT );
2864 : }
2865 : else
2866 : {
2867 : SAL_WARN( "sfx.doc", "Can not create a new temporary file for crash recovery!\n" );
2868 0 : }
2869 : }
2870 : }
2871 :
2872 2495 : bool readOnly = false;
2873 2495 : SFX_ITEMSET_ARG( pImp->m_pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, false );
2874 2495 : if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
2875 11 : readOnly = true;
2876 :
2877 2495 : SFX_ITEMSET_ARG( pImp->m_pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, false );
2878 2495 : if (!pFileNameItem) throw uno::RuntimeException();
2879 2495 : pImp->m_aLogicName = pFileNameItem->GetValue();
2880 2495 : pImp->m_nStorOpenMode = readOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
2881 4990 : Init_Impl();
2882 2495 : }
2883 :
2884 :
2885 :
2886 :
2887 1142 : SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const OUString& rBaseURL, const SfxItemSet* p ) :
2888 1142 : pImp(new SfxMedium_Impl(this))
2889 : {
2890 1142 : OUString aType = SfxFilter::GetTypeFromStorage(rStor);
2891 1142 : pImp->m_pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4EA( aType );
2892 : DBG_ASSERT( pImp->m_pFilter, "No Filter for storage found!" );
2893 :
2894 1142 : Init_Impl();
2895 1142 : pImp->xStorage = rStor;
2896 1142 : pImp->bDisposeStorage = false;
2897 :
2898 : // always take BaseURL first, could be overwritten by ItemSet
2899 1142 : GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
2900 1142 : if ( p )
2901 572 : GetItemSet()->Put( *p );
2902 1142 : }
2903 :
2904 :
2905 :
2906 2 : SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const OUString& rBaseURL, const OUString &rTypeName, const SfxItemSet* p ) :
2907 2 : pImp(new SfxMedium_Impl(this))
2908 : {
2909 2 : pImp->m_pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4EA( rTypeName );
2910 : DBG_ASSERT( pImp->m_pFilter, "No Filter for storage found!" );
2911 :
2912 2 : Init_Impl();
2913 2 : pImp->xStorage = rStor;
2914 2 : pImp->bDisposeStorage = false;
2915 :
2916 : // always take BaseURL first, could be overwritten by ItemSet
2917 2 : GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
2918 2 : if ( p )
2919 0 : GetItemSet()->Put( *p );
2920 2 : }
2921 :
2922 :
2923 :
2924 30338 : SfxMedium::~SfxMedium()
2925 : {
2926 : // if there is a requirement to clean the backup this is the last possibility to do it
2927 12352 : ClearBackup_Impl();
2928 :
2929 12352 : Close();
2930 :
2931 12352 : if( pImp->bIsTemp && !pImp->m_aName.isEmpty() )
2932 : {
2933 1 : OUString aTemp;
2934 1 : if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->m_aName, aTemp ))
2935 : {
2936 : SAL_WARN( "sfx.doc", "Physical name not convertible!");
2937 : }
2938 :
2939 1 : if ( !::utl::UCBContentHelper::Kill( aTemp ) )
2940 : {
2941 : SAL_WARN( "sfx.doc", "Couldn't remove temporary file!");
2942 1 : }
2943 : }
2944 :
2945 12352 : delete pImp;
2946 17986 : }
2947 :
2948 126649 : const OUString& SfxMedium::GetName() const
2949 : {
2950 126649 : return pImp->m_aLogicName;
2951 : }
2952 :
2953 150476 : const INetURLObject& SfxMedium::GetURLObject() const
2954 : {
2955 150476 : if (!pImp->m_pURLObj)
2956 : {
2957 10640 : pImp->m_pURLObj = new INetURLObject( pImp->m_aLogicName );
2958 10640 : pImp->m_pURLObj->SetMark("");
2959 : }
2960 :
2961 150476 : return *pImp->m_pURLObj;
2962 : }
2963 :
2964 0 : void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
2965 : {
2966 0 : pImp->aExpireTime = rDateTime;
2967 0 : }
2968 :
2969 :
2970 0 : bool SfxMedium::IsExpired() const
2971 : {
2972 0 : return pImp->aExpireTime.IsValidAndGregorian() && pImp->aExpireTime < DateTime( DateTime::SYSTEM );
2973 : }
2974 :
2975 :
2976 1 : void SfxMedium::ForceSynchronStream_Impl( bool bForce )
2977 : {
2978 1 : if( pImp->m_pInStream )
2979 : {
2980 1 : SvLockBytes* pBytes = pImp->m_pInStream->GetLockBytes();
2981 1 : if( pBytes )
2982 1 : pBytes->SetSynchronMode( bForce );
2983 : }
2984 1 : }
2985 :
2986 :
2987 0 : SfxFrame* SfxMedium::GetLoadTargetFrame() const
2988 : {
2989 0 : return pImp->wLoadTargetFrame;
2990 : }
2991 :
2992 5005 : void SfxMedium::setStreamToLoadFrom(const com::sun::star::uno::Reference<com::sun::star::io::XInputStream>& xInputStream, bool bIsReadOnly )
2993 : {
2994 5005 : pImp->m_xInputStreamToLoadFrom = xInputStream;
2995 5005 : pImp->m_bInputStreamIsReadOnly = bIsReadOnly;
2996 5005 : }
2997 :
2998 0 : void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
2999 : {
3000 0 : pImp->wLoadTargetFrame = pFrame;
3001 0 : }
3002 :
3003 :
3004 4 : void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
3005 : {
3006 4 : pImp->xStorage = rStor;
3007 4 : }
3008 :
3009 :
3010 435811 : SfxItemSet* SfxMedium::GetItemSet() const
3011 : {
3012 : // this method *must* return an ItemSet, returning NULL can cause crashes
3013 435811 : if (!pImp->m_pSet)
3014 9024 : pImp->m_pSet = new SfxAllItemSet( SfxGetpApp()->GetPool() );
3015 435811 : return pImp->m_pSet;
3016 : }
3017 :
3018 :
3019 2964 : SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
3020 : {
3021 2964 : if( !pImp->xAttributes.Is() )
3022 : {
3023 2964 : pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
3024 :
3025 2964 : if ( GetContent().is() )
3026 : {
3027 : try
3028 : {
3029 2949 : Any aAny = pImp->aContent.getPropertyValue("MediaType");
3030 5898 : OUString aContentType;
3031 2949 : aAny >>= aContentType;
3032 :
3033 5898 : pImp->xAttributes->Append( SvKeyValue( OUString("content-type"), aContentType ) );
3034 : }
3035 0 : catch ( const ::com::sun::star::uno::Exception& )
3036 : {
3037 : }
3038 : }
3039 : }
3040 :
3041 2964 : return pImp->xAttributes;
3042 : }
3043 :
3044 669 : ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SfxMedium::GetInputStream()
3045 : {
3046 669 : if ( !pImp->xInputStream.is() )
3047 390 : GetMedium_Impl();
3048 669 : return pImp->xInputStream;
3049 : }
3050 :
3051 2471 : const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
3052 : {
3053 : // if the medium has no name, then this medium should represent a new document and can have no version info
3054 9884 : if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
3055 12355 : ( !pImp->m_aName.isEmpty() || !pImp->m_aLogicName.isEmpty() ) && GetStorage().is() )
3056 : {
3057 : uno::Reference < document::XDocumentRevisionListPersistence > xReader =
3058 2471 : document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3059 : try
3060 : {
3061 2471 : pImp->aVersions = xReader->load( GetStorage() );
3062 : }
3063 0 : catch ( const uno::Exception& )
3064 : {
3065 2471 : }
3066 : }
3067 :
3068 2471 : if ( !pImp->m_bVersionsAlreadyLoaded )
3069 2334 : pImp->m_bVersionsAlreadyLoaded = true;
3070 :
3071 2471 : return pImp->aVersions;
3072 : }
3073 :
3074 0 : uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
3075 : {
3076 : uno::Reference < document::XDocumentRevisionListPersistence > xReader =
3077 0 : document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3078 : try
3079 : {
3080 0 : return xReader->load( xStorage );
3081 : }
3082 0 : catch ( const uno::Exception& )
3083 : {
3084 : }
3085 :
3086 0 : return uno::Sequence < util::RevisionTag >();
3087 : }
3088 :
3089 0 : sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
3090 : {
3091 0 : if ( GetStorage().is() )
3092 : {
3093 : // To determine a unique name for the stream
3094 0 : std::vector<sal_uInt32> aLongs;
3095 0 : sal_Int32 nLength = pImp->aVersions.getLength();
3096 0 : for ( sal_Int32 m=0; m<nLength; m++ )
3097 : {
3098 0 : sal_uInt32 nVer = static_cast<sal_uInt32>( pImp->aVersions[m].Identifier.copy(7).toInt32());
3099 : size_t n;
3100 0 : for ( n=0; n<aLongs.size(); ++n )
3101 0 : if ( nVer<aLongs[n] )
3102 0 : break;
3103 :
3104 0 : aLongs.insert( aLongs.begin()+n, nVer );
3105 : }
3106 :
3107 : sal_uInt16 nKey;
3108 0 : for ( nKey=0; nKey<aLongs.size(); ++nKey )
3109 0 : if ( aLongs[nKey] > ( sal_uIntPtr ) nKey+1 )
3110 0 : break;
3111 :
3112 0 : OUString aRevName = "Version" + OUString::number( nKey + 1 );
3113 0 : pImp->aVersions.realloc( nLength+1 );
3114 0 : rRevision.Identifier = aRevName;
3115 0 : pImp->aVersions[nLength] = rRevision;
3116 0 : return nKey;
3117 : }
3118 :
3119 0 : return 0;
3120 : }
3121 :
3122 0 : bool SfxMedium::RemoveVersion_Impl( const OUString& rName )
3123 : {
3124 0 : if ( !pImp->aVersions.getLength() )
3125 0 : return false;
3126 :
3127 0 : sal_Int32 nLength = pImp->aVersions.getLength();
3128 0 : for ( sal_Int32 n=0; n<nLength; n++ )
3129 : {
3130 0 : if ( pImp->aVersions[n].Identifier == rName )
3131 : {
3132 0 : for ( sal_Int32 m=n; m<nLength-1; m++ )
3133 0 : pImp->aVersions[m] = pImp->aVersions[m+1];
3134 0 : pImp->aVersions.realloc(nLength-1);
3135 0 : return true;
3136 : }
3137 : }
3138 :
3139 0 : return false;
3140 : }
3141 :
3142 831 : bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
3143 : {
3144 831 : if ( rMedium.pImp->aVersions.getLength() )
3145 : {
3146 1 : pImp->aVersions = rMedium.pImp->aVersions;
3147 1 : return true;
3148 : }
3149 :
3150 830 : return false;
3151 : }
3152 :
3153 101 : bool SfxMedium::SaveVersionList_Impl( bool /*bUseXML*/ )
3154 : {
3155 101 : if ( GetStorage().is() )
3156 : {
3157 101 : if ( !pImp->aVersions.getLength() )
3158 202 : return true;
3159 :
3160 : uno::Reference < document::XDocumentRevisionListPersistence > xWriter =
3161 0 : document::DocumentRevisionListPersistence::create( comphelper::getProcessComponentContext() );
3162 : try
3163 : {
3164 0 : xWriter->store( GetStorage(), pImp->aVersions );
3165 0 : return true;
3166 : }
3167 0 : catch ( const uno::Exception& )
3168 : {
3169 0 : }
3170 : }
3171 :
3172 0 : return false;
3173 : }
3174 :
3175 23131 : bool SfxMedium::IsReadOnly() const
3176 : {
3177 : // a) ReadOnly filter can't produce read/write contents!
3178 23131 : bool bReadOnly = pImp->m_pFilter && (pImp->m_pFilter->GetFilterFlags() & SfxFilterFlags::OPENREADONLY);
3179 :
3180 : // b) if filter allow read/write contents .. check open mode of the storage
3181 23131 : if (!bReadOnly)
3182 23131 : bReadOnly = !( GetOpenMode() & StreamMode::WRITE );
3183 :
3184 : // c) the API can force the readonly state!
3185 23131 : if (!bReadOnly)
3186 : {
3187 21375 : SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, false);
3188 21375 : if (pItem)
3189 45 : bReadOnly = pItem->GetValue();
3190 : }
3191 :
3192 23131 : return bReadOnly;
3193 : }
3194 :
3195 0 : bool SfxMedium::IsOriginallyReadOnly() const
3196 : {
3197 0 : return pImp->m_bOriginallyReadOnly;
3198 : }
3199 :
3200 :
3201 2731 : bool SfxMedium::SetWritableForUserOnly( const OUString& aURL )
3202 : {
3203 : // UCB does not allow to allow write access only for the user,
3204 : // use osl API
3205 2731 : bool bResult = false;
3206 :
3207 2731 : ::osl::DirectoryItem aDirItem;
3208 2731 : if ( ::osl::DirectoryItem::get( aURL, aDirItem ) == ::osl::FileBase::E_None )
3209 : {
3210 2731 : ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_Attributes );
3211 5462 : if ( aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None
3212 2731 : && aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
3213 : {
3214 2731 : sal_uInt64 nAttributes = aFileStatus.getAttributes();
3215 :
3216 : nAttributes &= ~(osl_File_Attribute_OwnWrite |
3217 : osl_File_Attribute_GrpWrite |
3218 : osl_File_Attribute_OthWrite |
3219 2731 : osl_File_Attribute_ReadOnly);
3220 : nAttributes |= (osl_File_Attribute_OwnWrite |
3221 2731 : osl_File_Attribute_OwnRead);
3222 :
3223 2731 : bResult = ( osl::File::setAttributes( aURL, nAttributes ) == ::osl::FileBase::E_None );
3224 2731 : }
3225 : }
3226 :
3227 2731 : return bResult;
3228 : }
3229 :
3230 :
3231 13657 : void SfxMedium::CreateTempFile( bool bReplace )
3232 : {
3233 13657 : if ( pImp->pTempFile )
3234 : {
3235 5231 : if ( !bReplace )
3236 10460 : return;
3237 :
3238 1 : DELETEZ( pImp->pTempFile );
3239 1 : pImp->m_aName.clear();
3240 : }
3241 :
3242 8427 : pImp->pTempFile = new ::utl::TempFile();
3243 8427 : pImp->pTempFile->EnableKillingFile( true );
3244 8427 : pImp->m_aName = pImp->pTempFile->GetFileName();
3245 8427 : OUString aTmpURL = pImp->pTempFile->GetURL();
3246 8427 : if ( pImp->m_aName.isEmpty() || aTmpURL.isEmpty() )
3247 : {
3248 0 : SetError( ERRCODE_IO_CANTWRITE, OUString( OSL_LOG_PREFIX ) );
3249 0 : return;
3250 : }
3251 :
3252 8427 : if ( !(pImp->m_nStorOpenMode & StreamMode::TRUNC) )
3253 : {
3254 7780 : bool bTransferSuccess = false;
3255 :
3256 31120 : if ( GetContent().is()
3257 15560 : && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
3258 33859 : && ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
3259 : {
3260 : // if there is already such a document, we should copy it
3261 : // if it is a file system use OS copy process
3262 : try
3263 : {
3264 2733 : uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
3265 5466 : INetURLObject aTmpURLObj( aTmpURL );
3266 : OUString aFileName = aTmpURLObj.getName( INetURLObject::LAST_SEGMENT,
3267 : true,
3268 5466 : INetURLObject::DECODE_WITH_CHARSET );
3269 2733 : if ( !aFileName.isEmpty() && aTmpURLObj.removeSegment() )
3270 : {
3271 2733 : ::ucbhelper::Content aTargetContent( aTmpURLObj.GetMainURL( INetURLObject::NO_DECODE ), xComEnv, comphelper::getProcessComponentContext() );
3272 5466 : OUString sMimeType = pImp->getFilterMimeType();
3273 2735 : if ( aTargetContent.transferContent( pImp->aContent, ::ucbhelper::InsertOperation_COPY, aFileName, NameClash::OVERWRITE, sMimeType ) )
3274 : {
3275 2731 : SetWritableForUserOnly( aTmpURL );
3276 2731 : bTransferSuccess = true;
3277 2733 : }
3278 2733 : }
3279 : }
3280 2 : catch( const uno::Exception& )
3281 : {}
3282 :
3283 2733 : if ( bTransferSuccess )
3284 : {
3285 2731 : CloseOutStream();
3286 2731 : CloseInStream();
3287 : }
3288 : }
3289 :
3290 7780 : if ( !bTransferSuccess && pImp->m_pInStream )
3291 : {
3292 : // the case when there is no URL-access available or this is a remote protocoll
3293 : // but there is an input stream
3294 5041 : GetOutStream();
3295 5041 : if ( pImp->m_pOutStream )
3296 : {
3297 5041 : char *pBuf = new char [8192];
3298 5041 : sal_uInt32 nErr = ERRCODE_NONE;
3299 :
3300 5041 : pImp->m_pInStream->Seek(0);
3301 5041 : pImp->m_pOutStream->Seek(0);
3302 :
3303 103135 : while( !pImp->m_pInStream->IsEof() && nErr == ERRCODE_NONE )
3304 : {
3305 93053 : sal_uInt32 nRead = pImp->m_pInStream->Read( pBuf, 8192 );
3306 93053 : nErr = pImp->m_pInStream->GetError();
3307 93053 : pImp->m_pOutStream->Write( pBuf, nRead );
3308 : }
3309 :
3310 5041 : bTransferSuccess = true;
3311 5041 : delete[] pBuf;
3312 5041 : CloseInStream();
3313 : }
3314 5041 : CloseOutStream_Impl();
3315 : }
3316 : else
3317 : {
3318 : // Quite strange design, but currently it is expected that in this case no transfer happens
3319 : // TODO/LATER: get rid of this inconsistent part of the call design
3320 2739 : bTransferSuccess = true;
3321 2739 : CloseInStream();
3322 : }
3323 :
3324 7780 : if ( !bTransferSuccess )
3325 : {
3326 0 : SetError( ERRCODE_IO_CANTWRITE, OUString( OSL_LOG_PREFIX ) );
3327 0 : return;
3328 : }
3329 : }
3330 :
3331 8427 : CloseStorage();
3332 : }
3333 :
3334 :
3335 235 : void SfxMedium::CreateTempFileNoCopy()
3336 : {
3337 : // this call always replaces the existing temporary file
3338 235 : if ( pImp->pTempFile )
3339 47 : delete pImp->pTempFile;
3340 :
3341 235 : pImp->pTempFile = new ::utl::TempFile();
3342 235 : pImp->pTempFile->EnableKillingFile( true );
3343 235 : pImp->m_aName = pImp->pTempFile->GetFileName();
3344 235 : if ( pImp->m_aName.isEmpty() )
3345 : {
3346 0 : SetError( ERRCODE_IO_CANTWRITE, OUString( OSL_LOG_PREFIX ) );
3347 235 : return;
3348 : }
3349 :
3350 235 : CloseOutStream_Impl();
3351 235 : CloseStorage();
3352 : }
3353 :
3354 0 : bool SfxMedium::SignContents_Impl( bool bScriptingContent, const OUString& aODFVersion, bool bHasValidDocumentSignature )
3355 : {
3356 0 : bool bChanges = false;
3357 :
3358 : // the medium should be closed to be able to sign, the caller is responsible to close it
3359 0 : if ( !IsOpen() && !GetError() )
3360 : {
3361 : // The component should know if there was a valid document signature, since
3362 : // it should show a warning in this case
3363 : uno::Reference< security::XDocumentDigitalSignatures > xSigner(
3364 : security::DocumentDigitalSignatures::createWithVersionAndValidSignature(
3365 0 : comphelper::getProcessComponentContext(), aODFVersion, bHasValidDocumentSignature ) );
3366 :
3367 0 : uno::Reference< embed::XStorage > xWriteableZipStor;
3368 0 : if ( !IsReadOnly() )
3369 : {
3370 : // we can reuse the temporary file if there is one already
3371 0 : CreateTempFile( false );
3372 0 : GetMedium_Impl();
3373 :
3374 : try
3375 : {
3376 0 : if ( !pImp->xStream.is() )
3377 0 : throw uno::RuntimeException();
3378 :
3379 0 : xWriteableZipStor = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream );
3380 0 : if ( !xWriteableZipStor.is() )
3381 0 : throw uno::RuntimeException();
3382 :
3383 0 : uno::Reference< embed::XStorage > xMetaInf = xWriteableZipStor->openStorageElement(
3384 : OUString( "META-INF" ),
3385 0 : embed::ElementModes::READWRITE );
3386 0 : if ( !xMetaInf.is() )
3387 0 : throw uno::RuntimeException();
3388 :
3389 0 : if ( bScriptingContent )
3390 : {
3391 : // If the signature has already the document signature it will be removed
3392 : // after the scripting signature is inserted.
3393 : uno::Reference< io::XStream > xStream(
3394 0 : xMetaInf->openStreamElement( xSigner->getScriptingContentSignatureDefaultStreamName(),
3395 0 : embed::ElementModes::READWRITE ),
3396 0 : uno::UNO_SET_THROW );
3397 :
3398 0 : if ( xSigner->signScriptingContent( GetZipStorageToSign_Impl(), xStream ) )
3399 : {
3400 : // remove the document signature if any
3401 0 : OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName();
3402 0 : if ( !aDocSigName.isEmpty() && xMetaInf->hasByName( aDocSigName ) )
3403 0 : xMetaInf->removeElement( aDocSigName );
3404 :
3405 0 : uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3406 0 : xTransact->commit();
3407 0 : xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3408 0 : xTransact->commit();
3409 :
3410 : // the temporary file has been written, commit it to the original file
3411 0 : Commit();
3412 0 : bChanges = true;
3413 0 : }
3414 : }
3415 : else
3416 : {
3417 : uno::Reference< io::XStream > xStream(
3418 0 : xMetaInf->openStreamElement( xSigner->getDocumentContentSignatureDefaultStreamName(),
3419 0 : embed::ElementModes::READWRITE ),
3420 0 : uno::UNO_SET_THROW );
3421 :
3422 0 : if ( xSigner->signDocumentContent( GetZipStorageToSign_Impl(), xStream ) )
3423 : {
3424 0 : uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
3425 0 : xTransact->commit();
3426 0 : xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
3427 0 : xTransact->commit();
3428 :
3429 : // the temporary file has been written, commit it to the original file
3430 0 : Commit();
3431 0 : bChanges = true;
3432 0 : }
3433 0 : }
3434 : }
3435 0 : catch ( const uno::Exception& )
3436 : {
3437 : SAL_WARN( "sfx.doc", "Couldn't use signing functionality!\n" );
3438 : }
3439 :
3440 0 : CloseAndRelease();
3441 : }
3442 : else
3443 : {
3444 : try
3445 : {
3446 0 : if ( bScriptingContent )
3447 0 : xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
3448 : else
3449 0 : xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
3450 : }
3451 0 : catch( const uno::Exception& )
3452 : {
3453 : SAL_WARN( "sfx.doc", "Couldn't use signing functionality!\n" );
3454 : }
3455 : }
3456 :
3457 0 : ResetError();
3458 : }
3459 :
3460 0 : return bChanges;
3461 : }
3462 :
3463 :
3464 609 : SignatureState SfxMedium::GetCachedSignatureState_Impl()
3465 : {
3466 609 : return pImp->m_nSignatureState;
3467 : }
3468 :
3469 :
3470 609 : void SfxMedium::SetCachedSignatureState_Impl( SignatureState nState )
3471 : {
3472 609 : pImp->m_nSignatureState = nState;
3473 609 : }
3474 :
3475 5373 : bool SfxMedium::HasStorage_Impl() const
3476 : {
3477 5373 : return pImp->xStorage.is();
3478 : }
3479 :
3480 0 : bool SfxMedium::IsOpen() const
3481 : {
3482 0 : return pImp->m_pInStream || pImp->m_pOutStream || pImp->xStorage.is();
3483 : }
3484 :
3485 0 : OUString SfxMedium::CreateTempCopyWithExt( const OUString& aURL )
3486 : {
3487 0 : OUString aResult;
3488 :
3489 0 : if ( !aURL.isEmpty() )
3490 : {
3491 0 : sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
3492 0 : OUString aExt = ( nPrefixLen == -1 ) ? OUString() : aURL.copy( nPrefixLen );
3493 :
3494 0 : OUString aNewTempFileURL = ::utl::TempFile( OUString(), true, &aExt ).GetURL();
3495 0 : if ( !aNewTempFileURL.isEmpty() )
3496 : {
3497 0 : INetURLObject aSource( aURL );
3498 0 : INetURLObject aDest( aNewTempFileURL );
3499 : OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
3500 : true,
3501 0 : INetURLObject::DECODE_WITH_CHARSET );
3502 0 : if ( !aFileName.isEmpty() && aDest.removeSegment() )
3503 : {
3504 : try
3505 : {
3506 0 : uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
3507 0 : ::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv, comphelper::getProcessComponentContext() );
3508 0 : ::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv, comphelper::getProcessComponentContext() );
3509 0 : if ( aTargetContent.transferContent( aSourceContent,
3510 : ::ucbhelper::InsertOperation_COPY,
3511 : aFileName,
3512 0 : NameClash::OVERWRITE ) )
3513 : {
3514 : // Success
3515 0 : aResult = aNewTempFileURL;
3516 0 : }
3517 : }
3518 0 : catch( const uno::Exception& )
3519 : {}
3520 0 : }
3521 0 : }
3522 : }
3523 :
3524 0 : return aResult;
3525 : }
3526 :
3527 0 : bool SfxMedium::CallApproveHandler(const uno::Reference< task::XInteractionHandler >& xHandler, const uno::Any& rRequest, bool bAllowAbort)
3528 : {
3529 0 : bool bResult = false;
3530 :
3531 0 : if ( xHandler.is() )
3532 : {
3533 : try
3534 : {
3535 0 : uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( bAllowAbort ? 2 : 1 );
3536 :
3537 0 : ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
3538 0 : aContinuations[ 0 ] = pApprove.get();
3539 :
3540 0 : if ( bAllowAbort )
3541 : {
3542 0 : ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
3543 0 : aContinuations[ 1 ] = pAbort.get();
3544 : }
3545 :
3546 0 : xHandler->handle(::framework::InteractionRequest::CreateRequest(rRequest, aContinuations));
3547 0 : bResult = pApprove->wasSelected();
3548 : }
3549 0 : catch( const Exception& )
3550 : {
3551 : }
3552 : }
3553 :
3554 0 : return bResult;
3555 : }
3556 :
3557 0 : OUString SfxMedium::SwitchDocumentToTempFile()
3558 : {
3559 : // the method returns empty string in case of failure
3560 0 : OUString aResult;
3561 0 : OUString aOrigURL = pImp->m_aLogicName;
3562 :
3563 0 : if ( !aOrigURL.isEmpty() )
3564 : {
3565 0 : sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
3566 : OUString const aExt = (nPrefixLen == -1)
3567 : ? OUString()
3568 0 : : aOrigURL.copy(nPrefixLen);
3569 0 : OUString aNewURL = ::utl::TempFile( OUString(), true, &aExt ).GetURL();
3570 :
3571 : // TODO/LATER: In future the aLogicName should be set to shared folder URL
3572 : // and a temporary file should be created. Transport_Impl should be impossible then.
3573 0 : if ( !aNewURL.isEmpty() )
3574 : {
3575 0 : uno::Reference< embed::XStorage > xStorage = GetStorage();
3576 0 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
3577 :
3578 0 : if ( xOptStorage.is() )
3579 : {
3580 : // TODO/LATER: reuse the pImp->pTempFile if it already exists
3581 0 : CanDisposeStorage_Impl( false );
3582 0 : Close();
3583 0 : SetPhysicalName_Impl( OUString() );
3584 0 : SetName( aNewURL );
3585 :
3586 : // remove the readonly state
3587 0 : bool bWasReadonly = false;
3588 0 : pImp->m_nStorOpenMode = SFX_STREAM_READWRITE;
3589 0 : SFX_ITEMSET_ARG( pImp->m_pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, false );
3590 0 : if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
3591 0 : bWasReadonly = true;
3592 0 : GetItemSet()->ClearItem( SID_DOC_READONLY );
3593 :
3594 0 : GetMedium_Impl();
3595 0 : LockOrigFileOnDemand( false, false );
3596 0 : CreateTempFile( true );
3597 0 : GetMedium_Impl();
3598 :
3599 0 : if ( pImp->xStream.is() )
3600 : {
3601 : try
3602 : {
3603 0 : xOptStorage->writeAndAttachToStream( pImp->xStream );
3604 0 : pImp->xStorage = xStorage;
3605 0 : aResult = aNewURL;
3606 : }
3607 0 : catch( const uno::Exception& )
3608 : {}
3609 : }
3610 :
3611 0 : if ( aResult.isEmpty() )
3612 : {
3613 0 : Close();
3614 0 : SetPhysicalName_Impl( OUString() );
3615 0 : SetName( aOrigURL );
3616 0 : if ( bWasReadonly )
3617 : {
3618 : // set the readonly state back
3619 0 : pImp->m_nStorOpenMode = SFX_STREAM_READONLY;
3620 0 : GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, true));
3621 : }
3622 0 : GetMedium_Impl();
3623 0 : pImp->xStorage = xStorage;
3624 : }
3625 0 : }
3626 0 : }
3627 : }
3628 :
3629 0 : return aResult;
3630 : }
3631 :
3632 0 : bool SfxMedium::SwitchDocumentToFile( const OUString& aURL )
3633 : {
3634 : // the method is only for storage based documents
3635 0 : bool bResult = false;
3636 0 : OUString aOrigURL = pImp->m_aLogicName;
3637 :
3638 0 : if ( !aURL.isEmpty() && !aOrigURL.isEmpty() )
3639 : {
3640 0 : uno::Reference< embed::XStorage > xStorage = GetStorage();
3641 0 : uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
3642 :
3643 0 : if ( xOptStorage.is() )
3644 : {
3645 : // TODO/LATER: reuse the pImp->pTempFile if it already exists
3646 0 : CanDisposeStorage_Impl( false );
3647 0 : Close();
3648 0 : SetPhysicalName_Impl( OUString() );
3649 0 : SetName( aURL );
3650 :
3651 : // open the temporary file based document
3652 0 : GetMedium_Impl();
3653 0 : LockOrigFileOnDemand( false, false );
3654 0 : CreateTempFile( true );
3655 0 : GetMedium_Impl();
3656 :
3657 0 : if ( pImp->xStream.is() )
3658 : {
3659 : try
3660 : {
3661 0 : uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
3662 0 : if ( xTruncate.is() )
3663 0 : xTruncate->truncate();
3664 :
3665 0 : xOptStorage->writeAndAttachToStream( pImp->xStream );
3666 0 : pImp->xStorage = xStorage;
3667 0 : bResult = true;
3668 : }
3669 0 : catch( const uno::Exception& )
3670 : {}
3671 : }
3672 :
3673 0 : if ( !bResult )
3674 : {
3675 0 : Close();
3676 0 : SetPhysicalName_Impl( OUString() );
3677 0 : SetName( aOrigURL );
3678 0 : GetMedium_Impl();
3679 0 : pImp->xStorage = xStorage;
3680 : }
3681 0 : }
3682 : }
3683 :
3684 0 : return bResult;
3685 : }
3686 :
3687 6 : void SfxMedium::SetInCheckIn( bool bInCheckIn )
3688 : {
3689 6 : pImp->m_bInCheckIn = bInCheckIn;
3690 6 : }
3691 :
3692 105 : bool SfxMedium::IsInCheckIn( )
3693 : {
3694 105 : return pImp->m_bInCheckIn;
3695 : }
3696 :
3697 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|