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