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