/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
::comphelper::DocPasswordVerifierResult SfxDocPasswordVerifier::verifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
{
::comphelper::DocPasswordVerifierResult eResult = ::comphelper::DocPasswordVerifierResult::WrongPassword; try
{ // check the encryption data // if the data correct is the stream will be opened successfully // and immediately closed
::comphelper::OStorageHelper::SetCommonStorageEncryptionData( mxStorage, rEncryptionData );
// for new ODF encryption, try to extract the encrypted inner package // (it will become the SfxObjectShell storage) if (!m_rMedium.TryEncryptedInnerPackage(mxStorage))
{ // ... old ODF encryption:
mxStorage->openStreamElement(
u"content.xml"_ustr,
embed::ElementModes::READ | embed::ElementModes::NOCREATE );
}
// no exception -> success
eResult = ::comphelper::DocPasswordVerifierResult::OK;
} catch( const packages::WrongPasswordException& )
{
eResult = ::comphelper::DocPasswordVerifierResult::WrongPassword;
} catch( const uno::Exception& )
{ // unknown error, report it as wrong password // TODO/LATER: we need an additional way to report unknown problems in this case
eResult = ::comphelper::DocPasswordVerifierResult::WrongPassword;
} return eResult;
}
ErrCode CheckPasswd_Impl
(
SfxObjectShell* pDoc,
SfxMedium* pFile // the Medium and its Password should be obtained
)
/* [Description]
Ask for the password for a medium, only works if it concerns storage. If the password flag is set in the Document Info, then the password is requested through a user dialogue and the set at the Set of the medium. If the set does not exist the it is created.
*/
{
ErrCode nRet = ERRCODE_NONE;
if( !pFile->GetFilter() || pFile->IsStorage() )
{
uno::Reference< embed::XStorage > xStorage = pFile->GetStorage(); if( xStorage.is() )
{
uno::Reference< beans::XPropertySet > xStorageProps( xStorage, uno::UNO_QUERY ); if ( xStorageProps.is() )
{ bool bIsEncrypted = false;
uno::Sequence< uno::Sequence< beans::NamedValue > > aGpgProperties; try {
xStorageProps->getPropertyValue(u"HasEncryptedEntries"_ustr)
>>= bIsEncrypted;
xStorageProps->getPropertyValue(u"EncryptionGpGProperties"_ustr)
>>= aGpgProperties;
} 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 later
}
if ( bIsEncrypted )
{
css::uno::Reference<css::awt::XWindow> xWin(pDoc ? pDoc->GetDialogParent(pFile) : nullptr); if (xWin)
xWin->setVisible(true);
nRet = ERRCODE_SFX_CANTGETPASSWD;
SfxItemSet& rSet = pFile->GetItemSet();
Reference< css::task::XInteractionHandler > xInteractionHandler = pFile->GetInteractionHandler(); if( xInteractionHandler.is() )
{ // use the comphelper password helper to request a password
OUString aPassword; const SfxStringItem* pPasswordItem = rSet.GetItem(SID_PASSWORD, false); if ( pPasswordItem )
aPassword = pPasswordItem->GetValue();
// try if one of the public key entries is // decryptable, then extract session key // from it if ( !aEncryptionData.hasElements() && aGpgProperties.hasElements() )
aEncryptionData = ::comphelper::DocPasswordHelper::decryptGpgSession(aGpgProperties);
// tdf#93389: if recovering a document, encryption data should contain // entries for the real filter, not only for recovery ODF, to keep it // encrypted. Pass this in encryption data. // TODO: pass here the real filter (from AutoRecovery::implts_openDocs) // to marshal this to requestAndVerifyDocPassword if (rSet.GetItemState(SID_DOC_SALVAGE, false) == SfxItemState::SET)
{
aEncryptionData = comphelper::concatSequences(
aEncryptionData, std::initializer_list<beans::NamedValue>{
{ u"ForSalvage"_ustr, css::uno::Any(true) } });
}
try
{ // update the version list of the medium using the new password
pFile->GetVersionList();
} catch( uno::Exception& )
{ // TODO/LATER: set the error code
}
// TODO/LATER: Should the other arguments be transferred as well? const SfxStringItem* pDefaultPathItem = rReq.GetArg<SfxStringItem>(SID_DEFAULTFILEPATH); if ( pDefaultPathItem )
aReq.AppendItem( *pDefaultPathItem ); const SfxStringItem* pDefaultNameItem = rReq.GetArg<SfxStringItem>(SID_DEFAULTFILENAME); if ( pDefaultNameItem )
aReq.AppendItem( *pDefaultNameItem );
if (xModel.is())
aTemplDlg.setDocumentModel(xModel);
int nRet = aTemplDlg.run(); if ( nRet == RET_OK )
{
rReq.Done(); if ( pTopWin != GetTopWindow() )
{ // the dialogue opens a document -> a new TopWindow appears
pTopWin = GetTopWindow();
bNewWin = true;
}
}
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->present();
}
if (aResult)
rReq.SetReturnValue( *aResult.getItem() );
}
}
namespace {
/** * Check if a given filter type should open the hyperlinked document * natively. * * @param rFilter filter object
*/ bool lcl_isFilterNativelySupported(const SfxFilter& rFilter)
{ if (rFilter.IsOwnFormat()) returntrue;
const OUString& aName = rFilter.GetFilterName(); // We can handle all Excel variants natively. return aName.startsWith("MS Excel");
}
if ( !pFileNameItem )
{ // get FileName from dialog
css::uno::Sequence<OUString> aURLList;
OUString aFilter;
std::optional<SfxAllItemSet> pSet;
OUString aPath; const SfxStringItem* pFolderNameItem = rReq.GetArg<SfxStringItem>(SID_PATH); if ( pFolderNameItem )
aPath = pFolderNameItem->GetValue(); elseif ( nSID == SID_OPENTEMPLATE )
{
aPath = SvtPathOptions().GetTemplatePath(); if (!aPath.isEmpty()) // if not empty then get last token
aPath = aPath.copy(aPath.lastIndexOf(';')+1); // lastIndexOf+copy works whether separator (';') is there or not
}
if (aURLList.hasElements())
{ 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 useful information // later if the following transaction was finished.
rtl::Reference<sfx2::PreventDuplicateInteraction> pHandler = new sfx2::PreventDuplicateInteraction(comphelper::getProcessComponentContext());
uno::Reference<task::XInteractionHandler> xWrappedHandler;
// wrap existing handler or create new UUI handler const SfxUnoAnyItem* pInteractionItem = rReq.GetArg<SfxUnoAnyItem>(SID_INTERACTIONHANDLER); if (pInteractionItem)
{
pInteractionItem->GetValue() >>= xWrappedHandler;
rReq.RemoveItem( SID_INTERACTIONHANDLER );
} if (xWrappedHandler.is())
pHandler->setHandler(xWrappedHandler); else
pHandler->useDefaultUUIHandler();
rReq.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::Any(uno::Reference<task::XInteractionHandler>(pHandler))) );
// define rules for this handler
css::uno::Type aInteraction = ::cppu::UnoType<css::task::ErrorCodeRequest>::get();
::sfx2::PreventDuplicateInteraction::InteractionInfo aRule(aInteraction);
pHandler->addInteractionRule(aRule);
if (!aDocService.isEmpty())
{
rReq.RemoveItem(SID_DOC_SERVICE);
rReq.AppendItem(SfxStringItem(SID_DOC_SERVICE, aDocService));
}
// Passes the checkbox state of "Edit Filter Settings" to filter dialogs through multiple layers of code. // Since some layers use a published API and cannot be modified directly, we use a context layer instead. // This is a one-time flag and is not stored in any configuration. // For an example of how it's used, see ScFilterOptionsObj::execute.
std::optional<css::uno::ContextLayer> oLayer; if (bShowFilterDialog.has_value())
{
oLayer.emplace(comphelper::NewFlagContext(u"ShowFilterDialog"_ustr,
bShowFilterDialog.value()));
}
// Run synchronous, so that not the next document is loaded // when rescheduling // TODO/LATER: use URLList argument and always remove one document after another, each step in asynchronous execution, until finished // but only if reschedule is a problem
GetDispatcher_Impl()->Execute( SID_OPENDOC, SfxCallMode::SYNCHRON, *rReq.GetArgs() );
// check for special interaction "NO MORE DOCUMENTS ALLOWED" and // break loop then. Otherwise we risk showing the same interaction more than 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_Int32(sal_uInt32(ERRCODE_SFX_NOMOREDOCUMENTSALLOWED))) break;
}
}
}
}
}
return;
}
}
bool bHyperlinkUsed = false;
if ( SID_OPENURL == nSID )
{ // SID_OPENURL does the same as SID_OPENDOC!
rReq.SetSlot( SID_OPENDOC );
} elseif ( nSID == SID_OPENTEMPLATE )
{
rReq.AppendItem( SfxBoolItem( SID_TEMPLATE, false ) );
} // pass URL to OS by using ShellExecuter or open it internal // if it seems to be an own format. /* Attention! There exist two possibilities to open hyperlinks: a) using SID_OPENHYPERLINK (new) b) using SID_BROWSE (old)
*/ elseif ( nSID == SID_OPENHYPERLINK )
{
rReq.SetSlot( SID_OPENDOC );
bHyperlinkUsed = true;
}
// no else here! It's optional ... if (!bHyperlinkUsed)
{ const SfxBoolItem* pHyperLinkUsedItem = rReq.GetArg<SfxBoolItem>(SID_BROWSE); if ( pHyperLinkUsedItem )
bHyperlinkUsed = pHyperLinkUsedItem->GetValue(); // no "official" item, so remove it from ItemSet before using UNO-API
rReq.RemoveItem( SID_BROWSE );
}
// Mark without URL cannot be handled by hyperlink code if ( bHyperlinkUsed && !aFileName.isEmpty() && aFileName[0] != '#' )
{
uno::Reference<document::XTypeDetection> xTypeDetection(
comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.document.TypeDetection"_ustr), UNO_QUERY);
// attempt loading native documents only if they are from a known protocol // it might be sensible to limit the set of protocols even further, but that // may cause regressions, needs further testing // see tdf#136427 for details if (aINetProtocol != INetProtocol::NotValid) { const OUString aTypeName { xTypeDetection->queryTypeByURL( aURL.Main ) };
SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
pFilter = rMatcher.GetFilter4EA( aTypeName );
}
if (!pFilter || (!lcl_isFilterNativelySupported(*pFilter) && !bStartPresentation))
{ // hyperlink does not link to own type => special handling (http, ftp) browser and (other external protocols) OS if ( aINetProtocol == INetProtocol::Mailto )
{ // don't dispatch mailto hyperlink to desktop dispatcher
rReq.RemoveItem( SID_TARGETNAME );
rReq.AppendItem( SfxStringItem( SID_TARGETNAME, u"_self"_ustr ) );
} elseif ( aINetProtocol == INetProtocol::Ftp ||
aINetProtocol == INetProtocol::Http ||
aINetProtocol == INetProtocol::Https )
{
sfx2::openUriExternally(aURL.Complete, true, rReq.GetFrameWeld()); return;
} else
{ // check for "internal" protocols that should not be forwarded to the system // add special protocols that always should be treated as internal
std::vector < OUString > aProtocols { u"private:*"_ustr, u"vnd.sun.star.*"_ustr };
if ( !pTargetFrame )
{ const SfxUnoFrameItem* pUnoFrameItem = rReq.GetArg<SfxUnoFrameItem>(SID_FILLFRAME); if ( pUnoFrameItem )
xTargetFrame = pUnoFrameItem->GetFrame();
}
if (!pTargetFrame && !xTargetFrame.is())
{ if (const SfxViewFrame* pViewFrame = SfxViewFrame::Current())
pTargetFrame = &pViewFrame->GetFrame();
}
// check if caller has set a callback
std::unique_ptr<SfxLinkItem> pLinkItem;
// remove from Itemset, because it confuses the parameter transformation if (auto pParamLinkItem = rReq.GetArg<SfxLinkItem>(SID_DONELINK))
pLinkItem.reset(pParamLinkItem->Clone());
rReq.RemoveItem( SID_DONELINK );
// check if the view must be hidden bool bHidden = false; const SfxBoolItem* pHidItem = rReq.GetArg<SfxBoolItem>(SID_HIDDEN); 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. const SfxBoolItem* pPreviewItem = rReq.GetArg<SfxBoolItem>(SID_PREVIEW); if (!bHidden && ( !pPreviewItem || !pPreviewItem->GetValue() ) )
{ const SfxUnoAnyItem* pInteractionItem = rReq.GetArg<SfxUnoAnyItem>(SID_INTERACTIONHANDLER); const SfxUInt16Item* pMacroExecItem = rReq.GetArg<SfxUInt16Item>(SID_MACROEXECMODE); const SfxUInt16Item* pDocTemplateItem = rReq.GetArg<SfxUInt16Item>(SID_UPDATEDOCMODE);
if (!pInteractionItem)
{
Reference < task::XInteractionHandler2 > xHdl = task::InteractionHandler::createWithParent( ::comphelper::getProcessComponentContext(), nullptr );
rReq.AppendItem( SfxUnoAnyItem(SID_INTERACTIONHANDLER,css::uno::Any(xHdl)) );
} if (!pMacroExecItem)
rReq.AppendItem( SfxUInt16Item(SID_MACROEXECMODE,css::document::MacroExecMode::USE_CONFIG) ); if (!pDocTemplateItem)
rReq.AppendItem( SfxUInt16Item(SID_UPDATEDOCMODE,css::document::UpdateDocMode::ACCORDING_TO_CONFIG) );
}
if ( bHidden )
{
aTarget = "_blank";
DBG_ASSERT( rReq.IsSynchronCall() || pLinkItem, "Hidden load process must be done synchronously!" );
}
Reference < XController > xController; // if a frame is given, it must be used for the starting point of the targeting 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 = Desktop::create(::comphelper::getProcessComponentContext());
}
}
// make URL ready const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_FILE_NAME);
aFileName = pURLItem->GetValue(); if( aFileName.startsWith("#") ) // Mark without URL
{
SfxViewFrame *pView = pTargetFrame ? pTargetFrame->GetCurrentViewFrame() : nullptr; if (!pView)
pView = SfxViewFrame::Current(); if (pView)
pView->GetViewShell()->JumpToMark( aFileName.copy(1) );
rReq.SetReturnValue( SfxViewFrameItem( pView ) ); return;
}
// convert items to properties for framework API calls
Sequence < PropertyValue > aArgs;
TransformItems( SID_OPENDOC, *rReq.GetArgs(), aArgs ); // Any Referer (that was relevant in the above call to // SvtSecurityOptions::isSecureMacroUri) is no longer relevant, assuming // this "open" request is initiated directly by the user: auto pArg = std::find_if(std::cbegin(aArgs), std::cend(aArgs),
[](const PropertyValue& rArg) { return rArg.Name == "Referer"; }); if (pArg != std::cend(aArgs))
{ auto nIndex = static_cast<sal_Int32>(std::distance(std::cbegin(aArgs), pArg));
comphelper::removeElementAt(aArgs, nIndex);
}
// 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 know the exact frame to get the controller for the return value from it
Reference < XComponent > xComp;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.