1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uno/Reference.h>
21 #include <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/frame/FrameSearchFlag.hpp>
23 #include <com/sun/star/frame/XComponentLoader.hpp>
24 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
25 #include <com/sun/star/frame/XDispatchProvider.hpp>
26 #include <com/sun/star/util/XCloseable.hpp>
27 #include <com/sun/star/frame/XFrame.hpp>
28 #include <com/sun/star/frame/Desktop.hpp>
29 #include <com/sun/star/frame/DispatchResultState.hpp>
30 #include <com/sun/star/frame/XDispatchResultListener.hpp>
31 #include <com/sun/star/util/URL.hpp>
32 #include <com/sun/star/util/URLTransformer.hpp>
33 #include <com/sun/star/util/XURLTransformer.hpp>
34 #include <com/sun/star/system/SystemShellExecuteException.hpp>
35 #include <com/sun/star/document/XTypeDetection.hpp>
36 #include <com/sun/star/document/MacroExecMode.hpp>
37 #include <com/sun/star/document/UpdateDocMode.hpp>
38 #include <com/sun/star/task/ErrorCodeRequest.hpp>
39 #include <com/sun/star/task/InteractionHandler.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/embed/ElementModes.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/uno/Sequence.h>
44 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
45 #include <cppuhelper/implbase1.hxx>
46 #include <rtl/ustring.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <comphelper/sequenceasvector.hxx>
50 #include <comphelper/storagehelper.hxx>
51 #include <comphelper/string.hxx>
52 #include <comphelper/synchronousdispatch.hxx>
54 #include <vcl/wrkwin.hxx>
55 #include <svl/intitem.hxx>
56 #include <vcl/msgbox.hxx>
57 #include <svl/stritem.hxx>
58 #include <svl/eitem.hxx>
59 #include <sfx2/doctempl.hxx>
60 #include <svtools/sfxecode.hxx>
61 #include <framework/preventduplicateinteraction.hxx>
62 #include <svtools/ehdl.hxx>
63 #include <basic/sbxobj.hxx>
64 #include <svl/urihelper.hxx>
65 #include <unotools/localfilehelper.hxx>
66 #include <unotools/pathoptions.hxx>
67 #include <unotools/moduleoptions.hxx>
68 #include <svtools/miscopt.hxx>
69 #include <svtools/templdlg.hxx>
70 #include <osl/file.hxx>
71 #include <unotools/extendedsecurityoptions.hxx>
72 #include <comphelper/docpasswordhelper.hxx>
73 #include <vcl/svapp.hxx>
75 #include <osl/mutex.hxx>
78 #include <sfx2/app.hxx>
79 #include <sfx2/bindings.hxx>
80 #include <sfx2/dispatch.hxx>
81 #include <sfx2/docfile.hxx>
82 #include <sfx2/fcontnr.hxx>
83 #include <sfx2/new.hxx>
84 #include <sfx2/objitem.hxx>
85 #include <sfx2/objsh.hxx>
86 #include <svl/slstitm.hxx>
87 #include "objshimp.hxx"
88 #include "openflag.hxx"
89 #include <sfx2/passwd.hxx>
90 #include <sfx2/request.hxx>
91 #include <sfx2/sfxresid.hxx>
92 #include <sfx2/viewsh.hxx>
94 #include <sfx2/viewfrm.hxx>
95 #include <sfx2/sfxuno.hxx>
96 #include <sfx2/objface.hxx>
97 #include <sfx2/filedlghelper.hxx>
98 #include <sfx2/docfac.hxx>
99 #include <sfx2/event.hxx>
100 #include "templatedlg.hxx"
101 #include "openuriexternally.hxx"
103 #include <officecfg/Office/ProtocolHandler.hxx>
105 using namespace ::com::sun::star
;
106 using namespace ::com::sun::star::beans
;
107 using namespace ::com::sun::star::frame
;
108 using namespace ::com::sun::star::lang
;
109 using namespace ::com::sun::star::uno
;
110 using namespace ::com::sun::star::util
;
111 using namespace ::com::sun::star::task
;
112 using namespace ::com::sun::star::container
;
113 using namespace ::cppu
;
114 using namespace ::sfx2
;
116 //=========================================================================
118 class SfxOpenDocStatusListener_Impl
: public WeakImplHelper1
< XDispatchResultListener
>
123 virtual void SAL_CALL
dispatchFinished( const DispatchResultEvent
& Event
) throw(RuntimeException
);
124 virtual void SAL_CALL
disposing( const EventObject
& Source
) throw(RuntimeException
);
125 SfxOpenDocStatusListener_Impl()
126 : bFinished( sal_False
)
127 , bSuccess( sal_False
)
131 void SAL_CALL
SfxOpenDocStatusListener_Impl::dispatchFinished( const DispatchResultEvent
& aEvent
) throw(RuntimeException
)
133 bSuccess
= ( aEvent
.State
== DispatchResultState::SUCCESS
);
134 bFinished
= sal_True
;
137 void SAL_CALL
SfxOpenDocStatusListener_Impl::disposing( const EventObject
& ) throw(RuntimeException
)
141 //====================================================================
143 void SetTemplate_Impl( const OUString
&rFileName
,
144 const OUString
&rLongName
,
145 SfxObjectShell
*pDoc
)
147 // write TemplateName to DocumentProperties of document
148 // TemplateDate stays as default (=current date)
149 pDoc
->ResetFromTemplate( rLongName
, rFileName
);
152 //====================================================================
153 class SfxDocPasswordVerifier
: public ::comphelper::IDocPasswordVerifier
156 inline explicit SfxDocPasswordVerifier( const Reference
< embed::XStorage
>& rxStorage
) :
157 mxStorage( rxStorage
) {}
159 virtual ::comphelper::DocPasswordVerifierResult
160 verifyPassword( const OUString
& rPassword
, uno::Sequence
< beans::NamedValue
>& o_rEncryptionData
);
161 virtual ::comphelper::DocPasswordVerifierResult
162 verifyEncryptionData( const uno::Sequence
< beans::NamedValue
>& rEncryptionData
);
166 Reference
< embed::XStorage
> mxStorage
;
169 //--------------------------------------------------------------------
170 ::comphelper::DocPasswordVerifierResult
SfxDocPasswordVerifier::verifyPassword( const OUString
& rPassword
, uno::Sequence
< beans::NamedValue
>& o_rEncryptionData
)
172 o_rEncryptionData
= ::comphelper::OStorageHelper::CreatePackageEncryptionData( rPassword
);
173 return verifyEncryptionData( o_rEncryptionData
);
177 //--------------------------------------------------------------------
178 ::comphelper::DocPasswordVerifierResult
SfxDocPasswordVerifier::verifyEncryptionData( const uno::Sequence
< beans::NamedValue
>& rEncryptionData
)
180 ::comphelper::DocPasswordVerifierResult eResult
= ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD
;
183 // check the encryption data
184 // if the data correct is the stream will be opened successfully
185 // and immediatelly closed
186 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( mxStorage
, rEncryptionData
);
188 mxStorage
->openStreamElement(
189 OUString( "content.xml" ),
190 embed::ElementModes::READ
| embed::ElementModes::NOCREATE
);
192 // no exception -> success
193 eResult
= ::comphelper::DocPasswordVerifierResult_OK
;
195 catch( const packages::WrongPasswordException
& )
197 eResult
= ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD
;
199 catch( const uno::Exception
& )
201 // unknown error, report it as wrong password
202 // TODO/LATER: we need an additional way to report unknown problems in this case
203 eResult
= ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD
;
208 //====================================================================
210 //--------------------------------------------------------------------
212 sal_uInt32 CheckPasswd_Impl
214 SfxObjectShell
* pDoc
,
215 SfxItemPool
& /*rPool*/, // Pool, if a Set has to be created
216 SfxMedium
* pFile
// the Medium and its Password shold be obtained
221 Ask for the password for a medium, only works if it concerns storage.
222 If the password flag is set in the Document Info, then the password is
223 requested through a user dialogue and the set at the Set of the medium.
224 If the set does not exist the it is created.
227 sal_uIntPtr nRet
= ERRCODE_NONE
;
229 if( ( !pFile
->GetFilter() || pFile
->IsStorage() ) )
231 uno::Reference
< embed::XStorage
> xStorage
= pFile
->GetStorage( sal_True
);
234 uno::Reference
< beans::XPropertySet
> xStorageProps( xStorage
, uno::UNO_QUERY
);
235 if ( xStorageProps
.is() )
237 sal_Bool bIsEncrypted
= sal_False
;
239 xStorageProps
->getPropertyValue("HasEncryptedEntries")
241 } catch( uno::Exception
& )
244 // the storage either has no encrypted elements or it's just
245 // does not allow to detect it, probably it should be implemented laiter
250 Window
* pWin
= pDoc
? pDoc
->GetDialogParent( pFile
) : NULL
;
254 nRet
= ERRCODE_SFX_CANTGETPASSWD
;
256 SfxItemSet
*pSet
= pFile
->GetItemSet();
259 Reference
< ::com::sun::star::task::XInteractionHandler
> xInteractionHandler
= pFile
->GetInteractionHandler();
260 if( xInteractionHandler
.is() )
262 // use the comphelper password helper to request a password
264 SFX_ITEMSET_ARG( pSet
, pPasswordItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
266 aPassword
= pPasswordItem
->GetValue();
268 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
269 SFX_ITEMSET_ARG( pSet
, pEncryptionDataItem
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, sal_False
);
270 if ( pEncryptionDataItem
)
271 pEncryptionDataItem
->GetValue() >>= aEncryptionData
;
273 OUString aDocumentName
= INetURLObject( pFile
->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET
);
275 SfxDocPasswordVerifier
aVerifier( xStorage
);
276 aEncryptionData
= ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
277 aVerifier
, aEncryptionData
, aPassword
, xInteractionHandler
, aDocumentName
, comphelper::DocPasswordRequestType_STANDARD
);
279 pSet
->ClearItem( SID_PASSWORD
);
280 pSet
->ClearItem( SID_ENCRYPTIONDATA
);
282 if ( aEncryptionData
.getLength() > 0 )
284 pSet
->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
288 // update the version list of the medium using the new password
289 pFile
->GetVersionList();
291 catch( uno::Exception
& )
293 // TODO/LATER: set the error code
299 nRet
= ERRCODE_IO_ABORT
;
306 OSL_FAIL( "A storage must implement XPropertySet interface!" );
307 nRet
= ERRCODE_SFX_CANTGETPASSWD
;
315 //--------------------------------------------------------------------
318 sal_uIntPtr
SfxApplication::LoadTemplate( SfxObjectShellLock
& xDoc
, const OUString
&rFileName
, sal_Bool bCopy
, SfxItemSet
* pSet
)
320 const SfxFilter
* pFilter
= NULL
;
321 SfxMedium
aMedium( rFileName
, ( STREAM_READ
| STREAM_SHARE_DENYNONE
) );
323 if ( !aMedium
.GetStorage( sal_False
).is() )
324 aMedium
.GetInStream();
326 if ( aMedium
.GetError() )
329 return aMedium
.GetErrorCode();
332 aMedium
.UseInteractionHandler( sal_True
);
333 sal_uIntPtr nErr
= GetFilterMatcher().GuessFilter( aMedium
,&pFilter
,SFX_FILTER_TEMPLATE
, 0 );
337 return ERRCODE_SFX_NOTATEMPLATE
;
340 if( !pFilter
|| !pFilter
->IsAllowedAsTemplate() )
343 return ERRCODE_SFX_NOTATEMPLATE
;
346 if ( pFilter
->GetFilterFlags() & SFX_FILTER_STARONEFILTER
)
348 DBG_ASSERT( !xDoc
.Is(), "Sorry, not implemented!" );
350 SfxStringItem
aName( SID_FILE_NAME
, rFileName
);
351 SfxStringItem
aReferer( SID_REFERER
, OUString("private:user") );
352 SfxStringItem
aFlags( SID_OPTIONS
, OUString("T") );
353 SfxBoolItem
aHidden( SID_HIDDEN
, sal_True
);
354 const SfxPoolItem
*pRet
= GetDispatcher_Impl()->Execute( SID_OPENDOC
, SFX_CALLMODE_SYNCHRON
, &aName
, &aHidden
, &aReferer
, &aFlags
, 0L );
355 const SfxObjectItem
*pObj
= PTR_CAST( SfxObjectItem
, pRet
);
357 xDoc
= PTR_CAST( SfxObjectShell
, pObj
->GetShell() );
360 const SfxViewFrameItem
*pView
= PTR_CAST( SfxViewFrameItem
, pRet
);
363 SfxViewFrame
*pFrame
= pView
->GetFrame();
365 xDoc
= pFrame
->GetObjectShell();
370 return ERRCODE_SFX_DOLOADFAILED
;
375 xDoc
= SfxObjectShell::CreateObject( pFilter
->GetServiceName() );
377 //pMedium takes ownership of pSet
378 SfxMedium
*pMedium
= new SfxMedium( rFileName
, STREAM_STD_READ
, pFilter
, pSet
);
379 if(!xDoc
->DoLoad(pMedium
))
381 ErrCode nErrCode
= xDoc
->GetErrorCode();
392 // TODO: introduce error handling
394 uno::Reference
< embed::XStorage
> xTempStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
395 if( !xTempStorage
.is() )
396 throw uno::RuntimeException();
398 xDoc
->GetStorage()->copyToStorage( xTempStorage
);
400 if ( !xDoc
->DoSaveCompleted( new SfxMedium( xTempStorage
, OUString() ) ) )
401 throw uno::RuntimeException();
403 catch( uno::Exception
& )
408 // TODO: transfer correct error outside
409 return ERRCODE_SFX_GENERAL
;
412 SetTemplate_Impl( rFileName
, OUString(), xDoc
);
415 SetTemplate_Impl( rFileName
, OUString(), xDoc
);
418 xDoc
->InvalidateName();
419 xDoc
->SetModified(sal_False
);
422 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
> xModel ( xDoc
->GetModel(), ::com::sun::star::uno::UNO_QUERY
);
425 SfxItemSet
* pNew
= xDoc
->GetMedium()->GetItemSet()->Clone();
426 pNew
->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
427 pNew
->ClearItem( SID_FILTER_NAME
);
428 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
> aArgs
;
429 TransformItems( SID_OPENDOC
, *pNew
, aArgs
);
430 sal_Int32 nLength
= aArgs
.getLength();
431 aArgs
.realloc( nLength
+ 1 );
432 aArgs
[nLength
].Name
= "Title";
433 aArgs
[nLength
].Value
<<= OUString( xDoc
->GetTitle( SFX_TITLE_DETECT
) );
434 xModel
->attachResource( OUString(), aArgs
);
438 return xDoc
->GetErrorCode();
441 //--------------------------------------------------------------------
443 void SfxApplication::NewDocDirectExec_Impl( SfxRequest
& rReq
)
445 SFX_REQUEST_ARG( rReq
, pFactoryItem
, SfxStringItem
, SID_NEWDOCDIRECT
, sal_False
);
448 aFactName
= pFactoryItem
->GetValue();
450 aFactName
= SvtModuleOptions().GetDefaultModuleName();
453 SfxRequest
aReq( SID_OPENDOC
, SFX_CALLMODE_SYNCHRON
, GetPool() );
454 OUString
aFact("private:factory/");
456 aReq
.AppendItem( SfxStringItem( SID_FILE_NAME
, aFact
) );
457 aReq
.AppendItem( SfxFrameItem( SID_DOCFRAME
, GetFrame() ) );
458 aReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, OUString( "_default" ) ) );
460 // TODO/LATER: Should the other arguments be transferred as well?
461 SFX_REQUEST_ARG( rReq
, pDefaultPathItem
, SfxStringItem
, SID_DEFAULTFILEPATH
, sal_False
);
462 if ( pDefaultPathItem
)
463 aReq
.AppendItem( *pDefaultPathItem
);
464 SFX_REQUEST_ARG( rReq
, pDefaultNameItem
, SfxStringItem
, SID_DEFAULTFILENAME
, sal_False
);
465 if ( pDefaultNameItem
)
466 aReq
.AppendItem( *pDefaultNameItem
);
468 SFX_APP()->ExecuteSlot( aReq
);
469 const SfxViewFrameItem
* pItem
= PTR_CAST( SfxViewFrameItem
, aReq
.GetReturnValue() );
471 rReq
.SetReturnValue( SfxFrameItem( 0, pItem
->GetFrame() ) );
474 //--------------------------------------------------------------------
476 void SfxApplication::NewDocExec_Impl( SfxRequest
& rReq
)
478 // No Parameter from BASIC only Factory given?
479 SFX_REQUEST_ARG(rReq
, pTemplNameItem
, SfxStringItem
, SID_TEMPLATE_NAME
, sal_False
);
480 SFX_REQUEST_ARG(rReq
, pTemplFileNameItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
481 SFX_REQUEST_ARG(rReq
, pTemplRegionNameItem
, SfxStringItem
, SID_TEMPLATE_REGIONNAME
, sal_False
);
483 SfxObjectShellLock xDoc
;
485 OUString aTemplateRegion
, aTemplateName
, aTemplateFileName
;
486 sal_Bool bDirect
= sal_False
; // through FileName instead of Region/Template
487 SfxErrorContext
aEc(ERRCTX_SFX_NEWDOC
);
488 if ( !pTemplNameItem
&& !pTemplFileNameItem
)
490 sal_Bool bNewWin
= sal_False
;
491 Window
* pTopWin
= GetTopWindow();
493 SfxTemplateManagerDlg aTemplDlg
;
494 int nRet
= aTemplDlg
.Execute();
495 if ( nRet
== RET_OK
)
498 if ( pTopWin
!= GetTopWindow() )
500 // the dialogue opens a document -> a new TopWindow appears
501 pTopWin
= GetTopWindow();
506 if ( bNewWin
&& pTopWin
)
507 // after the destruction of the dialogue its parent comes to top,
508 // but we want that the new document is on top
516 if ( pTemplNameItem
)
517 aTemplateName
= pTemplNameItem
->GetValue();
520 if ( pTemplRegionNameItem
)
521 aTemplateRegion
= pTemplRegionNameItem
->GetValue();
523 // Template-File-Name
524 if ( pTemplFileNameItem
)
526 aTemplateFileName
= pTemplFileNameItem
->GetValue();
531 sal_uIntPtr lErr
= 0;
532 SfxItemSet
* pSet
= new SfxAllItemSet( GetPool() );
533 pSet
->Put( SfxBoolItem( SID_TEMPLATE
, sal_True
) );
536 SfxDocumentTemplates aTmpFac
;
537 if( aTemplateFileName
.isEmpty() )
538 aTmpFac
.GetFull( aTemplateRegion
, aTemplateName
, aTemplateFileName
);
540 if( aTemplateFileName
.isEmpty() )
541 lErr
= ERRCODE_SFX_TEMPLATENOTFOUND
;
544 INetURLObject
aObj( aTemplateFileName
);
545 SfxErrorContext
aEC( ERRCTX_SFX_LOADTEMPLATE
, aObj
.PathToFileName() );
547 if ( lErr
!= ERRCODE_NONE
)
549 sal_uIntPtr lFatalErr
= ERRCODE_TOERROR(lErr
);
551 ErrorHandler::HandleError(lErr
);
555 SfxCallMode eMode
= SFX_CALLMODE_SYNCHRON
;
557 const SfxPoolItem
*pRet
=0;
558 SfxStringItem
aReferer( SID_REFERER
, "private:user" );
559 SfxStringItem
aTarget( SID_TARGETNAME
, "_default" );
560 if ( !aTemplateFileName
.isEmpty() )
562 DBG_ASSERT( aObj
.GetProtocol() != INET_PROT_NOT_VALID
, "Illegal URL!" );
564 SfxStringItem
aName( SID_FILE_NAME
, aObj
.GetMainURL( INetURLObject::NO_DECODE
) );
565 SfxStringItem
aTemplName( SID_TEMPLATE_NAME
, aTemplateName
);
566 SfxStringItem
aTemplRegionName( SID_TEMPLATE_REGIONNAME
, aTemplateRegion
);
567 pRet
= GetDispatcher_Impl()->Execute( SID_OPENDOC
, eMode
, &aName
, &aTarget
, &aReferer
, &aTemplName
, &aTemplRegionName
, 0L );
571 SfxStringItem
aName( SID_FILE_NAME
, "private:factory" );
572 pRet
= GetDispatcher_Impl()->Execute( SID_OPENDOC
, eMode
, &aName
, &aTarget
, &aReferer
, 0L );
576 rReq
.SetReturnValue( *pRet
);
580 //---------------------------------------------------------------------------
585 * Check if a given filter type should open the hyperlinked document
588 * @param rFilter filter object
590 bool lcl_isFilterNativelySupported(const SfxFilter
& rFilter
)
592 if (rFilter
.IsOwnFormat())
595 OUString aName
= rFilter
.GetFilterName();
596 if (aName
.startsWith("MS Excel"))
597 // We can handle all Excel variants natively.
605 void SfxApplication::OpenDocExec_Impl( SfxRequest
& rReq
)
607 OUString aDocService
;
608 SFX_REQUEST_ARG(rReq
, pDocSrvItem
, SfxStringItem
, SID_DOC_SERVICE
, false);
610 aDocService
= pDocSrvItem
->GetValue();
612 sal_uInt16 nSID
= rReq
.GetSlot();
613 SFX_REQUEST_ARG( rReq
, pFileNameItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
616 OUString
aCommand( pFileNameItem
->GetValue() );
617 const SfxSlot
* pSlot
= GetInterface()->GetSlot( aCommand
);
620 pFileNameItem
= NULL
;
624 if ( aCommand
.startsWith("slot:") )
626 sal_uInt16 nSlotId
= (sal_uInt16
) aCommand
.copy(5).toInt32();
627 if ( nSlotId
== SID_OPENDOC
)
628 pFileNameItem
= NULL
;
633 if ( !pFileNameItem
)
635 // get FileName from dialog
636 std::vector
<OUString
> pURLList
;
638 SfxItemSet
* pSet
= NULL
;
640 SFX_REQUEST_ARG( rReq
, pFolderNameItem
, SfxStringItem
, SID_PATH
, sal_False
);
641 if ( pFolderNameItem
)
642 aPath
= pFolderNameItem
->GetValue();
643 else if ( nSID
== SID_OPENTEMPLATE
)
645 aPath
= SvtPathOptions().GetTemplatePath();
646 sal_Int32 nTokenCount
= comphelper::string::getTokenCount(aPath
, ';');
647 aPath
= aPath
.getToken( nTokenCount
? ( nTokenCount
- 1 ) : 0 , ';' );
650 sal_Int16 nDialog
= SFX2_IMPL_DIALOG_CONFIG
;
651 SFX_REQUEST_ARG( rReq
, pSystemDialogItem
, SfxBoolItem
, SID_FILE_DIALOG
, sal_False
);
652 if ( pSystemDialogItem
)
653 nDialog
= pSystemDialogItem
->GetValue() ? SFX2_IMPL_DIALOG_SYSTEM
: SFX2_IMPL_DIALOG_OOO
;
655 OUString sStandardDir
;
657 SFX_REQUEST_ARG( rReq
, pStandardDirItem
, SfxStringItem
, SID_STANDARD_DIR
, sal_False
);
658 if ( pStandardDirItem
)
659 sStandardDir
= pStandardDirItem
->GetValue();
661 ::com::sun::star::uno::Sequence
< OUString
> aBlackList
;
663 SFX_REQUEST_ARG( rReq
, pBlackListItem
, SfxStringListItem
, SID_BLACK_LIST
, sal_False
);
664 if ( pBlackListItem
)
665 pBlackListItem
->GetStringList( aBlackList
);
668 sal_uIntPtr nErr
= sfx2::FileOpenDialog_Impl(
669 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION
,
670 SFXWB_MULTISELECTION
, OUString(), pURLList
,
671 aFilter
, pSet
, &aPath
, nDialog
, sStandardDir
, aBlackList
);
673 if ( nErr
== ERRCODE_ABORT
)
679 rReq
.SetArgs( *(SfxAllItemSet
*)pSet
);
680 if ( !aFilter
.isEmpty() )
681 rReq
.AppendItem( SfxStringItem( SID_FILTER_NAME
, aFilter
) );
682 rReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, OUString("_default") ) );
683 rReq
.AppendItem( SfxStringItem( SID_REFERER
, "private:user" ) );
686 if(!pURLList
.empty())
688 if ( nSID
== SID_OPENTEMPLATE
)
689 rReq
.AppendItem( SfxBoolItem( SID_TEMPLATE
, sal_False
) );
691 // This helper wraps an existing (or may new created InteractionHandler)
692 // intercept all incoming interactions and provide useful information
693 // later if the following transaction was finished.
695 ::framework::PreventDuplicateInteraction
* pHandler
= new ::framework::PreventDuplicateInteraction(::comphelper::getProcessComponentContext());
696 css::uno::Reference
< css::task::XInteractionHandler
> xHandler (static_cast< css::task::XInteractionHandler
* >(pHandler
), css::uno::UNO_QUERY
);
697 css::uno::Reference
< css::task::XInteractionHandler
> xWrappedHandler
;
699 // wrap existing handler or create new UUI handler
700 SFX_REQUEST_ARG(rReq
, pInteractionItem
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
701 if (pInteractionItem
)
703 pInteractionItem
->GetValue() >>= xWrappedHandler
;
704 rReq
.RemoveItem( SID_INTERACTIONHANDLER
);
706 if (xWrappedHandler
.is())
707 pHandler
->setHandler(xWrappedHandler
);
709 pHandler
->useDefaultUUIHandler();
710 rReq
.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER
,::com::sun::star::uno::makeAny(xHandler
)) );
712 // define rules for this handler
713 css::uno::Type aInteraction
= ::getCppuType(static_cast< css::task::ErrorCodeRequest
* >(0));
714 ::framework::PreventDuplicateInteraction::InteractionInfo
aRule (aInteraction
, 1);
715 pHandler
->addInteractionRule(aRule
);
717 if (!aDocService
.isEmpty())
719 rReq
.RemoveItem(SID_DOC_SERVICE
);
720 rReq
.AppendItem(SfxStringItem(SID_DOC_SERVICE
, aDocService
));
723 for(std::vector
<OUString
>::const_iterator i
= pURLList
.begin(); i
!= pURLList
.end(); ++i
)
725 rReq
.RemoveItem( SID_FILE_NAME
);
726 rReq
.AppendItem( SfxStringItem( SID_FILE_NAME
, *i
) );
728 // Run synchronous, so that not the next document is loaded
730 // TODO/LATER: use URLList argument and always remove one document after another, each step in asychronous execution, until finished
731 // but only if reschedule is a problem
732 GetDispatcher_Impl()->Execute( SID_OPENDOC
, SFX_CALLMODE_SYNCHRON
, *rReq
.GetArgs() );
734 // check for special interaction "NO MORE DOCUMENTS ALLOWED" and
735 // break loop then. Otherwise we risk showing the same interaction more then once.
736 if ( pHandler
->getInteractionInfo(aInteraction
, &aRule
) )
738 if (aRule
.m_nCallCount
> 0)
740 if (aRule
.m_xRequest
.is())
742 css::task::ErrorCodeRequest aRequest
;
743 if (aRule
.m_xRequest
->getRequest() >>= aRequest
)
745 if (aRequest
.ErrCode
==
746 sal::static_int_cast
< sal_Int32
>(
747 ERRCODE_SFX_NOMOREDOCUMENTSALLOWED
))
761 sal_Bool bHyperlinkUsed
= sal_False
;
763 if ( SID_OPENURL
== nSID
)
765 // SID_OPENURL does the same as SID_OPENDOC!
766 rReq
.SetSlot( SID_OPENDOC
);
769 else if ( nSID
== SID_OPENTEMPLATE
)
771 rReq
.AppendItem( SfxBoolItem( SID_TEMPLATE
, sal_False
) );
773 // pass URL to OS by using ShellExecuter or open it internal
774 // if it seams to be an own format.
776 There exist two possibilities to open hyperlinks:
777 a) using SID_OPENHYPERLINK (new)
778 b) using SID_BROWSE (old)
780 else if ( nSID
== SID_OPENHYPERLINK
)
782 rReq
.SetSlot( SID_OPENDOC
);
784 bHyperlinkUsed
= sal_True
;
787 // no else here! It's optional ...
790 SFX_REQUEST_ARG(rReq
, pHyperLinkUsedItem
, SfxBoolItem
, SID_BROWSE
, sal_False
);
791 if ( pHyperLinkUsedItem
)
792 bHyperlinkUsed
= pHyperLinkUsedItem
->GetValue();
793 // no "official" item, so remove it from ItemSet before using UNO-API
794 rReq
.RemoveItem( SID_BROWSE
);
797 SFX_REQUEST_ARG( rReq
, pFileName
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
798 OUString aFileName
= pFileName
->GetValue();
801 SFX_REQUEST_ARG( rReq
, pRefererItem
, SfxStringItem
, SID_REFERER
, sal_False
);
803 aReferer
= pRefererItem
->GetValue();
805 SFX_REQUEST_ARG( rReq
, pFileFlagsItem
, SfxStringItem
, SID_OPTIONS
, sal_False
);
806 if ( pFileFlagsItem
)
808 OUString aFileFlags
= pFileFlagsItem
->GetValue();
809 aFileFlags
= aFileFlags
.toAsciiUpperCase();
810 if ( -1 != aFileFlags
.indexOf( 0x0054 ) ) // T = 54h
812 rReq
.RemoveItem( SID_TEMPLATE
);
813 rReq
.AppendItem( SfxBoolItem( SID_TEMPLATE
, sal_True
) );
816 if ( -1 != aFileFlags
.indexOf( 0x0048 ) ) // H = 48h
818 rReq
.RemoveItem( SID_HIDDEN
);
819 rReq
.AppendItem( SfxBoolItem( SID_HIDDEN
, sal_True
) );
822 if ( -1 != aFileFlags
.indexOf( 0x0052 ) ) // R = 52h
824 rReq
.RemoveItem( SID_DOC_READONLY
);
825 rReq
.AppendItem( SfxBoolItem( SID_DOC_READONLY
, sal_True
) );
828 if ( -1 != aFileFlags
.indexOf( 0x0042 ) ) // B = 42h
830 rReq
.RemoveItem( SID_PREVIEW
);
831 rReq
.AppendItem( SfxBoolItem( SID_PREVIEW
, sal_True
) );
834 rReq
.RemoveItem( SID_OPTIONS
);
837 // Mark without URL cannot be handled by hyperlink code
838 if ( bHyperlinkUsed
&& !aFileName
.isEmpty() && aFileName
[0] != '#' )
840 Reference
< ::com::sun::star::document::XTypeDetection
> xTypeDetection(
841 ::comphelper::getProcessServiceFactory()->createInstance(
842 OUString("com.sun.star.document.TypeDetection")),
844 if ( xTypeDetection
.is() )
849 aURL
.Complete
= aFileName
;
850 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
851 xTrans
->parseStrict( aURL
);
853 INetProtocol aINetProtocol
= INetURLObject( aURL
.Complete
).GetProtocol();
854 SvtExtendedSecurityOptions aExtendedSecurityOptions
;
855 SvtExtendedSecurityOptions::OpenHyperlinkMode eMode
= aExtendedSecurityOptions
.GetOpenHyperlinkMode();
857 if ( eMode
== SvtExtendedSecurityOptions::OPEN_NEVER
&& aINetProtocol
!= INET_PROT_VND_SUN_STAR_HELP
)
859 SolarMutexGuard aGuard
;
860 Window
*pWindow
= SFX_APP()->GetTopWindow();
862 WarningBox
aSecurityWarningBox( pWindow
, SfxResId( RID_SECURITY_WARNING_NO_HYPERLINKS
));
863 aSecurityWarningBox
.SetText( SfxResId(RID_SECURITY_WARNING_TITLE
).toString() );
864 aSecurityWarningBox
.Execute();
868 aTypeName
= xTypeDetection
->queryTypeByURL( aURL
.Main
);
869 SfxFilterMatcher
& rMatcher
= SFX_APP()->GetFilterMatcher();
870 const SfxFilter
* pFilter
= rMatcher
.GetFilter4EA( aTypeName
);
871 if (!pFilter
|| !lcl_isFilterNativelySupported(*pFilter
))
873 // hyperlink does not link to own type => special handling (http, ftp) browser and (other external protocols) OS
874 if ( aINetProtocol
== INET_PROT_MAILTO
)
876 // don't dispatch mailto hyperlink to desktop dispatcher
877 rReq
.RemoveItem( SID_TARGETNAME
);
878 rReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, OUString("_self") ) );
880 else if ( aINetProtocol
== INET_PROT_FTP
||
881 aINetProtocol
== INET_PROT_HTTP
||
882 aINetProtocol
== INET_PROT_HTTPS
)
884 sfx2::openUriExternally(aURL
.Complete
, true);
889 // check for "internal" protocols that should not be forwarded to the system
890 Sequence
< OUString
> aProtocols(2);
892 // add special protocols that always should be treated as internal
893 aProtocols
[0] = "private:*";
894 aProtocols
[1] = "vnd.sun.star.*";
896 // get registered protocol handlers from configuration
897 Reference
< XNameAccess
> xAccess(officecfg::Office::ProtocolHandler::HandlerSet::get());
898 Sequence
< OUString
> aNames
= xAccess
->getElementNames();
899 for ( sal_Int32 nName
= 0; nName
< aNames
.getLength(); nName
++)
901 Reference
< XPropertySet
> xSet
;
902 Any aRet
= xAccess
->getByName( aNames
[nName
] );
907 aRet
= xSet
->getPropertyValue("Protocols");
908 Sequence
< OUString
> aTmp
;
911 // todo: add operator+= to SequenceAsVector class and use SequenceAsVector for aProtocols
912 sal_Int32 nLength
= aProtocols
.getLength();
913 aProtocols
.realloc( nLength
+aTmp
.getLength() );
914 for ( sal_Int32 n
=0; n
<aTmp
.getLength(); n
++ )
915 aProtocols
[(++nLength
)-1] = aTmp
[n
];
919 sal_Bool bFound
= sal_False
;
920 for ( sal_Int32 nProt
=0; nProt
<aProtocols
.getLength(); nProt
++ )
922 WildCard
aPattern(aProtocols
[nProt
]);
923 if ( aPattern
.Matches( aURL
.Complete
) )
932 sal_Bool bLoadInternal
= sal_False
;
935 sfx2::openUriExternally(
936 aURL
.Complete
, pFilter
== 0);
938 catch ( ::com::sun::star::system::SystemShellExecuteException
& )
940 rReq
.RemoveItem( SID_TARGETNAME
);
941 rReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, OUString("_default") ) );
942 bLoadInternal
= sal_True
;
944 if ( !bLoadInternal
)
951 // hyperlink document must be loaded into a new frame
952 rReq
.RemoveItem( SID_TARGETNAME
);
953 rReq
.AppendItem( SfxStringItem( SID_TARGETNAME
, OUString("_default") ) );
958 if (!SvtSecurityOptions().isSecureMacroUri(aFileName
, aReferer
))
960 SfxErrorContext
aCtx( ERRCTX_SFX_OPENDOC
, aFileName
);
961 ErrorHandler::HandleError( ERRCODE_IO_ACCESSDENIED
);
965 SfxFrame
* pTargetFrame
= NULL
;
966 Reference
< XFrame
> xTargetFrame
;
968 SFX_REQUEST_ARG(rReq
, pFrameItem
, SfxFrameItem
, SID_DOCFRAME
, sal_False
);
970 pTargetFrame
= pFrameItem
->GetFrame();
974 SFX_REQUEST_ARG(rReq
, pUnoFrameItem
, SfxUnoFrameItem
, SID_FILLFRAME
, sal_False
);
976 xTargetFrame
= pUnoFrameItem
->GetFrame();
979 if ( !pTargetFrame
&& !xTargetFrame
.is() && SfxViewFrame::Current() )
980 pTargetFrame
= &SfxViewFrame::Current()->GetFrame();
982 // check if caller has set a callback
983 SFX_REQUEST_ARG(rReq
, pLinkItem
, SfxLinkItem
, SID_DONELINK
, sal_False
);
985 // remove from Itemset, because it confuses the parameter transformation
987 pLinkItem
= (SfxLinkItem
*) pLinkItem
->Clone();
989 rReq
.RemoveItem( SID_DONELINK
);
991 // check if the view must be hidden
992 sal_Bool bHidden
= sal_False
;
993 SFX_REQUEST_ARG(rReq
, pHidItem
, SfxBoolItem
, SID_HIDDEN
, sal_False
);
995 bHidden
= pHidItem
->GetValue();
997 // This request is a UI call. We have to set the right values inside the MediaDescriptor
998 // for: InteractionHandler, StatusIndicator, MacroExecutionMode and DocTemplate.
999 // But we have to look for already existing values or for real hidden requests.
1000 SFX_REQUEST_ARG(rReq
, pPreviewItem
, SfxBoolItem
, SID_PREVIEW
, sal_False
);
1001 if (!bHidden
&& ( !pPreviewItem
|| !pPreviewItem
->GetValue() ) )
1003 SFX_REQUEST_ARG(rReq
, pInteractionItem
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
1004 SFX_REQUEST_ARG(rReq
, pMacroExecItem
, SfxUInt16Item
, SID_MACROEXECMODE
, sal_False
);
1005 SFX_REQUEST_ARG(rReq
, pDocTemplateItem
, SfxUInt16Item
, SID_UPDATEDOCMODE
, sal_False
);
1007 if (!pInteractionItem
)
1009 Reference
< task::XInteractionHandler2
> xHdl
= task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), 0 );
1010 rReq
.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER
,::com::sun::star::uno::makeAny(xHdl
)) );
1012 if (!pMacroExecItem
)
1013 rReq
.AppendItem( SfxUInt16Item(SID_MACROEXECMODE
,::com::sun::star::document::MacroExecMode::USE_CONFIG
) );
1014 if (!pDocTemplateItem
)
1015 rReq
.AppendItem( SfxUInt16Item(SID_UPDATEDOCMODE
,::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG
) );
1018 // extract target name
1020 SFX_REQUEST_ARG(rReq
, pTargetItem
, SfxStringItem
, SID_TARGETNAME
, sal_False
);
1022 aTarget
= pTargetItem
->GetValue();
1025 SFX_REQUEST_ARG( rReq
, pNewViewItem
, SfxBoolItem
, SID_OPEN_NEW_VIEW
, sal_False
);
1026 if ( pNewViewItem
&& pNewViewItem
->GetValue() )
1027 aTarget
= "_blank" ;
1033 DBG_ASSERT( rReq
.IsSynchronCall() || pLinkItem
, "Hidden load process must be done synchronously!" );
1036 Reference
< XController
> xController
;
1037 // if a frame is given, it must be used for the starting point of the targetting mechanism
1038 // this code is also used if asynchronous loading is possible, because loadComponent always is synchron
1039 if ( !xTargetFrame
.is() )
1043 xTargetFrame
= pTargetFrame
->GetFrameInterface();
1047 xTargetFrame
.set( Desktop::create(::comphelper::getProcessComponentContext()), UNO_QUERY
);
1052 SFX_REQUEST_ARG( rReq
, pURLItem
, SfxStringItem
, SID_FILE_NAME
, sal_False
);
1053 aFileName
= pURLItem
->GetValue();
1054 if( !aFileName
.isEmpty() && aFileName
[0] == '#' ) // Mark without URL
1056 SfxViewFrame
*pView
= pTargetFrame
? pTargetFrame
->GetCurrentViewFrame() : 0;
1058 pView
= SfxViewFrame::Current();
1059 pView
->GetViewShell()->JumpToMark( aFileName
.copy(1) );
1060 rReq
.SetReturnValue( SfxViewFrameItem( 0, pView
) );
1064 // convert items to properties for framework API calls
1065 Sequence
< PropertyValue
> aArgs
;
1066 TransformItems( SID_OPENDOC
, *rReq
.GetArgs(), aArgs
);
1067 // Any Referer (that was relevant in the above call to
1068 // SvtSecurityOptions::isSecureMacroUri) is no longer relevant, assuming
1069 // this "open" request is initiated directly by the user:
1070 for (sal_Int32 i
= 0; i
!= aArgs
.getLength(); ++i
) {
1071 if (aArgs
[i
].Name
== "Referer") {
1073 for (; i
!= aArgs
.getLength(); ++i
) {
1074 aArgs
[i
- 1] = aArgs
[i
];
1076 aArgs
.realloc(aArgs
.getLength()-1);
1081 // TODO/LATER: either remove LinkItem or create an asynchronous process for it
1082 if( bHidden
|| pLinkItem
|| rReq
.IsSynchronCall() )
1084 // if loading must be done synchron, we must wait for completion to get a return value
1085 // find frame by myself; I must konw the exact frame to get the controller for the return value from it
1086 Reference
< XComponent
> xComp
;
1090 xComp
= ::comphelper::SynchronousDispatch::dispatch( xTargetFrame
, aFileName
, aTarget
, 0, aArgs
);
1092 catch(const RuntimeException
&)
1096 catch(const ::com::sun::star::uno::Exception
&)
1100 Reference
< XModel
> xModel( xComp
, UNO_QUERY
);
1102 xController
= xModel
->getCurrentController();
1104 xController
= Reference
< XController
>( xComp
, UNO_QUERY
);
1110 aURL
.Complete
= aFileName
;
1111 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
1112 xTrans
->parseStrict( aURL
);
1114 Reference
< XDispatchProvider
> xProv( xTargetFrame
, UNO_QUERY
);
1115 Reference
< XDispatch
> xDisp
= xProv
.is() ? xProv
->queryDispatch( aURL
, aTarget
, FrameSearchFlag::ALL
) : Reference
< XDispatch
>();;
1116 SAL_INFO( "sfx2.appl", "PERFORMANCE - SfxApplication::OpenDocExec_Impl" );
1118 xDisp
->dispatch( aURL
, aArgs
);
1121 if ( xController
.is() )
1123 // try to find the SfxFrame for the controller
1124 SfxFrame
* pCntrFrame
= NULL
;
1125 for ( SfxViewShell
* pShell
= SfxViewShell::GetFirst( 0, sal_False
); pShell
; pShell
= SfxViewShell::GetNext( *pShell
, 0, sal_False
) )
1127 if ( pShell
->GetController() == xController
)
1129 pCntrFrame
= &pShell
->GetViewFrame()->GetFrame();
1136 SfxObjectShell
* pSh
= pCntrFrame
->GetCurrentDocument();
1137 DBG_ASSERT( pSh
, "Controller without ObjectShell ?!" );
1139 rReq
.SetReturnValue( SfxViewFrameItem( 0, pCntrFrame
->GetCurrentViewFrame() ) );
1142 pSh
->RestoreNoDelete();
1148 SfxPoolItem
* pRet
= rReq
.GetReturnValue()->Clone();
1149 pLinkItem
->GetValue().Call(pRet
);
1154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */