diff options
Diffstat (limited to 'sfx2/source/appl/appopen.cxx')
-rw-r--r-- | sfx2/source/appl/appopen.cxx | 1332 |
1 files changed, 1332 insertions, 0 deletions
diff --git a/sfx2/source/appl/appopen.cxx b/sfx2/source/appl/appopen.cxx new file mode 100644 index 000000000000..89bb5f23f1de --- /dev/null +++ b/sfx2/source/appl/appopen.cxx @@ -0,0 +1,1332 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XNotifyingDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/DispatchResultState.hpp> +#include <com/sun/star/frame/XDispatchResultListener.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/document/XTypeDetection.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <com/sun/star/task/ErrorCodeRequest.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ustring.hxx> + + +#include <comphelper/storagehelper.hxx> +#include <comphelper/synchronousdispatch.hxx> +#include <comphelper/configurationhelper.hxx> +#include <comphelper/sequenceasvector.hxx> + +#include <vcl/wrkwin.hxx> +#include <svl/intitem.hxx> +#include <vcl/msgbox.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <sfx2/doctempl.hxx> +#include <svtools/sfxecode.hxx> +#include <framework/preventduplicateinteraction.hxx> +#include <svtools/ehdl.hxx> +#include <basic/sbxobj.hxx> +#include <svl/urihelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/moduleoptions.hxx> +#include <svtools/templdlg.hxx> +#include <osl/file.hxx> +#include <unotools/extendedsecurityoptions.hxx> +#include <comphelper/docpasswordhelper.hxx> +#include <vcl/svapp.hxx> + +#include <vos/mutex.hxx> + +#include <rtl/logfile.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/new.hxx> +#include <sfx2/objitem.hxx> +#include <sfx2/objsh.hxx> +#include <svl/slstitm.hxx> +#include "objshimp.hxx" +#include "openflag.hxx" +#include <sfx2/passwd.hxx> +#include "referers.hxx" +#include <sfx2/request.hxx> +#include "sfxresid.hxx" +#include <sfx2/viewsh.hxx> +#include "app.hrc" +#include <sfx2/viewfrm.hxx> +#include <sfx2/sfxuno.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/event.hxx> + +#define _SVSTDARR_STRINGSDTOR +#include <svl/svstdarr.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::system; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::container; +using namespace ::cppu; +using namespace ::sfx2; + +namespace css = ::com::sun::star; + +//========================================================================= + +class SfxOpenDocStatusListener_Impl : public WeakImplHelper1< XDispatchResultListener > +{ +public: + BOOL bFinished; + BOOL bSuccess; + virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& Event ) throw(RuntimeException); + virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException); + SfxOpenDocStatusListener_Impl() + : bFinished( FALSE ) + , bSuccess( FALSE ) + {} +}; + +void SAL_CALL SfxOpenDocStatusListener_Impl::dispatchFinished( const DispatchResultEvent& aEvent ) throw(RuntimeException) +{ + bSuccess = ( aEvent.State == DispatchResultState::SUCCESS ); + bFinished = TRUE; +} + +void SAL_CALL SfxOpenDocStatusListener_Impl::disposing( const EventObject& ) throw(RuntimeException) +{ +} + +SfxObjectShellRef SfxApplication::DocAlreadyLoaded +( + const String& rName, // Name des Dokuments mit Pfad + BOOL bSilent, // TRUE: nicht nach neuer Sicht fragen + BOOL bActivate, // soll bestehende Sicht aktiviert werden + BOOL bForbidVisible, + const String* pPostStr +) + +/* [Beschreibung] + + Stellt fest, ob ein Dokument mit dem Namen 'rName' bereits geladen + ist und liefert einen Pointer darauf zu"uck. + + Ist das Dokument noch nicht geladen, wird ein 0-Pointer zur"uckgeliefert. +*/ + +{ + // zu suchenden Namen als URL aufbereiten + INetURLObject aUrlToFind( rName ); + DBG_ASSERT( aUrlToFind.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL" ); + String aPostString; + if ( pPostStr ) + aPostString = *pPostStr; + + // noch offen? + SfxObjectShellRef xDoc; + + if ( !aUrlToFind.HasError() ) + { + // dann bei den normal geoeffneten Docs + if ( !xDoc.Is() ) + { + xDoc = SfxObjectShell::GetFirst( 0, FALSE ); // auch hidden Docs + while( xDoc.Is() ) + { + if ( xDoc->GetMedium() && + xDoc->GetCreateMode() == SFX_CREATE_MODE_STANDARD && + !xDoc->IsAbortingImport() && !xDoc->IsLoading() ) + { + // Vergleiche anhand der URLs + INetURLObject aUrl( xDoc->GetMedium()->GetName() ); + if ( !aUrl.HasError() && aUrl == aUrlToFind && + (!bForbidVisible || !SfxViewFrame::GetFirst( xDoc, TRUE )) && + !xDoc->IsLoading()) + { + break; + } + } + xDoc = SfxObjectShell::GetNext( *xDoc, 0, FALSE ); + } + } + } + + // gefunden? + if ( xDoc.Is() && bActivate ) + { + DBG_ASSERT( + !bForbidVisible, "Unsichtbares kann nicht aktiviert werden" ); + + SfxViewFrame* pFrame; + for( pFrame = SfxViewFrame::GetFirst( xDoc ); + pFrame && !pFrame->IsVisible(); + pFrame = SfxViewFrame::GetNext( *pFrame, xDoc ) ) ; + if ( pFrame ) + { + SfxViewFrame *pCur = SfxViewFrame::Current(); + if ( !bSilent && pFrame == pCur ) + InfoBox( 0, SfxResId(RID_DOCALREADYLOADED_DLG)).Execute(); + if ( bActivate ) + { + pFrame->MakeActive_Impl( TRUE ); + } + } + } + return xDoc; +} + +//==================================================================== + +void SetTemplate_Impl( const String &rFileName, + const String &rLongName, + SfxObjectShell *pDoc) +{ + // write TemplateName to DocumentInfo of document + // TemplateDate stays as default (=current date) + pDoc->ResetFromTemplate( rLongName, rFileName ); +} + +//-------------------------------------------------------------------- + +class SfxDocPasswordVerifier : public ::comphelper::IDocPasswordVerifier +{ +public: + inline explicit SfxDocPasswordVerifier( const Reference< embed::XStorage >& rxStorage ) : + mxStorage( rxStorage ) {} + + virtual ::comphelper::DocPasswordVerifierResult + verifyPassword( const ::rtl::OUString& rPassword ); + +private: + Reference< embed::XStorage > mxStorage; +}; + +::comphelper::DocPasswordVerifierResult SfxDocPasswordVerifier::verifyPassword( const ::rtl::OUString& rPassword ) +{ + ::comphelper::DocPasswordVerifierResult eResult = ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD; + try + { + // check the password + // if the password correct is the stream will be opened successfuly + // and immediatelly closed + ::comphelper::OStorageHelper::SetCommonStoragePassword( mxStorage, rPassword ); + + mxStorage->openStreamElement( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ), + embed::ElementModes::READ | embed::ElementModes::NOCREATE ); + + // no exception -> success + eResult = ::comphelper::DocPasswordVerifierResult_OK; + } + catch( const packages::WrongPasswordException& ) + { + eResult = ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD; + } + catch( const uno::Exception& ) + { + // unknown error, do not try to ask again + eResult = ::comphelper::DocPasswordVerifierResult_ABORT; + } + return eResult; +} + +//-------------------------------------------------------------------- + +sal_uInt32 CheckPasswd_Impl +( + //Window *pWin, // Parent des Dialogs + SfxObjectShell* pDoc, + SfxItemPool& /*rPool*/, // Pool, falls ein Set erzeugt werden mus + SfxMedium* pFile // das Medium, dessen Passwort gfs. erfragt werden soll +) + +/* [Beschreibung] + + Zu einem Medium das Passwort erfragen; funktioniert nur, wenn es sich + um einen Storage handelt. + Wenn in der Documentinfo das Passwort-Flag gesetzt ist, wird + das Passwort vom Benutzer per Dialog erfragt und an dem Set + des Mediums gesetzt; das Set wird, wenn nicht vorhanden, erzeugt. +*/ +{ + ULONG nRet = ERRCODE_NONE; + + if( ( !pFile->GetFilter() || pFile->IsStorage() ) ) + { + uno::Reference< embed::XStorage > xStorage = pFile->GetStorage( sal_True ); + if( xStorage.is() ) + { + uno::Reference< beans::XPropertySet > xStorageProps( xStorage, uno::UNO_QUERY ); + if ( xStorageProps.is() ) + { + sal_Bool bIsEncrypted = sal_False; + try { + xStorageProps->getPropertyValue( ::rtl::OUString::createFromAscii("HasEncryptedEntries") ) + >>= bIsEncrypted; + } catch( uno::Exception& ) + { + // TODO/LATER: + // the storage either has no encrypted elements or it's just + // does not allow to detect it, probably it should be implemented laiter + /* + bIsEncrypted = ( aInfo.Load( xStorage ) && aInfo.IsPasswd() ); + */ + } + + if ( bIsEncrypted ) + { + Window* pWin = pDoc ? pDoc->GetDialogParent( pFile ) : NULL; + if ( pWin ) + pWin->Show(); + + nRet = ERRCODE_SFX_CANTGETPASSWD; + + SfxItemSet *pSet = pFile->GetItemSet(); + if( pSet ) + { + Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = pFile->GetInteractionHandler(); + if( xInteractionHandler.is() ) + { + // use the comphelper password helper to request a password + ::rtl::OUString aDocumentName = INetURLObject( pFile->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET ); + SfxDocPasswordVerifier aVerifier( xStorage ); + ::rtl::OUString aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword( + aVerifier, ::rtl::OUString(), xInteractionHandler, aDocumentName, comphelper::DocPasswordRequestType_STANDARD ); + + if ( aPassword.getLength() > 0 ) + { + pSet->Put( SfxStringItem( SID_PASSWORD, aPassword ) ); + + try + { + // update the version list of the medium using the new password + pFile->GetVersionList(); + } + catch( uno::Exception& ) + { + // TODO/LATER: set the error code + } + + nRet = ERRCODE_NONE; + } + else + nRet = ERRCODE_IO_ABORT; + } + } + } + } + else + { + OSL_ENSURE( sal_False, "A storage must implement XPropertySet interface!" ); + nRet = ERRCODE_SFX_CANTGETPASSWD; + } + } + } + + return nRet; +} + +//-------------------------------------------------------------------- + + +ULONG SfxApplication::LoadTemplate( SfxObjectShellLock& xDoc, const String &rFileName, BOOL bCopy, SfxItemSet* pSet ) +{ + const SfxFilter* pFilter = NULL; + SfxMedium aMedium( rFileName, ( STREAM_READ | STREAM_SHARE_DENYNONE ), FALSE ); + + if ( !aMedium.GetStorage( sal_True ).is() ) + aMedium.GetInStream(); + + if ( aMedium.GetError() ) + { + delete pSet; + return aMedium.GetErrorCode(); + } + + aMedium.UseInteractionHandler( TRUE ); + ULONG nErr = GetFilterMatcher().GuessFilter( aMedium,&pFilter,SFX_FILTER_TEMPLATE, 0 ); + if ( 0 != nErr) + { + delete pSet; + return ERRCODE_SFX_NOTATEMPLATE; + } + + if( !pFilter || !pFilter->IsAllowedAsTemplate() ) + { + delete pSet; + return ERRCODE_SFX_NOTATEMPLATE; + } + + if ( pFilter->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) + { + DBG_ASSERT( !xDoc.Is(), "Sorry, not implemented!" ); + delete pSet; + SfxStringItem aName( SID_FILE_NAME, rFileName ); + SfxStringItem aReferer( SID_REFERER, String::CreateFromAscii("private:user") ); + SfxStringItem aFlags( SID_OPTIONS, String::CreateFromAscii("T") ); + SfxBoolItem aHidden( SID_HIDDEN, TRUE ); + const SfxPoolItem *pRet = GetDispatcher_Impl()->Execute( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, &aName, &aHidden, &aReferer, &aFlags, 0L ); + const SfxObjectItem *pObj = PTR_CAST( SfxObjectItem, pRet ); + if ( pObj ) + xDoc = PTR_CAST( SfxObjectShell, pObj->GetShell() ); + else + { + const SfxViewFrameItem *pView = PTR_CAST( SfxViewFrameItem, pRet ); + if ( pView ) + { + SfxViewFrame *pFrame = pView->GetFrame(); + if ( pFrame ) + xDoc = pFrame->GetObjectShell(); + } + } + + if ( !xDoc.Is() ) + return ERRCODE_SFX_DOLOADFAILED; + } + else + { + if ( !xDoc.Is() ) + xDoc = SfxObjectShell::CreateObject( pFilter->GetServiceName() ); + + SfxMedium *pMedium = new SfxMedium( rFileName, STREAM_STD_READ, FALSE, pFilter, pSet ); + if(!xDoc->DoLoad(pMedium)) + { + ErrCode nErrCode = xDoc->GetErrorCode(); + xDoc->DoClose(); + xDoc.Clear(); + return nErrCode; + } + } + + if( bCopy ) + { + try + { + // TODO: introduce error handling + + uno::Reference< embed::XStorage > xTempStorage = ::comphelper::OStorageHelper::GetTemporaryStorage(); + if( !xTempStorage.is() ) + throw uno::RuntimeException(); + + xDoc->GetStorage()->copyToStorage( xTempStorage ); + +//REMOVE // the following operations should be done in one step +//REMOVE xDoc->DoHandsOff(); + if ( !xDoc->DoSaveCompleted( new SfxMedium( xTempStorage, String() ) ) ) + throw uno::RuntimeException(); + } + catch( uno::Exception& ) + { + xDoc->DoClose(); + xDoc.Clear(); + + // TODO: transfer correct error outside + return ERRCODE_SFX_GENERAL; + } + + SetTemplate_Impl( rFileName, String(), xDoc ); + } + else + SetTemplate_Impl( rFileName, String(), xDoc ); + + xDoc->SetNoName(); + xDoc->InvalidateName(); + xDoc->SetModified(FALSE); + xDoc->ResetError(); + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > xModel ( xDoc->GetModel(), ::com::sun::star::uno::UNO_QUERY ); + if ( xModel.is() ) + { + SfxItemSet* pNew = xDoc->GetMedium()->GetItemSet()->Clone(); + pNew->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL ); + pNew->ClearItem( SID_FILTER_NAME ); + //pNew->Put( SfxStringItem( SID_FILTER_NAME, xDoc->GetFactory().GetFilter(0)->GetFilterName() ) ); + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs; + TransformItems( SID_OPENDOC, *pNew, aArgs ); + sal_Int32 nLength = aArgs.getLength(); + aArgs.realloc( nLength + 1 ); + aArgs[nLength].Name = DEFINE_CONST_UNICODE("Title"); + aArgs[nLength].Value <<= ::rtl::OUString( xDoc->GetTitle( SFX_TITLE_DETECT ) ); + xModel->attachResource( ::rtl::OUString(), aArgs ); + delete pNew; + } + + return xDoc->GetErrorCode(); +} + +//-------------------------------------------------------------------- + +void SfxApplication::NewDocDirectExec_Impl( SfxRequest& rReq ) +{ + DBG_MEMTEST(); + + SFX_REQUEST_ARG( rReq, pFactoryItem, SfxStringItem, SID_NEWDOCDIRECT, FALSE); + String aFactName; + if ( pFactoryItem ) + aFactName = pFactoryItem->GetValue(); + else + aFactName = SvtModuleOptions().GetDefaultModuleName(); + + + SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, GetPool() ); + String aFact = String::CreateFromAscii("private:factory/"); + aFact += aFactName; + aReq.AppendItem( SfxStringItem( SID_FILE_NAME, aFact ) ); + aReq.AppendItem( SfxFrameItem( SID_DOCFRAME, GetFrame() ) ); + aReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii( "_default" ) ) ); + + // TODO/LATER: Should the other arguments be transfered as well? + SFX_REQUEST_ARG( rReq, pDefaultPathItem, SfxStringItem, SID_DEFAULTFILEPATH, FALSE); + if ( pDefaultPathItem ) + aReq.AppendItem( *pDefaultPathItem ); + SFX_REQUEST_ARG( rReq, pDefaultNameItem, SfxStringItem, SID_DEFAULTFILENAME, FALSE); + if ( pDefaultNameItem ) + aReq.AppendItem( *pDefaultNameItem ); + + SFX_APP()->ExecuteSlot( aReq ); + const SfxViewFrameItem* pItem = PTR_CAST( SfxViewFrameItem, aReq.GetReturnValue() ); + if ( pItem ) + rReq.SetReturnValue( SfxFrameItem( 0, pItem->GetFrame() ) ); +} + +//-------------------------------------------------------------------- + +void SfxApplication::NewDocExec_Impl( SfxRequest& rReq ) +{ + DBG_MEMTEST(); + + // keine Parameter vom BASIC nur Factory angegeben? + SFX_REQUEST_ARG(rReq, pTemplNameItem, SfxStringItem, SID_TEMPLATE_NAME, FALSE); + SFX_REQUEST_ARG(rReq, pTemplFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE); + SFX_REQUEST_ARG(rReq, pTemplRegionNameItem, SfxStringItem, SID_TEMPLATE_REGIONNAME, FALSE); + + SfxObjectShellLock xDoc; + + String aTemplateRegion, aTemplateName, aTemplateFileName; + BOOL bDirect = FALSE; // "uber FileName anstelle Region/Template + SfxErrorContext aEc(ERRCTX_SFX_NEWDOC); + if ( !pTemplNameItem && !pTemplFileNameItem ) + { + Window* pTopWin = GetTopWindow(); + SvtDocumentTemplateDialog* pDocTemplDlg = new SvtDocumentTemplateDialog( NULL ); + int nRet = pDocTemplDlg->Execute(); + sal_Bool bNewWin = sal_False; + if ( nRet == RET_OK ) + { + rReq.Done(); + if ( pTopWin != GetTopWindow() ) + { + // the dialogue opens a document -> a new TopWindow appears + pTopWin = GetTopWindow(); + bNewWin = sal_True; + } + } + + delete pDocTemplDlg; + if ( bNewWin && pTopWin ) + // after the destruction of the dialogue its parent comes to top, + // but we want that the new document is on top + pTopWin->ToTop(); + + return; + } + else + { + // Template-Name + if ( pTemplNameItem ) + aTemplateName = pTemplNameItem->GetValue(); + + // Template-Region + if ( pTemplRegionNameItem ) + aTemplateRegion = pTemplRegionNameItem->GetValue(); + + // Template-File-Name + if ( pTemplFileNameItem ) + { + aTemplateFileName = pTemplFileNameItem->GetValue(); + bDirect = TRUE; + } + } + + ULONG lErr = 0; + SfxItemSet* pSet = new SfxAllItemSet( GetPool() ); + pSet->Put( SfxBoolItem( SID_TEMPLATE, TRUE ) ); + if ( !bDirect ) + { + SfxDocumentTemplates aTmpFac; + if( !aTemplateFileName.Len() ) + aTmpFac.GetFull( aTemplateRegion, aTemplateName, aTemplateFileName ); + + if( !aTemplateFileName.Len() ) + lErr = ERRCODE_SFX_TEMPLATENOTFOUND; + } + + INetURLObject aObj( aTemplateFileName ); + SfxErrorContext aEC( ERRCTX_SFX_LOADTEMPLATE, aObj.PathToFileName() ); + + if ( lErr != ERRCODE_NONE ) + { + ULONG lFatalErr = ERRCODE_TOERROR(lErr); + if ( lFatalErr ) + ErrorHandler::HandleError(lErr); + } + else + { + SfxCallMode eMode = SFX_CALLMODE_SYNCHRON; + + const SfxPoolItem *pRet=0; + SfxStringItem aReferer( SID_REFERER, DEFINE_CONST_UNICODE("private:user") ); + SfxStringItem aTarget( SID_TARGETNAME, DEFINE_CONST_UNICODE("_default") ); + if ( aTemplateFileName.Len() ) + { + DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL!" ); + + SfxStringItem aName( SID_FILE_NAME, aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + SfxStringItem aTemplName( SID_TEMPLATE_NAME, aTemplateName ); + SfxStringItem aTemplRegionName( SID_TEMPLATE_REGIONNAME, aTemplateRegion ); + pRet = GetDispatcher_Impl()->Execute( SID_OPENDOC, eMode, &aName, &aTarget, &aReferer, &aTemplName, &aTemplRegionName, 0L ); + } + else + { + SfxStringItem aName( SID_FILE_NAME, DEFINE_CONST_UNICODE("private:factory") ); + pRet = GetDispatcher_Impl()->Execute( SID_OPENDOC, eMode, &aName, &aTarget, &aReferer, 0L ); + } + + if ( pRet ) + rReq.SetReturnValue( *pRet ); + } +} + +//--------------------------------------------------------------------------- + +void SfxApplication::OpenDocExec_Impl( SfxRequest& rReq ) +{ + DBG_MEMTEST(); + + USHORT nSID = rReq.GetSlot(); + SFX_REQUEST_ARG( rReq, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE ); + if ( pFileNameItem ) + { + String aCommand( pFileNameItem->GetValue() ); + const SfxSlot* pSlot = GetInterface()->GetSlot( aCommand ); + if ( pSlot ) + { + pFileNameItem = NULL; + } + else + { + sal_Int32 nIndex = aCommand.SearchAscii("slot:"); + if ( !nIndex ) + { + USHORT nSlotId = (USHORT) String( aCommand, 5, aCommand.Len()-5 ).ToInt32(); + if ( nSlotId == SID_OPENDOC ) + pFileNameItem = NULL; + } + } + } + + if ( !pFileNameItem ) + { + // get FileName from dialog + SvStringsDtor* pURLList = NULL; + String aFilter; + SfxItemSet* pSet = NULL; + String aPath; + SFX_REQUEST_ARG( rReq, pFolderNameItem, SfxStringItem, SID_PATH, FALSE ); + if ( pFolderNameItem ) + aPath = pFolderNameItem->GetValue(); + else if ( nSID == SID_OPENTEMPLATE ) + { + aPath = SvtPathOptions().GetTemplatePath(); + sal_Int32 nTokenCount = aPath.GetTokenCount( ';' ); + aPath = aPath.GetToken( + sal::static_int_cast< xub_StrLen >( + nTokenCount ? ( nTokenCount - 1 ) : 0 ), + ';' ); + } + + sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG; + SFX_REQUEST_ARG( rReq, pSystemDialogItem, SfxBoolItem, SID_FILE_DIALOG, FALSE ); + if ( pSystemDialogItem ) + nDialog = pSystemDialogItem->GetValue() ? SFX2_IMPL_DIALOG_SYSTEM : SFX2_IMPL_DIALOG_OOO; + + String sStandardDir; + + SFX_REQUEST_ARG( rReq, pStandardDirItem, SfxStringItem, SID_STANDARD_DIR, FALSE ); + if ( pStandardDirItem ) + sStandardDir = pStandardDirItem->GetValue(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > aBlackList; + + SFX_REQUEST_ARG( rReq, pBlackListItem, SfxStringListItem, SID_BLACK_LIST, FALSE ); + if ( pBlackListItem ) + pBlackListItem->GetStringList( aBlackList ); + + + ULONG nErr = sfx2::FileOpenDialog_Impl( + WB_OPEN | SFXWB_MULTISELECTION | SFXWB_SHOWVERSIONS, String(), pURLList, aFilter, pSet, &aPath, nDialog, sStandardDir, aBlackList ); + + if ( nErr == ERRCODE_ABORT ) + { + delete pURLList; + return; + } + + rReq.SetArgs( *(SfxAllItemSet*)pSet ); + if (aFilter.Len() >0 ) + rReq.AppendItem( SfxStringItem( SID_FILTER_NAME, aFilter ) ); + rReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_default") ) ); + rReq.AppendItem( SfxStringItem( SID_REFERER, String::CreateFromAscii(SFX_REFERER_USER) ) ); + delete pSet; + + if ( pURLList->Count() ) + { + if ( nSID == SID_OPENTEMPLATE ) + rReq.AppendItem( SfxBoolItem( SID_TEMPLATE, FALSE ) ); + + // This helper wraps an existing (or may new created InteractionHandler) + // intercept all incoming interactions and provide usefull informations + // later if the following transaction was finished. + + ::framework::PreventDuplicateInteraction* pHandler = new ::framework::PreventDuplicateInteraction(::comphelper::getProcessServiceFactory()); + css::uno::Reference< css::task::XInteractionHandler > xHandler (static_cast< css::task::XInteractionHandler* >(pHandler), css::uno::UNO_QUERY); + css::uno::Reference< css::task::XInteractionHandler > xWrappedHandler; + + // wrap existing handler or create new UUI handler + SFX_REQUEST_ARG(rReq, pInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, FALSE); + if (pInteractionItem) + { + pInteractionItem->GetValue() >>= xWrappedHandler; + rReq.RemoveItem( SID_INTERACTIONHANDLER ); + } + if (xWrappedHandler.is()) + pHandler->setHandler(xWrappedHandler); + else + pHandler->useDefaultUUIHandler(); + rReq.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER,::com::sun::star::uno::makeAny(xHandler)) ); + + // define rules for this handler + css::uno::Type aInteraction = ::getCppuType(static_cast< css::task::ErrorCodeRequest* >(0)); + ::framework::PreventDuplicateInteraction::InteractionInfo aRule (aInteraction, 1); + pHandler->addInteractionRule(aRule); + + for ( USHORT i = 0; i < pURLList->Count(); ++i ) + { + String aURL = *(pURLList->GetObject(i)); + rReq.RemoveItem( SID_FILE_NAME ); + rReq.AppendItem( SfxStringItem( SID_FILE_NAME, aURL ) ); + + // synchron ausf"uhren, damit beim Reschedulen nicht schon das n"achste Dokument + // geladen wird + // TODO/LATER: use URLList argument and always remove one document after another, each step in asychronous execution, until finished + // but only if reschedule is a problem + GetDispatcher_Impl()->Execute( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, *rReq.GetArgs() ); + + // check for special interaction "NO MORE DOCUMENTS ALLOWED" and + // break loop then. Otherwise we risk showing the same interaction more then once. + if ( pHandler->getInteractionInfo(aInteraction, &aRule) ) + { + if (aRule.m_nCallCount > 0) + { + if (aRule.m_xRequest.is()) + { + css::task::ErrorCodeRequest aRequest; + if (aRule.m_xRequest->getRequest() >>= aRequest) + { + if (aRequest.ErrCode == + sal::static_int_cast< sal_Int32 >( + ERRCODE_SFX_NOMOREDOCUMENTSALLOWED)) + break; + } + } + } + } + } + + delete pURLList; + return; + } + delete pURLList; + } + + if ( !rReq.IsSynchronCall() ) + { + // now check wether a stream is already there + // if not: download it in a thread and restart the call + // return; + } + + BOOL bHyperlinkUsed = FALSE; + + if ( SID_OPENURL == nSID ) + { + // SID_OPENURL does the same as SID_OPENDOC! + rReq.SetSlot( SID_OPENDOC ); + nSID = SID_OPENDOC; + } + else if ( nSID == SID_OPENTEMPLATE ) + { + rReq.AppendItem( SfxBoolItem( SID_TEMPLATE, FALSE ) ); + } + // pass URL to OS by using ShellExecuter or open it internal + // if it seams to be an own format. + /* Attention! + There exist two possibilities to open hyperlinks: + a) using SID_OPENHYPERLINK (new) + b) using SID_BROWSE (old) + */ + else if ( nSID == SID_OPENHYPERLINK ) + { + rReq.SetSlot( SID_OPENDOC ); + nSID = SID_OPENDOC; + bHyperlinkUsed = TRUE; + } + + // no else here! It's optional ... + if (!bHyperlinkUsed) + { + SFX_REQUEST_ARG(rReq, pHyperLinkUsedItem, SfxBoolItem, SID_BROWSE, FALSE); + if ( pHyperLinkUsedItem ) + bHyperlinkUsed = pHyperLinkUsedItem->GetValue(); + // no "official" item, so remove it from ItemSet before using UNO-API + rReq.RemoveItem( SID_BROWSE ); + } + + SFX_REQUEST_ARG( rReq, pFileName, SfxStringItem, SID_FILE_NAME, FALSE ); + String aFileName = pFileName->GetValue(); + + String aReferer; + SFX_REQUEST_ARG( rReq, pRefererItem, SfxStringItem, SID_REFERER, FALSE ); + if ( pRefererItem ) + aReferer = pRefererItem->GetValue(); + + SFX_REQUEST_ARG( rReq, pFileFlagsItem, SfxStringItem, SID_OPTIONS, FALSE); + if ( pFileFlagsItem ) + { + String aFileFlags = pFileFlagsItem->GetValue(); + aFileFlags.ToUpperAscii(); + if ( STRING_NOTFOUND != aFileFlags.Search( 0x0054 ) ) // T = 54h + { + rReq.RemoveItem( SID_TEMPLATE ); + rReq.AppendItem( SfxBoolItem( SID_TEMPLATE, TRUE ) ); + } + + if ( STRING_NOTFOUND != aFileFlags.Search( 0x0048 ) ) // H = 48h + { + rReq.RemoveItem( SID_HIDDEN ); + rReq.AppendItem( SfxBoolItem( SID_HIDDEN, TRUE ) ); + } + + if ( STRING_NOTFOUND != aFileFlags.Search( 0x0052 ) ) // R = 52h + { + rReq.RemoveItem( SID_DOC_READONLY ); + rReq.AppendItem( SfxBoolItem( SID_DOC_READONLY, TRUE ) ); + } + + if ( STRING_NOTFOUND != aFileFlags.Search( 0x0042 ) ) // B = 42h + { + rReq.RemoveItem( SID_PREVIEW ); + rReq.AppendItem( SfxBoolItem( SID_PREVIEW, TRUE ) ); + } + + if ( STRING_NOTFOUND != aFileFlags.Search( 0x0053 ) ) // S = 53h + { + // not supported anymore + //rReq.RemoveItem( SID_SILENT ); + //rReq.AppendItem( SfxBoolItem( SID_SILENT, TRUE ) ); + } + + rReq.RemoveItem( SID_OPTIONS ); + } + + // Mark without URL cannot be handled by hyperlink code + if ( bHyperlinkUsed && aFileName.Len() && aFileName.GetChar(0) != '#' ) + { + Reference< ::com::sun::star::document::XTypeDetection > xTypeDetection( + ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.document.TypeDetection" )), + UNO_QUERY ); + if ( xTypeDetection.is() ) + { + URL aURL; + ::rtl::OUString aTypeName; + + aURL.Complete = aFileName; + Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY ); + xTrans->parseStrict( aURL ); + + INetProtocol aINetProtocol = INetURLObject( aURL.Complete ).GetProtocol(); + SvtExtendedSecurityOptions aExtendedSecurityOptions; + SvtExtendedSecurityOptions::OpenHyperlinkMode eMode = aExtendedSecurityOptions.GetOpenHyperlinkMode(); + if ( eMode == SvtExtendedSecurityOptions::OPEN_WITHSECURITYCHECK ) + { + if ( aINetProtocol == INET_PROT_FILE ) + { +/*!!! pb: #i49802# no security warning any longer + // Check if file URL is a directory. This is not insecure! + osl::Directory aDir( aURL.Main ); + sal_Bool bIsDir = ( aDir.open() == osl::Directory::E_None ); + + if ( !bIsDir && !aExtendedSecurityOptions.IsSecureHyperlink( aURL.Complete ) ) + { + // Security check for local files depending on the extension + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + + String aSecurityWarningBoxTitle( SfxResId( RID_SECURITY_WARNING_TITLE )); + WarningBox aSecurityWarningBox( pWindow, SfxResId( RID_SECURITY_WARNING_HYPERLINK )); + aSecurityWarningBox.SetText( aSecurityWarningBoxTitle ); + + // Replace %s with the real file name + String aMsgText = aSecurityWarningBox.GetMessText(); + String aMainURL( aURL.Main ); + String aFileName; + + utl::LocalFileHelper::ConvertURLToPhysicalName( aMainURL, aFileName ); + aMsgText.SearchAndReplaceAscii( "%s", aFileName ); + aSecurityWarningBox.SetMessText( aMsgText ); + + if( aSecurityWarningBox.Execute() == RET_NO ) + return; + } +*/ + } + } + else if ( eMode == SvtExtendedSecurityOptions::OPEN_NEVER && aINetProtocol != INET_PROT_VND_SUN_STAR_HELP ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + + String aSecurityWarningBoxTitle( SfxResId( RID_SECURITY_WARNING_TITLE )); + WarningBox aSecurityWarningBox( pWindow, SfxResId( RID_SECURITY_WARNING_NO_HYPERLINKS )); + aSecurityWarningBox.SetText( aSecurityWarningBoxTitle ); + aSecurityWarningBox.Execute(); + return; + } + + aTypeName = xTypeDetection->queryTypeByURL( aURL.Main ); + SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); + const SfxFilter* pFilter = rMatcher.GetFilter4EA( aTypeName ); + if ( !pFilter || !( pFilter->IsOwnFormat() )) + { + // hyperlink does not link to own type => special handling (http, ftp) browser and (other external protocols) OS + Reference< XSystemShellExecute > xSystemShellExecute( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.system.SystemShellExecute" )), UNO_QUERY ); + if ( xSystemShellExecute.is() ) + { + if ( aINetProtocol == INET_PROT_MAILTO ) + { + // don't dispatch mailto hyperlink to desktop dispatcher + rReq.RemoveItem( SID_TARGETNAME ); + rReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_self") ) ); + } + else if ( aINetProtocol == INET_PROT_FTP || + aINetProtocol == INET_PROT_HTTP || + aINetProtocol == INET_PROT_HTTPS ) + { + try + { + // start browser + ::rtl::OUString aURLString( aURL.Complete ); + xSystemShellExecute->execute( aURLString, ::rtl::OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + ErrorBox( pWindow, SfxResId( MSG_ERR_NO_WEBBROWSER_FOUND )).Execute(); + } + catch ( ::com::sun::star::system::SystemShellExecuteException& ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + ErrorBox( pWindow, SfxResId( MSG_ERR_NO_WEBBROWSER_FOUND )).Execute(); + } + + return; + } + else + { + // check for "internal" protocols that should not be forwarded to the system + Sequence < ::rtl::OUString > aProtocols(2); + + // add special protocols that always should be treated as internal + aProtocols[0] = ::rtl::OUString::createFromAscii("private:*"); + aProtocols[1] = ::rtl::OUString::createFromAscii("vnd.sun.star.*"); + + try + { + // get registered protocol handlers from configuration + Reference < XNameAccess > xAccess( ::comphelper::ConfigurationHelper::openConfig( ::comphelper::getProcessServiceFactory(), + ::rtl::OUString::createFromAscii("org.openoffice.Office.ProtocolHandler/HandlerSet"), ::comphelper::ConfigurationHelper::E_READONLY ), UNO_QUERY ); + if ( xAccess.is() ) + { + Sequence < ::rtl::OUString > aNames = xAccess->getElementNames(); + for ( sal_Int32 nName = 0; nName < aNames.getLength(); nName ++) + { + Reference < XPropertySet > xSet; + Any aRet = xAccess->getByName( aNames[nName] ); + aRet >>= xSet; + if ( xSet.is() ) + { + // copy protocols + aRet = xSet->getPropertyValue( ::rtl::OUString::createFromAscii("Protocols") ); + Sequence < ::rtl::OUString > aTmp; + aRet >>= aTmp; + + // todo: add operator+= to SequenceAsVector class and use SequenceAsVector for aProtocols + sal_Int32 nLength = aProtocols.getLength(); + aProtocols.realloc( nLength+aTmp.getLength() ); + for ( sal_Int32 n=0; n<aTmp.getLength(); n++ ) + aProtocols[(++nLength)-1] = aTmp[n]; + } + } + } + } + catch ( Exception& ) + { + // registered protocols could not be read + } + + sal_Bool bFound = sal_False; + for ( sal_Int32 nProt=0; nProt<aProtocols.getLength(); nProt++ ) + { + WildCard aPattern(aProtocols[nProt]); + if ( aPattern.Matches( aURL.Complete ) ) + { + bFound = sal_True; + break; + } + } + + if ( !bFound ) + { + BOOL bLoadInternal = FALSE; + + // security reservation: => we have to check the referer before executing + if (SFX_APP()->IsSecureURL(rtl::OUString(), &aReferer)) + { + ::rtl::OUString aURLString( aURL.Complete ); + + try + { + // give os this file + xSystemShellExecute->execute( aURLString, ::rtl::OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + ErrorBox( pWindow, SfxResId( MSG_ERR_NO_WEBBROWSER_FOUND )).Execute(); + } + catch ( ::com::sun::star::system::SystemShellExecuteException& ) + { + if ( !pFilter ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pWindow = SFX_APP()->GetTopWindow(); + ErrorBox( pWindow, SfxResId( MSG_ERR_NO_WEBBROWSER_FOUND )).Execute(); + } + else + { + rReq.RemoveItem( SID_TARGETNAME ); + rReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_default") ) ); + bLoadInternal = TRUE; + } + } + } + else + { + SfxErrorContext aCtx( ERRCTX_SFX_OPENDOC, aURL.Complete ); + ErrorHandler::HandleError( ERRCODE_IO_ACCESSDENIED ); + } + + if ( !bLoadInternal ) + return; + } + } + } + } + else + { + // hyperlink document must be loaded into a new frame + rReq.RemoveItem( SID_TARGETNAME ); + rReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_default") ) ); + } + } + } + + if ( !SFX_APP()->IsSecureURL( INetURLObject(aFileName), &aReferer ) ) + { + SfxErrorContext aCtx( ERRCTX_SFX_OPENDOC, aFileName ); + ErrorHandler::HandleError( ERRCODE_IO_ACCESSDENIED ); + return; + } + + SfxFrame* pTargetFrame = NULL; + Reference< XFrame > xTargetFrame; + + SFX_REQUEST_ARG(rReq, pFrameItem, SfxFrameItem, SID_DOCFRAME, FALSE); + if ( pFrameItem ) + pTargetFrame = pFrameItem->GetFrame(); + + if ( !pTargetFrame ) + { + SFX_REQUEST_ARG(rReq, pUnoFrameItem, SfxUnoFrameItem, SID_FILLFRAME, FALSE); + if ( pUnoFrameItem ) + xTargetFrame = pUnoFrameItem->GetFrame(); + } + + if ( !pTargetFrame && !xTargetFrame.is() && SfxViewFrame::Current() ) + pTargetFrame = &SfxViewFrame::Current()->GetFrame(); + + // check if caller has set a callback + SFX_REQUEST_ARG(rReq, pLinkItem, SfxLinkItem, SID_DONELINK, FALSE ); + + // remove from Itemset, because it confuses the parameter transformation + if ( pLinkItem ) + pLinkItem = (SfxLinkItem*) pLinkItem->Clone(); + + rReq.RemoveItem( SID_DONELINK ); + + // check if the view must be hidden + BOOL bHidden = FALSE; + SFX_REQUEST_ARG(rReq, pHidItem, SfxBoolItem, SID_HIDDEN, FALSE); + if ( pHidItem ) + bHidden = pHidItem->GetValue(); + + // This request is a UI call. We have to set the right values inside the MediaDescriptor + // for: InteractionHandler, StatusIndicator, MacroExecutionMode and DocTemplate. + // But we have to look for already existing values or for real hidden requests. + SFX_REQUEST_ARG(rReq, pPreviewItem, SfxBoolItem, SID_PREVIEW, FALSE); + if (!bHidden && ( !pPreviewItem || !pPreviewItem->GetValue() ) ) + { + SFX_REQUEST_ARG(rReq, pInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, FALSE); + SFX_REQUEST_ARG(rReq, pMacroExecItem , SfxUInt16Item, SID_MACROEXECMODE , FALSE); + SFX_REQUEST_ARG(rReq, pDocTemplateItem, SfxUInt16Item, SID_UPDATEDOCMODE , FALSE); + + if (!pInteractionItem) + { + Reference < ::com::sun::star::task::XInteractionHandler > xHdl( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.comp.uui.UUIInteractionHandler")), UNO_QUERY ); + if (xHdl.is()) + rReq.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER,::com::sun::star::uno::makeAny(xHdl)) ); + } + if (!pMacroExecItem) + rReq.AppendItem( SfxUInt16Item(SID_MACROEXECMODE,::com::sun::star::document::MacroExecMode::USE_CONFIG) ); + if (!pDocTemplateItem) + rReq.AppendItem( SfxUInt16Item(SID_UPDATEDOCMODE,::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG) ); + } + + // extract target name + ::rtl::OUString aTarget; + SFX_REQUEST_ARG(rReq, pTargetItem, SfxStringItem, SID_TARGETNAME, FALSE); + if ( pTargetItem ) + aTarget = pTargetItem->GetValue(); + else + { + SFX_REQUEST_ARG( rReq, pNewViewItem, SfxBoolItem, SID_OPEN_NEW_VIEW, FALSE ); + if ( pNewViewItem && pNewViewItem->GetValue() ) + aTarget = String::CreateFromAscii("_blank" ); + } + + if ( bHidden ) + { + aTarget = String::CreateFromAscii("_blank"); + DBG_ASSERT( rReq.IsSynchronCall() || pLinkItem, "Hidden load process must be done synchronously!" ); + } + + Reference < XController > xController; +// if ( ( !bIsBlankTarget && pFrame ) || pLinkItem || !rReq.IsSynchronCall() ) +// { + // if a frame is given, it must be used for the starting point of the targetting mechanism + // this code is also used if asynchronous loading is possible, because loadComponent always is synchron + if ( !xTargetFrame.is() ) + { + if ( pTargetFrame ) + { + xTargetFrame = pTargetFrame->GetFrameInterface(); + } + else + { + xTargetFrame.set( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY ); + } + } + + // make URL ready + SFX_REQUEST_ARG( rReq, pURLItem, SfxStringItem, SID_FILE_NAME, FALSE ); + aFileName = pURLItem->GetValue(); + if( aFileName.Len() && aFileName.GetChar(0) == '#' ) // Mark without URL + { + SfxViewFrame *pView = pTargetFrame ? pTargetFrame->GetCurrentViewFrame() : 0; + if ( !pView ) + pView = SfxViewFrame::Current(); + pView->GetViewShell()->JumpToMark( aFileName.Copy(1) ); + rReq.SetReturnValue( SfxViewFrameItem( 0, pView ) ); + return; + } + + // convert items to properties for framework API calls + Sequence < PropertyValue > aArgs; + TransformItems( SID_OPENDOC, *rReq.GetArgs(), aArgs ); + + // TODO/LATER: either remove LinkItem or create an asynchronous process for it + if( bHidden || pLinkItem || rReq.IsSynchronCall() ) + { + // if loading must be done synchron, we must wait for completion to get a return value + // find frame by myself; I must konw the exact frame to get the controller for the return value from it + //if( aTarget.getLength() ) + // xTargetFrame = xTargetFrame->findFrame( aTarget, FrameSearchFlag::ALL ); + Reference < XComponent > xComp; + + try + { + xComp = ::comphelper::SynchronousDispatch::dispatch( xTargetFrame, aFileName, aTarget, 0, aArgs ); +// Reference < XComponentLoader > xLoader( xTargetFrame, UNO_QUERY ); +// xComp = xLoader->loadComponentFromURL( aFileName, aTarget, 0, aArgs ); + } + catch(const RuntimeException&) + { + throw; + } + catch(const ::com::sun::star::uno::Exception&) + { + } + + Reference < XModel > xModel( xComp, UNO_QUERY ); + if ( xModel.is() ) + xController = xModel->getCurrentController(); + else + xController = Reference < XController >( xComp, UNO_QUERY ); + + } + else + { + URL aURL; + aURL.Complete = aFileName; + Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY ); + xTrans->parseStrict( aURL ); + + Reference < XDispatchProvider > xProv( xTargetFrame, UNO_QUERY ); + Reference < XDispatch > xDisp = xProv.is() ? xProv->queryDispatch( aURL, aTarget, FrameSearchFlag::ALL ) : Reference < XDispatch >();; + RTL_LOGFILE_PRODUCT_CONTEXT( aLog2, "PERFORMANCE - SfxApplication::OpenDocExec_Impl" ); + if ( xDisp.is() ) + xDisp->dispatch( aURL, aArgs ); + } + /* + } + else + { + // synchron loading without a given frame or as blank frame + SFX_REQUEST_ARG( rReq, pFileNameItem, SfxStringItem, SID_FILE_NAME, FALSE ); + + // Desktop service must exists! dont catch() or check for problems here ... + // But loading of documents can fail by other reasons. Handle it more gracefully. + Reference < XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY ); + Reference < XComponent > xComp; + try + { + xComp = xDesktop->loadComponentFromURL( pFileNameItem->GetValue(), aTarget, 0, aArgs ); + } + catch(const RuntimeException&) + { + throw; + } + catch(const ::com::sun::star::uno::Exception&) + { + xDesktop.clear(); + xComp.clear(); + } + + Reference < XModel > xModel( xComp, UNO_QUERY ); + if ( xModel.is() ) + xController = xModel->getCurrentController(); + else + xController = Reference < XController >( xComp, UNO_QUERY ); + }*/ + + if ( xController.is() ) + { + // try to find the SfxFrame for the controller + SfxFrame* pCntrFrame = NULL; + for ( SfxViewShell* pShell = SfxViewShell::GetFirst( 0, FALSE ); pShell; pShell = SfxViewShell::GetNext( *pShell, 0, FALSE ) ) + { + if ( pShell->GetController() == xController ) + { + pCntrFrame = &pShell->GetViewFrame()->GetFrame(); + break; + } + } + + if ( pCntrFrame ) + { + SfxObjectShell* pSh = pCntrFrame->GetCurrentDocument(); + DBG_ASSERT( pSh, "Controller without ObjectShell ?!" ); + + rReq.SetReturnValue( SfxViewFrameItem( 0, pCntrFrame->GetCurrentViewFrame() ) ); + + if ( bHidden ) + pSh->RestoreNoDelete(); + } + } + + if ( pLinkItem ) + { + SfxPoolItem* pRet = rReq.GetReturnValue()->Clone(); + pLinkItem->GetValue().Call(pRet); + delete pLinkItem; + } +} |