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