diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /uui/source | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'uui/source')
48 files changed, 7210 insertions, 0 deletions
diff --git a/uui/source/alreadyopen.cxx b/uui/source/alreadyopen.cxx new file mode 100644 index 000000000..2fe5dcbc4 --- /dev/null +++ b/uui/source/alreadyopen.cxx @@ -0,0 +1,44 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include "alreadyopen.hxx" +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> + +AlreadyOpenQueryBox::AlreadyOpenQueryBox(weld::Window* pParent, const std::locale& rLocale, const OUString& rMessage, bool bIsStoring) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, rMessage)) +{ + m_xQueryBox->set_title(Translate::get(STR_ALREADYOPEN_TITLE, rLocale)); + if (bIsStoring) + { + m_xQueryBox->add_button(Translate::get(STR_ALREADYOPEN_RETRY_SAVE_BTN, rLocale), RET_YES); + m_xQueryBox->add_button(Translate::get(STR_ALREADYOPEN_SAVE_BTN, rLocale), RET_NO); + } + else + { + m_xQueryBox->add_button(Translate::get(STR_ALREADYOPEN_READONLY_BTN, rLocale), RET_YES); + m_xQueryBox->add_button(Translate::get(STR_ALREADYOPEN_OPEN_BTN, rLocale), RET_NO); + } + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_YES); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/alreadyopen.hxx b/uui/source/alreadyopen.hxx new file mode 100644 index 000000000..3d6e5a8fa --- /dev/null +++ b/uui/source/alreadyopen.hxx @@ -0,0 +1,35 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_ALREADYOPEN_HXX +#define INCLUDED_UUI_SOURCE_ALREADYOPEN_HXX + +#include <vcl/weld.hxx> + +class AlreadyOpenQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; +public: + AlreadyOpenQueryBox(weld::Window* pParent, const std::locale& rResLocale, const OUString& aMessage, bool bIsStoring); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/authfallbackdlg.cxx b/uui/source/authfallbackdlg.cxx new file mode 100644 index 000000000..3fa4fc165 --- /dev/null +++ b/uui/source/authfallbackdlg.cxx @@ -0,0 +1,68 @@ +/* -*- 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/. + */ + +#include "authfallbackdlg.hxx" + +AuthFallbackDlg::AuthFallbackDlg(weld::Window* pParent, const OUString& instructions, + const OUString& url) + : GenericDialogController(pParent, "uui/ui/authfallback.ui", "AuthFallbackDlg") + , m_bGoogleMode( false ) + , m_xTVInstructions(m_xBuilder->weld_label("instructions")) + , m_xEDUrl(m_xBuilder->weld_entry("url")) + , m_xEDCode(m_xBuilder->weld_entry("code")) + , m_xEDGoogleCode(m_xBuilder->weld_entry("google_code")) + , m_xBTOk(m_xBuilder->weld_button("ok")) + , m_xBTCancel(m_xBuilder->weld_button("cancel")) + , m_xGoogleBox(m_xBuilder->weld_widget("GDrive")) + , m_xOneDriveBox(m_xBuilder->weld_widget("OneDrive")) +{ + m_xBTOk->connect_clicked( LINK( this, AuthFallbackDlg, OKHdl) ); + m_xBTCancel->connect_clicked( LINK( this, AuthFallbackDlg, CancelHdl) ); + m_xBTOk->set_sensitive(true); + + m_xTVInstructions->set_label(instructions); + if( url.isEmpty() ) + { + // Google 2FA + m_bGoogleMode = true; + m_xGoogleBox->show(); + m_xOneDriveBox->hide(); + m_xEDUrl->hide(); + } + else + { + // OneDrive + m_bGoogleMode = false; + m_xGoogleBox->hide(); + m_xOneDriveBox->show(); + m_xEDUrl->set_text( url ); + } +} + +AuthFallbackDlg::~AuthFallbackDlg() +{ +} + +OUString AuthFallbackDlg::GetCode() const +{ + if( m_bGoogleMode ) + return m_xEDGoogleCode->get_text(); + else + return m_xEDCode->get_text(); +} + +IMPL_LINK_NOARG(AuthFallbackDlg, OKHdl, weld::Button&, void) +{ + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(AuthFallbackDlg, CancelHdl, weld::Button&, void) +{ + m_xDialog->response(RET_CANCEL); +} diff --git a/uui/source/authfallbackdlg.hxx b/uui/source/authfallbackdlg.hxx new file mode 100644 index 000000000..b3482f70e --- /dev/null +++ b/uui/source/authfallbackdlg.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_SVTOOLS_AUTHFALLBACKDLG_HXX +#define INCLUDED_SVTOOLS_AUTHFALLBACKDLG_HXX + +#include <vcl/weld.hxx> + +class AuthFallbackDlg : public weld::GenericDialogController +{ +private: + bool m_bGoogleMode; + + std::unique_ptr<weld::Label> m_xTVInstructions; + std::unique_ptr<weld::Entry> m_xEDUrl; + std::unique_ptr<weld::Entry> m_xEDCode; + std::unique_ptr<weld::Entry> m_xEDGoogleCode; + std::unique_ptr<weld::Button> m_xBTOk; + std::unique_ptr<weld::Button> m_xBTCancel; + std::unique_ptr<weld::Widget> m_xGoogleBox; + std::unique_ptr<weld::Widget> m_xOneDriveBox; + +public: + AuthFallbackDlg(weld::Window* pParent, const OUString& instructions, const OUString& url); + virtual ~AuthFallbackDlg() override; + + OUString GetCode() const; + +private: + DECL_LINK(OKHdl, weld::Button&, void); + DECL_LINK(CancelHdl, weld::Button&, void); +}; + +#endif // INCLUDED_SVTOOLS_AUTHFALLBACKDLG_HXX diff --git a/uui/source/filechanged.cxx b/uui/source/filechanged.cxx new file mode 100644 index 000000000..23db10450 --- /dev/null +++ b/uui/source/filechanged.cxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> +#include "filechanged.hxx" + +FileChangedQueryBox::FileChangedQueryBox(weld::Window* pParent, const std::locale& rLocale) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, + VclButtonsType::NONE, Translate::get(STR_FILECHANGED_MSG, rLocale))) +{ + m_xQueryBox->set_title(Translate::get(STR_FILECHANGED_TITLE, rLocale)); + m_xQueryBox->add_button(Translate::get(STR_FILECHANGED_SAVEANYWAY_BTN, rLocale), RET_YES); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_YES); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/filechanged.hxx b/uui/source/filechanged.hxx new file mode 100644 index 000000000..f68b793e9 --- /dev/null +++ b/uui/source/filechanged.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_FILECHANGED_HXX +#define INCLUDED_UUI_SOURCE_FILECHANGED_HXX + +#include <vcl/weld.hxx> + +class FileChangedQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; + +public: + FileChangedQueryBox(weld::Window* pParent, const std::locale& pResLocale); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/fltdlg.cxx b/uui/source/fltdlg.cxx new file mode 100644 index 000000000..391cf5a70 --- /dev/null +++ b/uui/source/fltdlg.cxx @@ -0,0 +1,211 @@ +/* -*- 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 . + */ + +#include "fltdlg.hxx" + +#include <com/sun/star/util/XStringWidth.hpp> +#include <cppuhelper/implbase.hxx> +#include <tools/urlobj.hxx> + +#include <osl/file.hxx> + +namespace uui +{ + +/*-************************************************************************************************************ + @short initialize filter dialog with start values + @descr We set some necessary information on these instance for later working and create internal structures. + After construction user should call "SetFilters()" and "SetURL()" to fill listbox with selectable filter + names and set file name of file, which should be used for selected filter. + + @seealso method SetFilters() + @seealso method SetURL() + + @param "pParentWindow" , parent window for dialog + @threadsafe no +*//*-*************************************************************************************************************/ +FilterDialog::FilterDialog(weld::Window* pParentWindow) + : GenericDialogController(pParentWindow, "uui/ui/filterselect.ui", "FilterSelectDialog") + , m_pFilterNames(nullptr) + , m_xFtURL(m_xBuilder->weld_label("url")) + , m_xLbFilters(m_xBuilder->weld_tree_view("filters")) +{ + m_xLbFilters->set_size_request(m_xLbFilters->get_approximate_digit_width() * 42, + m_xLbFilters->get_height_rows(15)); +} + +FilterDialog::~FilterDialog() +{ +} + +/*-************************************************************************************************************ + @short set file name on dialog control + @descr We convert given URL (it must be a URL!) into valid file name and show it on our dialog. + @param "sURL", URL for showing + @threadsafe no +*//*-*************************************************************************************************************/ +void FilterDialog::SetURL( const OUString& sURL ) +{ + // convert it and use given pure string as fallback if conversion failed + m_xFtURL->set_label(impl_buildUIFileName(sURL)); +} + +/*-************************************************************************************************************ + @short change list of filter names + @descr We save given pointer internal and use it to fill our listbox with given names. + Saved list pointer is used on method "AskForFilter()" too, to find user selected item + and return pointer into these list as result of operation. + So it's possible to call dialog again and again for different or same filter list + and ask user for his decision by best performance! + + @attention Don't free memory of given list after this call till object will die ... or + you call "ChangeFilters( NULL )"! Then we forget it too. + + @seealso method AskForFilter() + + @param "pFilterNames", pointer to list of filter names, which should be used for later operations. + @onerror We clear list box and forget our currently set filter information completely! + @threadsafe no +*//*-*************************************************************************************************************/ +void FilterDialog::ChangeFilters( const FilterNameList* pFilterNames ) +{ + m_pFilterNames = pFilterNames; + m_xLbFilters->clear(); + if( m_pFilterNames != nullptr ) + { + for( const auto& rItem : *m_pFilterNames ) + { + m_xLbFilters->append_text(rItem.sUI); + } + } +} + +/*-************************************************************************************************************ + @short ask user for his decision + @descr We show the dialog and if user finish it with "OK" - we try to find selected item in internal saved + name list (which you must set in "ChangeFilters()"!). If we return sal_True as result, you can use out + parameter "pSelectedItem" as pointer into your FilterNameList to get selected item really ... + but if we return sal_False ... user has cancel the dialog ... you should not do that. pSelectedItem is not + set to any valid value then. We don't change them ... + + @seealso method ChangeFilters() + + @param "pSelectedItem", returns result of selection as pointer into set list of filter names + (valid for function return sal_True only!) + @return true => pSelectedItem parameter points into name list and represent use decision + false => use has cancelled dialog (pSelectedItem is not valid then!) + + @onerror We return false ... but don't change pSelectedItem! + @threadsafe no +*//*-*************************************************************************************************************/ +bool FilterDialog::AskForFilter( FilterNameListPtr& pSelectedItem ) +{ + bool bSelected = false; + + if( m_pFilterNames != nullptr ) + { + if (m_xDialog->run() == RET_OK) + { + OUString sEntry = m_xLbFilters->get_selected_text(); + if( !sEntry.isEmpty() ) + { + int nPos = m_xLbFilters->get_selected_index(); + if( nPos < static_cast<int>(m_pFilterNames->size()) ) + { + pSelectedItem = m_pFilterNames->begin(); + pSelectedItem += nPos; + bSelected = ( pSelectedItem != m_pFilterNames->end() ); + } + } + } + } + + return bSelected; +} + +namespace { + +/*-************************************************************************************************************ + @short helper class to calculate length of given string + @descr Instances of it can be used as callback for INetURLObject::getAbbreviated() method to build + short URLs to show it on GUI. We use in ctor set OutputDevice to call special VCL method ... + + @seealso method OutputDevice::GetTextWidth() + @seealso method InetURLObject::getAbbreviated() + @threadsafe no +*//*-*************************************************************************************************************/ +class StringCalculator : public ::cppu::WeakImplHelper< css::util::XStringWidth > +{ + public: + explicit StringCalculator(weld::Widget* pDevice) + : m_pDevice(pDevice) + { + } + + sal_Int32 SAL_CALL queryStringWidth( const OUString& sString ) override + { + return static_cast<sal_Int32>(m_pDevice->get_pixel_size(sString).Width()); + } + + private: + weld::Widget* m_pDevice; +}; + +} + +/*-************************************************************************************************************ + @short try to build short name of given URL to show it n GUI + @descr We detect type of given URL automatically and build this short name depend on this type ... + If we couldn't make it right we return full given string without any changes ... + + @seealso method InetURLObject::getAbbreviated() + + @param "sName", file name + @return A short file name ... + + @onerror We return given name without any changes. + @threadsafe no +*//*-*************************************************************************************************************/ +OUString FilterDialog::impl_buildUIFileName( const OUString& sName ) +{ + OUString sShortName( sName ); + + if (osl::FileBase::getSystemPathFromFileURL(sName, sShortName) == osl::FileBase::E_None) + + { + // it's a system file... build short name by using osl functionality + } + else + { + // otherwise it's really a URL... build short name by using INetURLObject + css::uno::Reference< css::util::XStringWidth > xStringCalculator(new StringCalculator(m_xFtURL.get())); + if( xStringCalculator.is() ) + { + INetURLObject aBuilder ( sName ); + Size aSize = m_xLbFilters->get_preferred_size(); + sShortName = aBuilder.getAbbreviated( xStringCalculator, aSize.Width(), INetURLObject::DecodeMechanism::Unambiguous ); + } + } + + return sShortName; +} + +} // namespace uui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/fltdlg.hxx b/uui/source/fltdlg.hxx new file mode 100644 index 000000000..5f788073c --- /dev/null +++ b/uui/source/fltdlg.hxx @@ -0,0 +1,64 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_FLTDLG_HXX +#define INCLUDED_UUI_SOURCE_FLTDLG_HXX + +#include <vcl/weld.hxx> + +#include <vector> + +namespace uui +{ + +struct FilterNamePair +{ + OUString sInternal; + OUString sUI ; +}; + +typedef ::std::vector< FilterNamePair > FilterNameList ; +typedef FilterNameList::const_iterator FilterNameListPtr; + +class FilterDialog : public weld::GenericDialogController +{ + // public interface + public: + explicit FilterDialog(weld::Window* pParentWindow); + virtual ~FilterDialog() override; + void SetURL ( const OUString& sURL ); + void ChangeFilters( const FilterNameList* pFilterNames ); + bool AskForFilter ( FilterNameListPtr& pSelectedItem ); + + private: + OUString impl_buildUIFileName( const OUString& sURL ); + + // member + private: + const FilterNameList* m_pFilterNames; + std::unique_ptr<weld::Label> m_xFtURL; + std::unique_ptr<weld::TreeView> m_xLbFilters; + +}; // class FilterDialog + +} // namespace uui + +#endif // INCLUDED_UUI_SOURCE_FLTDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/getcontinuations.hxx b/uui/source/getcontinuations.hxx new file mode 100644 index 000000000..6ea1f55fa --- /dev/null +++ b/uui/source/getcontinuations.hxx @@ -0,0 +1,105 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_GETCONTINUATIONS_HXX +#define INCLUDED_UUI_SOURCE_GETCONTINUATIONS_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +namespace com::sun::star { + namespace task { + class XInteractionContinuation; + } +} + +template< class t1 > +bool setContinuation( + css::uno::Reference< css::task::XInteractionContinuation > const & rContinuation, + css::uno::Reference< t1 > * pContinuation) +{ + if (pContinuation && !pContinuation->is()) + { + pContinuation->set(rContinuation, css::uno::UNO_QUERY); + if (pContinuation->is()) + return true; + } + return false; +} + +template< class t1, class t2 > +void getContinuations( + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + css::uno::Reference< t1 > * pContinuation1, + css::uno::Reference< t2 > * pContinuation2) +{ + for (const auto& rContinuation : rContinuations) + { + if (setContinuation(rContinuation, pContinuation1)) + continue; + if (setContinuation(rContinuation, pContinuation2)) + continue; + } +} + +template< class t1, class t2, class t3 > +void getContinuations( + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + css::uno::Reference< t1 > * pContinuation1, + css::uno::Reference< t2 > * pContinuation2, + css::uno::Reference< t3 > * pContinuation3) +{ + for (const auto& rContinuation : rContinuations) + { + if (setContinuation(rContinuation, pContinuation1)) + continue; + if (setContinuation(rContinuation, pContinuation2)) + continue; + if (setContinuation(rContinuation, pContinuation3)) + continue; + } +} + +template< class t1, class t2, class t3, class t4 > +void getContinuations( + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + css::uno::Reference< t1 > * pContinuation1, + css::uno::Reference< t2 > * pContinuation2, + css::uno::Reference< t3 > * pContinuation3, + css::uno::Reference< t4 > * pContinuation4) +{ + for (const auto& rContinuation : rContinuations) + { + if (setContinuation(rContinuation, pContinuation1)) + continue; + if (setContinuation(rContinuation, pContinuation2)) + continue; + if (setContinuation(rContinuation, pContinuation3)) + continue; + if (setContinuation(rContinuation, pContinuation4)) + continue; + } +} + +#endif // INCLUDED_UUI_SOURCE_GETCONTINUATIONS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-authentication.cxx b/uui/source/iahndl-authentication.cxx new file mode 100644 index 000000000..ad975d3f9 --- /dev/null +++ b/uui/source/iahndl-authentication.cxx @@ -0,0 +1,747 @@ +/* -*- 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 . + */ + +#include <com/sun/star/task/DocumentPasswordRequest.hpp> +#include <com/sun/star/task/DocumentPasswordRequest2.hpp> +#include <com/sun/star/task/DocumentMSPasswordRequest.hpp> +#include <com/sun/star/task/DocumentMSPasswordRequest2.hpp> +#include <com/sun/star/task/MasterPasswordRequest.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionPassword.hpp> +#include <com/sun/star/task/XInteractionPassword2.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> +#include <com/sun/star/ucb/XInteractionAuthFallback.hpp> +#include <com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp> +#include <com/sun/star/ucb/URLAuthenticationRequest.hpp> + +#include <osl/diagnose.h> +#include <rtl/digest.h> +#include <rtl/ustrbuf.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/errinf.hxx> +#include <vcl/abstdlg.hxx> +#include <vcl/svapp.hxx> +#include <sal/log.hxx> + +#include "authfallbackdlg.hxx" +#include <strings.hrc> +#include "getcontinuations.hxx" +#include "passwordcontainer.hxx" +#include "loginerr.hxx" +#include "logindlg.hxx" +#include "masterpasscrtdlg.hxx" +#include "masterpassworddlg.hxx" +#include "passworddlg.hxx" + +#include "iahndl.hxx" + +#include <memory> + +using namespace com::sun::star; + +namespace { + +void +executeLoginDialog( + weld::Window* pParent, + LoginErrorInfo & rInfo, + OUString const & rRealm) +{ + SolarMutexGuard aGuard; + + bool bAccount = (rInfo.GetFlags() & LOGINERROR_FLAG_MODIFY_ACCOUNT) != 0; + bool bSavePassword = rInfo.GetCanRememberPassword(); + bool bCanUseSysCreds = rInfo.GetCanUseSystemCredentials(); + + LoginFlags nFlags = LoginFlags::NONE; + if (rInfo.GetErrorText().isEmpty()) + nFlags |= LoginFlags::NoErrorText; + if (!bAccount) + nFlags |= LoginFlags::NoAccount; + if (!(rInfo.GetFlags() & LOGINERROR_FLAG_MODIFY_USER_NAME)) + nFlags |= LoginFlags::UsernameReadonly; + + if (!bSavePassword) + nFlags |= LoginFlags::NoSavePassword; + + if (!bCanUseSysCreds) + nFlags |= LoginFlags::NoUseSysCreds; + + LoginDialog aDialog(pParent, nFlags, rInfo.GetServer(), rRealm); + if (!rInfo.GetErrorText().isEmpty()) + aDialog.SetErrorText(rInfo.GetErrorText()); + aDialog.SetName(rInfo.GetUserName()); + if (bAccount) + aDialog.ClearAccount(); + else + aDialog.ClearPassword(); + aDialog.SetPassword(rInfo.GetPassword()); + + if (bSavePassword) + { + std::locale aLocale(Translate::Create("uui")); + aDialog.SetSavePasswordText( + Translate::get(rInfo.GetIsRememberPersistent() + ? RID_SAVE_PASSWORD + : RID_KEEP_PASSWORD, + aLocale)); + + aDialog.SetSavePassword(rInfo.GetIsRememberPassword()); + } + + if ( bCanUseSysCreds ) + aDialog.SetUseSystemCredentials( rInfo.GetIsUseSystemCredentials() ); + + rInfo.SetResult(aDialog.run() == RET_OK ? DialogMask::ButtonsOk : + DialogMask::ButtonsCancel); + rInfo.SetUserName(aDialog.GetName()); + rInfo.SetPassword(aDialog.GetPassword()); + rInfo.SetAccount(aDialog.GetAccount()); + rInfo.SetIsRememberPassword(aDialog.IsSavePassword()); + + if ( bCanUseSysCreds ) + rInfo.SetIsUseSystemCredentials( aDialog.IsUseSystemCredentials() ); +} + +void getRememberModes( + uno::Sequence< ucb::RememberAuthentication > const & rRememberModes, + ucb::RememberAuthentication & rPreferredMode, + ucb::RememberAuthentication & rAlternateMode ) +{ + sal_Int32 nCount = rRememberModes.getLength(); + OSL_ENSURE( (nCount > 0) && (nCount < 4), + "ucb::RememberAuthentication sequence size mismatch!" ); + if ( nCount == 1 ) + { + rPreferredMode = rAlternateMode = rRememberModes[ 0 ]; + return; + } + else + { + bool bHasRememberModeSession = false; + bool bHasRememberModePersistent = false; + + for (const auto& rRememberMode : rRememberModes) + { + switch ( rRememberMode ) + { + case ucb::RememberAuthentication_NO: + break; + case ucb::RememberAuthentication_SESSION: + bHasRememberModeSession = true; + break; + case ucb::RememberAuthentication_PERSISTENT: + bHasRememberModePersistent = true; + break; + default: + SAL_WARN( "uui", "Unsupported RememberAuthentication value" << static_cast<sal_Int32>(rRememberMode) ); + break; + } + } + + if (bHasRememberModePersistent) + { + rPreferredMode = ucb::RememberAuthentication_PERSISTENT; + if (bHasRememberModeSession) + rAlternateMode = ucb::RememberAuthentication_SESSION; + else + rAlternateMode = ucb::RememberAuthentication_NO; + } + else + { + rPreferredMode = ucb::RememberAuthentication_SESSION; + rAlternateMode = ucb::RememberAuthentication_NO; + } + } +} + +void +handleAuthenticationRequest_( + weld::Window * pParent, + uno::Reference< task::XInteractionHandler2 > const & xIH, + uno::Reference< uno::XComponentContext > const & xContext, + ucb::AuthenticationRequest const & rRequest, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, + const OUString & rURL) +{ + uno::Reference< task::XInteractionRetry > xRetry; + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< ucb::XInteractionSupplyAuthentication > + xSupplyAuthentication; + uno::Reference< ucb::XInteractionSupplyAuthentication2 > + xSupplyAuthentication2; + getContinuations(rContinuations, &xRetry, &xAbort, &xSupplyAuthentication); + if (xSupplyAuthentication.is()) + xSupplyAuthentication2.set(xSupplyAuthentication, uno::UNO_QUERY); + + + // First, try to obtain credentials from password container service. + uui::PasswordContainerHelper aPwContainerHelper(xContext); + if (aPwContainerHelper.handleAuthenticationRequest(rRequest, + xSupplyAuthentication, + rURL, + xIH)) + { + xSupplyAuthentication->select(); + return; + } + + + // Second, try to obtain credentials from user via password dialog. + ucb::RememberAuthentication eDefaultRememberMode + = ucb::RememberAuthentication_SESSION; + ucb::RememberAuthentication ePreferredRememberMode + = eDefaultRememberMode; + ucb::RememberAuthentication eAlternateRememberMode + = ucb::RememberAuthentication_NO; + + if (xSupplyAuthentication.is()) + { + getRememberModes( + xSupplyAuthentication->getRememberPasswordModes( + eDefaultRememberMode), + ePreferredRememberMode, + eAlternateRememberMode); + } + + bool bCanUseSystemCredentials; + sal_Bool bDefaultUseSystemCredentials; + if (xSupplyAuthentication2.is()) + { + bCanUseSystemCredentials + = xSupplyAuthentication2->canUseSystemCredentials( + bDefaultUseSystemCredentials); + } + else + { + bCanUseSystemCredentials = false; + bDefaultUseSystemCredentials = false; + } + + LoginErrorInfo aInfo; + aInfo.SetServer(rRequest.ServerName); + if (rRequest.HasAccount) + aInfo.SetAccount(rRequest.Account); + if (rRequest.HasUserName) + aInfo.SetUserName(rRequest.UserName); + if (rRequest.HasPassword) + aInfo.SetPassword(rRequest.Password); + aInfo.SetErrorText(rRequest.Diagnostic); + + aInfo.SetCanRememberPassword( + ePreferredRememberMode != eAlternateRememberMode); + aInfo.SetIsRememberPassword( + ePreferredRememberMode == eDefaultRememberMode); + aInfo.SetIsRememberPersistent( + ePreferredRememberMode == ucb::RememberAuthentication_PERSISTENT); + + aInfo.SetCanUseSystemCredentials(bCanUseSystemCredentials); + aInfo.SetIsUseSystemCredentials( bDefaultUseSystemCredentials ); + aInfo.SetModifyAccount(rRequest.HasAccount + && xSupplyAuthentication.is() + && xSupplyAuthentication->canSetAccount()); + aInfo.SetModifyUserName(rRequest.HasUserName + && xSupplyAuthentication.is() + && xSupplyAuthentication->canSetUserName()); + executeLoginDialog(pParent, + aInfo, + rRequest.HasRealm ? rRequest.Realm : OUString()); + switch (aInfo.GetResult()) + { + case DialogMask::ButtonsOk: + if (xSupplyAuthentication.is()) + { + if (xSupplyAuthentication->canSetUserName()) + xSupplyAuthentication->setUserName(aInfo.GetUserName()); + if (xSupplyAuthentication->canSetPassword()) + xSupplyAuthentication->setPassword(aInfo.GetPassword()); + + if (ePreferredRememberMode != eAlternateRememberMode) + { + // user had the choice. + if (aInfo.GetIsRememberPassword()) + xSupplyAuthentication->setRememberPassword( + ePreferredRememberMode); + else + xSupplyAuthentication->setRememberPassword( + eAlternateRememberMode); + } + else + { + // user had no choice. + xSupplyAuthentication->setRememberPassword( + ePreferredRememberMode); + } + + if (rRequest.HasRealm) + { + if (xSupplyAuthentication->canSetRealm()) + xSupplyAuthentication->setRealm(aInfo.GetAccount()); + } + else if (xSupplyAuthentication->canSetAccount()) + xSupplyAuthentication->setAccount(aInfo.GetAccount()); + + if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials ) + xSupplyAuthentication2->setUseSystemCredentials( + aInfo.GetIsUseSystemCredentials() ); + + xSupplyAuthentication->select(); + } + + + // Third, store credentials in password container. + + if ( aInfo.GetIsUseSystemCredentials() ) + { + if (aInfo.GetIsRememberPassword()) + { + if (!aPwContainerHelper.addRecord( + !rURL.isEmpty() ? rURL : rRequest.ServerName, + OUString(), // empty u/p -> sys creds + uno::Sequence< OUString >(), + xIH, + ePreferredRememberMode + == ucb::RememberAuthentication_PERSISTENT)) + { + xSupplyAuthentication->setRememberPassword( + ucb::RememberAuthentication_NO); + } + } + else if (eAlternateRememberMode + == ucb::RememberAuthentication_SESSION) + { + if (!aPwContainerHelper.addRecord( + !rURL.isEmpty() ? rURL : rRequest.ServerName, + OUString(), // empty u/p -> sys creds + uno::Sequence< OUString >(), + xIH, + false /* SESSION */)) + { + xSupplyAuthentication->setRememberPassword( + ucb::RememberAuthentication_NO); + } + } + } + // Empty user name can not be valid: + else if (!aInfo.GetUserName().isEmpty()) + { + uno::Sequence< OUString > + aPassList(aInfo.GetAccount().isEmpty() ? 1 : 2); + aPassList[0] = aInfo.GetPassword(); + if (!aInfo.GetAccount().isEmpty()) + aPassList[1] = aInfo.GetAccount(); + + if (aInfo.GetIsRememberPassword()) + { + if (!aPwContainerHelper.addRecord( + !rURL.isEmpty() ? rURL : rRequest.ServerName, + aInfo.GetUserName(), + aPassList, + xIH, + ePreferredRememberMode + == ucb::RememberAuthentication_PERSISTENT)) + { + xSupplyAuthentication->setRememberPassword( + ucb::RememberAuthentication_NO); + } + } + else if (eAlternateRememberMode + == ucb::RememberAuthentication_SESSION) + { + if (!aPwContainerHelper.addRecord( + !rURL.isEmpty() ? rURL : rRequest.ServerName, + aInfo.GetUserName(), + aPassList, + xIH, + false /* SESSION */)) + { + xSupplyAuthentication->setRememberPassword( + ucb::RememberAuthentication_NO); + } + } + } + break; + + case DialogMask::ButtonsRetry: + if (xRetry.is()) + xRetry->select(); + break; + + default: + if (xAbort.is()) + xAbort->select(); + break; + } +} + +void +executeMasterPasswordDialog( + weld::Window* pParent, + LoginErrorInfo & rInfo, + task::PasswordRequestMode nMode) +{ + OString aMaster; + { + SolarMutexGuard aGuard; + + std::locale aResLocale(Translate::Create("uui")); + if( nMode == task::PasswordRequestMode_PASSWORD_CREATE ) + { + MasterPasswordCreateDialog aDialog(pParent, aResLocale); + rInfo.SetResult(aDialog.run() + == RET_OK ? DialogMask::ButtonsOk : DialogMask::ButtonsCancel); + aMaster = OUStringToOString( + aDialog.GetMasterPassword(), RTL_TEXTENCODING_UTF8); + } + else + { + MasterPasswordDialog aDialog(pParent, nMode, aResLocale); + rInfo.SetResult(aDialog.run() + == RET_OK ? DialogMask::ButtonsOk : DialogMask::ButtonsCancel); + aMaster = OUStringToOString( + aDialog.GetMasterPassword(), RTL_TEXTENCODING_UTF8); + } + } + + sal_uInt8 aKey[RTL_DIGEST_LENGTH_MD5]; + // FIXME this is subject to the SHA1-bug tdf#114939 - but this + // MasterPassword stuff is just stored in the UserInstallation, + // so no interop concerns + rtl_digest_PBKDF2(aKey, + RTL_DIGEST_LENGTH_MD5, + reinterpret_cast< sal_uInt8 const * >(aMaster.getStr()), + aMaster.getLength(), + reinterpret_cast< sal_uInt8 const * >( + "3B5509ABA6BC42D9A3A1F3DAD49E56A51"), + 32, + 1000); + + OUStringBuffer aBuffer; + for (sal_uInt8 i : aKey) + { + aBuffer.append(static_cast< sal_Unicode >('a' + (i >> 4))); + aBuffer.append(static_cast< sal_Unicode >('a' + (i & 15))); + } + rInfo.SetPassword(aBuffer.makeStringAndClear()); +} + +void +handleMasterPasswordRequest_( + weld::Window * pParent, + task::PasswordRequestMode nMode, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations) +{ + uno::Reference< task::XInteractionRetry > xRetry; + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< ucb::XInteractionSupplyAuthentication > + xSupplyAuthentication; + getContinuations(rContinuations, &xRetry, &xAbort, &xSupplyAuthentication); + LoginErrorInfo aInfo; + + // in case of master password a hash code is returned + executeMasterPasswordDialog(pParent, aInfo, nMode); + + switch (aInfo.GetResult()) + { + case DialogMask::ButtonsOk: + if (xSupplyAuthentication.is()) + { + if (xSupplyAuthentication->canSetPassword()) + xSupplyAuthentication->setPassword(aInfo.GetPassword()); + xSupplyAuthentication->select(); + } + break; + + case DialogMask::ButtonsRetry: + if (xRetry.is()) + xRetry->select(); + break; + + default: + if (xAbort.is()) + xAbort->select(); + break; + } +} + +void +executePasswordDialog( + weld::Window * pParent, + LoginErrorInfo & rInfo, + task::PasswordRequestMode nMode, + const OUString& aDocName, + sal_uInt16 nMaxPasswordLen, + bool bIsPasswordToModify, + bool bIsSimplePasswordRequest ) +{ + SolarMutexGuard aGuard; + + std::locale aResLocale(Translate::Create("uui")); + if( nMode == task::PasswordRequestMode_PASSWORD_CREATE ) + { + if (bIsSimplePasswordRequest) + { + std::unique_ptr<PasswordDialog> xDialog(new PasswordDialog(pParent, nMode, + aResLocale, aDocName, bIsPasswordToModify, bIsSimplePasswordRequest)); + xDialog->SetMinLen(0); + + rInfo.SetResult(xDialog->run() == RET_OK ? DialogMask::ButtonsOk : DialogMask::ButtonsCancel); + rInfo.SetPassword(xDialog->GetPassword()); + } + else + { + VclAbstractDialogFactory * pFact = VclAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractPasswordToOpenModifyDialog> const pDialog( + pFact->CreatePasswordToOpenModifyDialog(pParent, nMaxPasswordLen, bIsPasswordToModify)); + + rInfo.SetResult( pDialog->Execute() == RET_OK ? DialogMask::ButtonsOk : DialogMask::ButtonsCancel ); + rInfo.SetPassword( pDialog->GetPasswordToOpen() ); + rInfo.SetPasswordToModify( pDialog->GetPasswordToModify() ); + rInfo.SetRecommendToOpenReadonly( pDialog->IsRecommendToOpenReadonly() ); + } + } + else // enter password or reenter password + { + std::unique_ptr<PasswordDialog> xDialog(new PasswordDialog(pParent, nMode, + aResLocale, aDocName, bIsPasswordToModify, bIsSimplePasswordRequest)); + xDialog->SetMinLen(0); + + rInfo.SetResult(xDialog->run() == RET_OK ? DialogMask::ButtonsOk : DialogMask::ButtonsCancel); + rInfo.SetPassword(bIsPasswordToModify ? OUString() : xDialog->GetPassword()); + rInfo.SetPasswordToModify(bIsPasswordToModify ? xDialog->GetPassword() : OUString()); + } +} + +void +handlePasswordRequest_( + weld::Window * pParent, + task::PasswordRequestMode nMode, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, + const OUString& aDocumentName, + sal_uInt16 nMaxPasswordLen, + bool bIsPasswordToModify, + bool bIsSimplePasswordRequest = false ) +{ + uno::Reference< task::XInteractionRetry > xRetry; + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< task::XInteractionPassword > xPassword; + uno::Reference< task::XInteractionPassword2 > xPassword2; + getContinuations(rContinuations, &xRetry, &xAbort, &xPassword2, &xPassword); + + if ( xPassword2.is() && !xPassword.is() ) + xPassword.set( xPassword2, uno::UNO_QUERY_THROW ); + + LoginErrorInfo aInfo; + + executePasswordDialog( pParent, aInfo, nMode, + aDocumentName, nMaxPasswordLen, bIsPasswordToModify, bIsSimplePasswordRequest ); + + switch (aInfo.GetResult()) + { + case DialogMask::ButtonsOk: + OSL_ENSURE( !bIsPasswordToModify || xPassword2.is(), "PasswordToModify is requested, but there is no Interaction!" ); + if (xPassword.is()) + { + if (xPassword2.is()) + { + xPassword2->setPasswordToModify( aInfo.GetPasswordToModify() ); + xPassword2->setRecommendReadOnly( aInfo.IsRecommendToOpenReadonly() ); + } + + xPassword->setPassword(aInfo.GetPassword()); + xPassword->select(); + } + break; + + case DialogMask::ButtonsRetry: + if (xRetry.is()) + xRetry->select(); + break; + + default: + if (xAbort.is()) + xAbort->select(); + break; + } +} + +} // namespace + +bool +UUIInteractionHelper::handleAuthenticationRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + + ucb::URLAuthenticationRequest aURLAuthenticationRequest; + if (aAnyRequest >>= aURLAuthenticationRequest) + { + handleAuthenticationRequest_(Application::GetFrameWeld(xParent), + getInteractionHandler(), + m_xContext, + aURLAuthenticationRequest, + rRequest->getContinuations(), + aURLAuthenticationRequest.URL); + return true; + } + + ucb::AuthenticationRequest aAuthenticationRequest; + if (aAnyRequest >>= aAuthenticationRequest) + { + handleAuthenticationRequest_(Application::GetFrameWeld(xParent), + getInteractionHandler(), + m_xContext, + aAuthenticationRequest, + rRequest->getContinuations(), + OUString()); + return true; + } + return false; +} + +bool +UUIInteractionHelper::handleMasterPasswordRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + task::MasterPasswordRequest aMasterPasswordRequest; + if (aAnyRequest >>= aMasterPasswordRequest) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + + handleMasterPasswordRequest_(Application::GetFrameWeld(xParent), + aMasterPasswordRequest.Mode, + rRequest->getContinuations()); + return true; + } + return false; +} + +bool +UUIInteractionHelper::handlePasswordRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + // parameters to be filled for the call to handlePasswordRequest_ + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + task::PasswordRequestMode nMode = task::PasswordRequestMode_PASSWORD_ENTER; + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations = rRequest->getContinuations(); + OUString aDocumentName; + sal_uInt16 nMaxPasswordLen = 0; // any length + bool bIsPasswordToModify = false; + + bool bDoHandleRequest = false; + + uno::Any aAnyRequest(rRequest->getRequest()); + + do + { + task::DocumentPasswordRequest2 aDocumentPasswordRequest2; + if (aAnyRequest >>= aDocumentPasswordRequest2) + { + nMode = aDocumentPasswordRequest2.Mode; + aDocumentName = aDocumentPasswordRequest2.Name; + bIsPasswordToModify = aDocumentPasswordRequest2.IsRequestPasswordToModify; + + bDoHandleRequest = true; + break; // do + } + + task::DocumentPasswordRequest aDocumentPasswordRequest; + if (aAnyRequest >>= aDocumentPasswordRequest) + { + nMode = aDocumentPasswordRequest.Mode; + aDocumentName = aDocumentPasswordRequest.Name; + + bDoHandleRequest = true; + break; // do + } + + task::DocumentMSPasswordRequest2 aDocumentMSPasswordRequest2; + if (aAnyRequest >>= aDocumentMSPasswordRequest2) + { + nMode = aDocumentMSPasswordRequest2.Mode; + aDocumentName = aDocumentMSPasswordRequest2.Name; + nMaxPasswordLen = 15; + bIsPasswordToModify = aDocumentMSPasswordRequest2.IsRequestPasswordToModify; + + bDoHandleRequest = true; + break; // do + } + + task::DocumentMSPasswordRequest aDocumentMSPasswordRequest; + if (aAnyRequest >>= aDocumentMSPasswordRequest) + { + nMode = aDocumentMSPasswordRequest.Mode; + aDocumentName = aDocumentMSPasswordRequest.Name; + nMaxPasswordLen = 15; + + bDoHandleRequest = true; + break; // do + } + } + while (false); + + if (bDoHandleRequest) + { + handlePasswordRequest_( Application::GetFrameWeld(xParent), nMode, rContinuations, + aDocumentName, nMaxPasswordLen, bIsPasswordToModify ); + return true; + } + + task::PasswordRequest aPasswordRequest; + if( aAnyRequest >>= aPasswordRequest ) + { + handlePasswordRequest_(Application::GetFrameWeld(xParent), + aPasswordRequest.Mode, + rRequest->getContinuations(), + OUString(), + 0 /* sal_uInt16 nMaxPasswordLen */, + false /* bool bIsPasswordToModify */, + true /* bool bIsSimplePasswordRequest */ ); + return true; + } + + return false; +} + +void +UUIInteractionHelper::handleAuthFallbackRequest( const OUString & instructions, + const OUString & url, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations ) +{ + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + AuthFallbackDlg dlg(Application::GetFrameWeld(xParent), instructions, url); + int retCode = dlg.run(); + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< ucb::XInteractionAuthFallback > xAuthFallback; + getContinuations(rContinuations, &xAbort, &xAuthFallback); + + if( retCode == RET_OK && xAuthFallback.is( ) ) + { + xAuthFallback->setCode(dlg.GetCode()); + xAuthFallback->select( ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-errorhandler.cxx b/uui/source/iahndl-errorhandler.cxx new file mode 100644 index 000000000..56f54255d --- /dev/null +++ b/uui/source/iahndl-errorhandler.cxx @@ -0,0 +1,292 @@ +/* -*- 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 . + */ + +#include <vcl/errinf.hxx> +#include <vcl/svapp.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/weld.hxx> + +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> + +#include <svx/svxerr.hxx> +#include <unotools/resmgr.hxx> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> + +#include <ids.hrc> +#include "getcontinuations.hxx" + +#include "iahndl.hxx" +#include <memory> + +using namespace com::sun::star; + +namespace { + +enum class MessageBoxStyle { + NONE = 0x0000, + Ok = 0x0001, + OkCancel = 0x0002, + YesNo = 0x0004, + YesNoCancel = 0x0008, + RetryCancel = 0x0010 +}; + +DialogMask +executeErrorDialog( + weld::Window* pParent, + task::InteractionClassification eClassification, + OUString const & rContext, + OUString const & rMessage, + MessageBoxStyle nButtonMask) +{ + SolarMutexGuard aGuard; + + OUStringBuffer aText(rContext); + if (!rContext.isEmpty() && !rMessage.isEmpty()) + aText.append(":\n"); + //TODO! must be internationalized + aText.append(rMessage); + + std::unique_ptr<weld::MessageDialog> xBox; + + switch (eClassification) + { + case task::InteractionClassification_ERROR: + xBox.reset(Application::CreateMessageDialog(pParent, + VclMessageType::Error, VclButtonsType::NONE, aText.makeStringAndClear())); + break; + case task::InteractionClassification_WARNING: + xBox.reset(Application::CreateMessageDialog(pParent, + VclMessageType::Warning, VclButtonsType::NONE, aText.makeStringAndClear())); + break; + case task::InteractionClassification_INFO: + xBox.reset(Application::CreateMessageDialog(pParent, + VclMessageType::Info, VclButtonsType::NONE, aText.makeStringAndClear())); + break; + case task::InteractionClassification_QUERY: + xBox.reset(Application::CreateMessageDialog(pParent, + VclMessageType::Question, VclButtonsType::NONE, aText.makeStringAndClear())); + break; + default: + assert(false); + break; + } + + + switch (nButtonMask) + { + case MessageBoxStyle::NONE: + break; + case MessageBoxStyle::Ok: + xBox->add_button(GetStandardText(StandardButtonType::OK), static_cast<int>(DialogMask::ButtonsOk)); + break; + case MessageBoxStyle::OkCancel: + xBox->add_button(GetStandardText(StandardButtonType::OK), static_cast<int>(DialogMask::ButtonsOk)); + xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel)); + break; + case MessageBoxStyle::YesNo: + xBox->add_button(GetStandardText(StandardButtonType::Yes), static_cast<int>(DialogMask::ButtonsYes)); + xBox->add_button(GetStandardText(StandardButtonType::No), static_cast<int>(DialogMask::ButtonsNo)); + break; + case MessageBoxStyle::YesNoCancel: + xBox->add_button(GetStandardText(StandardButtonType::Yes), static_cast<int>(DialogMask::ButtonsYes)); + xBox->add_button(GetStandardText(StandardButtonType::No), static_cast<int>(DialogMask::ButtonsNo)); + xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel)); + break; + case MessageBoxStyle::RetryCancel: + xBox->add_button(GetStandardText(StandardButtonType::Retry), static_cast<int>(DialogMask::ButtonsRetry)); + xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel)); + break; + } + + return static_cast<DialogMask>(xBox->run()); +} + +} + +void +UUIInteractionHelper::handleErrorHandlerRequest( + task::InteractionClassification eClassification, + ErrCode nErrorCode, + std::vector< OUString > const & rArguments, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString) +{ + if (bObtainErrorStringOnly) + { + bHasErrorString = isInformationalErrorMessageRequest(rContinuations); + if (!bHasErrorString) + return; + } + + OUString aMessage; + { + enum Source { SOURCE_DEFAULT, SOURCE_SVX, SOURCE_UUI }; + static char const * const aManager[3] = { "svt", "svx", "uui" }; + static const ErrMsgCode* const aId[3] + = { RID_ERRHDL, + RID_SVXERRCODE, + RID_UUI_ERRHDL }; + ErrCodeArea nErrorArea = nErrorCode.GetArea(); + Source eSource = + nErrorArea < ErrCodeArea::Svx ? SOURCE_DEFAULT + : nErrorArea == ErrCodeArea::Svx ? SOURCE_SVX : SOURCE_UUI; + + std::locale aResLocale = Translate::Create(aManager[eSource]); + ErrorResource aErrorResource(aId[eSource], aResLocale); + if (!aErrorResource.getString(nErrorCode, aMessage)) + return; + } + + aMessage = replaceMessageWithArguments( aMessage, rArguments ); + + if (bObtainErrorStringOnly) + { + rErrorString = aMessage; + return; + } + else + { + //TODO! It can happen that the buttons calculated below do not match + // the error text from the resource (e.g., some text that is not a + // question, but YES and NO buttons). Some error texts have + // ExtraData that specifies a set of buttons, but that data is not + // really useful, because a single error text may well make sense + // both with only an OK button and with RETRY and CANCEL buttons. + + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionDisapprove > xDisapprove; + uno::Reference< task::XInteractionRetry > xRetry; + uno::Reference< task::XInteractionAbort > xAbort; + getContinuations( + rContinuations, &xApprove, &xDisapprove, &xRetry, &xAbort); + + // The following mapping uses the bit mask + // Approve = 8, + // Disapprove = 4, + // Retry = 2, + // Abort = 1 + + // The mapping has five properties on which the code to select the + // correct continuation relies: + // 1 The OK button is mapped to Approve if that is available, + // otherwise to Abort if that is available, otherwise to none. + // 2 The CANCEL button is always mapped to Abort. + // 3 The RETRY button is always mapped to Retry. + // 4 The NO button is always mapped to Disapprove. + // 5 The YES button is always mapped to Approve. + + // Because the WinBits button combinations are quite restricted, not + // every request can be served here. + + // Finally, it seems to be better to leave default button + // determination to VCL (the favouring of CANCEL as default button + // seems to not always be what the user wants)... + MessageBoxStyle const aButtonMask[16] + = { MessageBoxStyle::NONE, + MessageBoxStyle::Ok /*| MessBoxStyle::DefaultOk*/, // Abort + MessageBoxStyle::NONE, + MessageBoxStyle::RetryCancel /*| MessBoxStyle::DefaultCancel*/, // Retry, Abort + MessageBoxStyle::NONE, + MessageBoxStyle::NONE, + MessageBoxStyle::NONE, + MessageBoxStyle::NONE, + MessageBoxStyle::Ok /*| MessBoxStyle::DefaultOk*/, // Approve + MessageBoxStyle::OkCancel /*| MessBoxStyle::DefaultCancel*/, // Approve, Abort + MessageBoxStyle::NONE, + MessageBoxStyle::NONE, + MessageBoxStyle::YesNo /*| MessBoxStyle::DefaultNo*/, // Approve, Disapprove + MessageBoxStyle::YesNoCancel /*| MessBoxStyle::DefaultCancel*/, + // Approve, Disapprove, Abort + MessageBoxStyle::NONE, + MessageBoxStyle::NONE }; + + MessageBoxStyle nButtonMask = aButtonMask[(xApprove.is() ? 8 : 0) + | (xDisapprove.is() ? 4 : 0) + | (xRetry.is() ? 2 : 0) + | (xAbort.is() ? 1 : 0)]; + if (nButtonMask == MessageBoxStyle::NONE) + return; + + //TODO! remove this backwards compatibility? + OUString aContext(m_aContextParam); + if (aContext.isEmpty() && nErrorCode != ERRCODE_NONE) + { + SolarMutexGuard aGuard; + ErrorContext * pContext = ErrorContext::GetContext(); + if (pContext) + { + OUString aContextString; + if (pContext->GetString(nErrorCode, aContextString)) + aContext = aContextString; + } + } + + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + DialogMask nResult = executeErrorDialog(Application::GetFrameWeld(xParent), + eClassification, aContext, aMessage, nButtonMask ); + + switch (nResult) + { + case DialogMask::ButtonsOk: + OSL_ENSURE(xApprove.is() || xAbort.is(), "unexpected situation"); + if (xApprove.is()) + xApprove->select(); + else if (xAbort.is()) + xAbort->select(); + break; + + case DialogMask::ButtonsCancel: + OSL_ENSURE(xAbort.is(), "unexpected situation"); + if (xAbort.is()) + xAbort->select(); + break; + + case DialogMask::ButtonsRetry: + OSL_ENSURE(xRetry.is(), "unexpected situation"); + if (xRetry.is()) + xRetry->select(); + break; + + case DialogMask::ButtonsNo: + OSL_ENSURE(xDisapprove.is(), "unexpected situation"); + if (xDisapprove.is()) + xDisapprove->select(); + break; + + case DialogMask::ButtonsYes: + OSL_ENSURE(xApprove.is(), "unexpected situation"); + if (xApprove.is()) + xApprove->select(); + break; + + default: break; + } + + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-filter.cxx b/uui/source/iahndl-filter.cxx new file mode 100644 index 000000000..706c568aa --- /dev/null +++ b/uui/source/iahndl-filter.cxx @@ -0,0 +1,315 @@ +/* -*- 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 . + */ + +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/document/FilterOptionsRequest.hpp> +#include <com/sun/star/document/NoSuchFilterRequest.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XInteractionFilterOptions.hpp> +#include <com/sun/star/document/XInteractionFilterSelect.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> + +#include <comphelper/propertysequence.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <vcl/svapp.hxx> + +#include "getcontinuations.hxx" +#include "fltdlg.hxx" + +#include "iahndl.hxx" + +using namespace com::sun::star; + +namespace { + +void +executeFilterDialog( + weld::Window* pParent , + OUString const & rURL , + uui::FilterNameList const & rFilters, + OUString & rFilter ) +{ + SolarMutexGuard aGuard; + + uui::FilterDialog aDialog(pParent); + + aDialog.SetURL(rURL); + aDialog.ChangeFilters(&rFilters); + + uui::FilterNameListPtr pSelected = rFilters.end(); + if (aDialog.AskForFilter(pSelected)) + { + rFilter = pSelected->sInternal; + } +} + +void +handleNoSuchFilterRequest_( + weld::Window* pParent, + uno::Reference< uno::XComponentContext > const & xContext, + document::NoSuchFilterRequest const & rRequest, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations ) +{ + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< document::XInteractionFilterSelect > xFilterTransport; + getContinuations(rContinuations, &xAbort, &xFilterTransport); + + // check necessary resources - if they don't exist - abort or + // break this operation + if (!xAbort.is()) + return; + + if (!xFilterTransport.is()) + { + xAbort->select(); + return; + } + + uno::Reference< container::XContainerQuery > xFilterContainer; + try + { + xFilterContainer.set( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.document.FilterFactory", xContext ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + } + + if (!xFilterContainer.is()) + { + xAbort->select(); + return; + } + + uui::FilterNameList lNames; + + // Note: We look for all filters here which match the following criteria: + // - they are import filters as minimum (of course they can + // support export too) + // - we don't show any filter which are flagged as "don't show it + // at the UI" or "they are not installed" + // - we ignore filters, which have not set any valid + // DocumentService (e.g. our pure graphic filters) + // - we show it sorted by her UIName's + // - We don't use the order flag or prefer default filters. + // (Because this list shows all filters and the user should + // find his filter very easy by his UIName ...) + // - We use "_query_all" here ... but we filter graphic filters + // out by using DocumentService property later! + uno::Reference< container::XEnumeration > xFilters + = xFilterContainer->createSubSetEnumerationByQuery( + "_query_all:sort_prop=uiname:iflags=1:eflags=143360"); + while (xFilters->hasMoreElements()) + { + try + { + ::comphelper::SequenceAsHashMap lProps(xFilters->nextElement()); + uui::FilterNamePair aPair; + + aPair.sInternal = lProps.getUnpackedValueOrDefault( + "Name", OUString()); + aPair.sUI = lProps.getUnpackedValueOrDefault( + "UIName", OUString()); + if ( aPair.sInternal.isEmpty() || aPair.sUI.isEmpty() ) + { + continue; + } + lNames.push_back( aPair ); + } + catch(const uno::RuntimeException&) + { + throw; + } + catch(const uno::Exception&) + { + continue; + } + } + + // no list available for showing + // -> abort operation + if (lNames.empty()) + { + xAbort->select(); + return; + } + + // let the user select the right filter + OUString sSelectedFilter; + executeFilterDialog( pParent, + rRequest.URL, + lNames, + sSelectedFilter ); + + // If he doesn't select anyone + // -> abort operation + if (sSelectedFilter.isEmpty()) + { + xAbort->select(); + return; + } + + // otherwise set it for return + xFilterTransport->setFilter( sSelectedFilter ); + xFilterTransport->select(); +} + +void +handleFilterOptionsRequest_( + uno::Reference<awt::XWindow> const & rWindow, + uno::Reference< uno::XComponentContext > const & xContext, + document::FilterOptionsRequest const & rRequest, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations) +{ + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< document::XInteractionFilterOptions > xFilterOptions; + getContinuations(rContinuations, &xAbort, &xFilterOptions); + + uno::Reference< container::XNameAccess > xFilterCFG; + try + { + xFilterCFG.set( xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.document.FilterFactory", xContext ), + uno::UNO_QUERY ); + } + catch ( uno::Exception const & ) + { + } + + if( xFilterCFG.is() && rRequest.rProperties.hasElements() ) + { + try + { + OUString aFilterName; + auto pProperty = std::find_if(rRequest.rProperties.begin(), rRequest.rProperties.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "FilterName"; }); + if (pProperty != rRequest.rProperties.end()) + { + pProperty->Value >>= aFilterName; + } + + uno::Sequence < beans::PropertyValue > aProps; + if ( xFilterCFG->getByName( aFilterName ) >>= aProps ) + { + auto pProp = std::find_if(aProps.begin(), aProps.end(), + [](const beans::PropertyValue& rProp) { return rProp.Name == "UIComponent"; }); + if (pProp != aProps.end()) + { + OUString aServiceName; + pProp->Value >>= aServiceName; + if( !aServiceName.isEmpty() ) + { + uno::Sequence<uno::Any> aDialogArgs(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", uno::Any(rWindow)}, + })); + + uno::Reference< + ui::dialogs::XExecutableDialog > xFilterDialog( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + aServiceName, aDialogArgs, xContext ), + uno::UNO_QUERY ); + + uno::Reference< beans::XPropertyAccess > + xFilterProperties( xFilterDialog, + uno::UNO_QUERY ); + + if( xFilterDialog.is() && xFilterProperties.is() ) + { + uno::Reference< + document::XImporter > xImporter( + xFilterDialog, uno::UNO_QUERY ); + if( xImporter.is() ) + xImporter->setTargetDocument( rRequest.rModel ); + + xFilterProperties->setPropertyValues( + rRequest.rProperties ); + + if( xFilterDialog->execute() ) + { + xFilterOptions->setFilterOptions( + xFilterProperties->getPropertyValues() ); + xFilterOptions->select(); + return; + } + } + } + } + } + } + catch( container::NoSuchElementException& ) + { + // the filter name is unknown + } + catch( uno::Exception& ) + { + } + } + + xAbort->select(); +} + +} // namespace + +bool +UUIInteractionHelper::handleNoSuchFilterRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + document::NoSuchFilterRequest aNoSuchFilterRequest; + if (aAnyRequest >>= aNoSuchFilterRequest) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleNoSuchFilterRequest_(Application::GetFrameWeld(xParent), + m_xContext, + aNoSuchFilterRequest, + rRequest->getContinuations()); + return true; + } + return false; +} + +bool +UUIInteractionHelper::handleFilterOptionsRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + document::FilterOptionsRequest aFilterOptionsRequest; + if (aAnyRequest >>= aFilterOptionsRequest) + { + handleFilterOptionsRequest_(getParentXWindow(), + m_xContext, + aFilterOptionsRequest, + rRequest->getContinuations()); + return true; + } + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-ioexceptions.cxx b/uui/source/iahndl-ioexceptions.cxx new file mode 100644 index 000000000..6da1ea3a6 --- /dev/null +++ b/uui/source/iahndl-ioexceptions.cxx @@ -0,0 +1,277 @@ +/* -*- 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 . + */ + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include <comphelper/fileurl.hxx> + +#include <ids.hxx> + +#include "iahndl.hxx" + +using namespace com::sun::star; + +namespace { + +template<class T> +bool +getRequestArgument(uno::Sequence< uno::Any > const & rArguments, + OUString const & rKey, + T * pValue) +{ + for (const auto& rArgument : rArguments) + { + beans::PropertyValue aProperty; + if ((rArgument >>= aProperty) && aProperty.Name == rKey) + { + T aValue; + if (aProperty.Value >>= aValue) + { + if (pValue) + *pValue = aValue; + return true; + } + } + } + return false; +} + +bool +getResourceNameRequestArgument(uno::Sequence< uno::Any > const & rArguments, + OUString * pValue) +{ + if (!getRequestArgument(rArguments, "Uri", pValue)) + return false; + // Use the resource name only for file URLs, to avoid confusion: + if (pValue && comphelper::isFileUrl(*pValue)) + getRequestArgument(rArguments, "ResourceName", pValue); + return true; +} + +} // namespace + +bool +UUIInteractionHelper::handleInteractiveIOException( + uno::Reference< task::XInteractionRequest > const & rRequest, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + bHasErrorString = false; + + ucb::InteractiveIOException aIoException; + if (aAnyRequest >>= aIoException) + { + uno::Sequence< uno::Any > aRequestArguments; + ucb::InteractiveAugmentedIOException aAugmentedIoException; + if (aAnyRequest >>= aAugmentedIoException) + aRequestArguments = aAugmentedIoException.Arguments; + + ErrCode nErrorCode; + std::vector< OUString > aArguments; + static ErrCode const + aErrorCode[sal_Int32(ucb::IOErrorCode_WRONG_VERSION) + 1][2] + = { { ERRCODE_IO_ABORT, ERRCODE_UUI_IO_ABORT }, // ABORT + { ERRCODE_IO_ACCESSDENIED, ERRCODE_UUI_IO_ACCESSDENIED }, + // ACCESS_DENIED + { ERRCODE_IO_ALREADYEXISTS, + ERRCODE_UUI_IO_ALREADYEXISTS }, // ALREADY_EXISTING + { ERRCODE_IO_BADCRC, ERRCODE_UUI_IO_BADCRC }, // BAD_CRC + { ERRCODE_IO_CANTCREATE, ERRCODE_UUI_IO_CANTCREATE }, + // CANT_CREATE + { ERRCODE_IO_CANTREAD, ERRCODE_UUI_IO_CANTREAD }, + // CANT_READ + { ERRCODE_IO_CANTSEEK, ERRCODE_UUI_IO_CANTSEEK }, + // CANT_SEEK + { ERRCODE_IO_CANTTELL, ERRCODE_UUI_IO_CANTTELL }, + // CANT_TELL + { ERRCODE_IO_CANTWRITE, ERRCODE_UUI_IO_CANTWRITE }, + // CANT_WRITE + { ERRCODE_IO_CURRENTDIR, ERRCODE_UUI_IO_CURRENTDIR }, + // CURRENT_DIRECTORY + { ERRCODE_IO_DEVICENOTREADY, ERRCODE_UUI_IO_NOTREADY }, + // DEVICE_NOT_READY + { ERRCODE_IO_NOTSAMEDEVICE, + ERRCODE_UUI_IO_NOTSAMEDEVICE }, // DIFFERENT_DEVICES + { ERRCODE_IO_GENERAL, ERRCODE_UUI_IO_GENERAL }, // GENERAL + { ERRCODE_IO_INVALIDACCESS, + ERRCODE_UUI_IO_INVALIDACCESS }, // INVALID_ACCESS + { ERRCODE_IO_INVALIDCHAR, ERRCODE_UUI_IO_INVALIDCHAR }, + // INVALID_CHARACTER + { ERRCODE_IO_INVALIDDEVICE, + ERRCODE_UUI_IO_INVALIDDEVICE }, // INVALID_DEVICE + { ERRCODE_IO_INVALIDLENGTH, + ERRCODE_UUI_IO_INVALIDLENGTH }, // INVALID_LENGTH + { ERRCODE_IO_INVALIDPARAMETER, + ERRCODE_UUI_IO_INVALIDPARAMETER }, // INVALID_PARAMETER + { ERRCODE_IO_ISWILDCARD, ERRCODE_UUI_IO_ISWILDCARD }, + // IS_WILDCARD + { ERRCODE_IO_LOCKVIOLATION, + ERRCODE_UUI_IO_LOCKVIOLATION }, // LOCKING_VIOLATION + { ERRCODE_IO_MISPLACEDCHAR, + ERRCODE_UUI_IO_MISPLACEDCHAR }, // MISPLACED_CHARACTER + { ERRCODE_IO_NAMETOOLONG, ERRCODE_UUI_IO_NAMETOOLONG }, + // NAME_TOO_LONG + { ERRCODE_IO_NOTEXISTS, ERRCODE_UUI_IO_NOTEXISTS }, + // NOT_EXISTING + { ERRCODE_IO_NOTEXISTSPATH, + ERRCODE_UUI_IO_NOTEXISTSPATH }, // NOT_EXISTING_PATH + { ERRCODE_IO_NOTSUPPORTED, ERRCODE_UUI_IO_NOTSUPPORTED }, + // NOT_SUPPORTED + { ERRCODE_IO_NOTADIRECTORY, + ERRCODE_UUI_IO_NOTADIRECTORY }, // NO_DIRECTORY + { ERRCODE_IO_NOTAFILE, ERRCODE_UUI_IO_NOTAFILE }, + // NO_FILE + { ERRCODE_IO_OUTOFSPACE, ERRCODE_UUI_IO_OUTOFSPACE }, + // OUT_OF_DISK_SPACE + { ERRCODE_IO_TOOMANYOPENFILES, + ERRCODE_UUI_IO_TOOMANYOPENFILES }, + // OUT_OF_FILE_HANDLES + { ERRCODE_IO_OUTOFMEMORY, ERRCODE_UUI_IO_OUTOFMEMORY }, + // OUT_OF_MEMORY + { ERRCODE_IO_PENDING, ERRCODE_UUI_IO_PENDING }, // PENDING + { ERRCODE_IO_RECURSIVE, ERRCODE_UUI_IO_RECURSIVE }, + // RECURSIVE + { ERRCODE_IO_UNKNOWN, ERRCODE_UUI_IO_UNKNOWN }, // UNKNOWN + { ERRCODE_IO_WRITEPROTECTED, + ERRCODE_UUI_IO_WRITEPROTECTED }, // WRITE_PROTECTED + { ERRCODE_IO_WRONGFORMAT, ERRCODE_UUI_IO_WRONGFORMAT }, + // WRONG_FORMAT + { ERRCODE_IO_WRONGVERSION, + ERRCODE_UUI_IO_WRONGVERSION } }; // WRONG_VERSION + switch (aIoException.Code) + { + case ucb::IOErrorCode_CANT_CREATE: + { + OUString aArgFolder; + if (getRequestArgument(aRequestArguments, "Folder", &aArgFolder)) + { + OUString aArgUri; + if (getResourceNameRequestArgument(aRequestArguments, + &aArgUri)) + { + nErrorCode = ERRCODE_UUI_IO_CANTCREATE; + aArguments.reserve(2); + aArguments.push_back(aArgUri); + aArguments.push_back(aArgFolder); + } + else + { + nErrorCode = ERRCODE_UUI_IO_CANTCREATE_NONAME; + aArguments.push_back(aArgFolder); + } + } + else + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][0]; + break; + } + + case ucb::IOErrorCode_DEVICE_NOT_READY: + { + OUString aArgUri; + if (getResourceNameRequestArgument(aRequestArguments, + &aArgUri)) + { + OUString aResourceType; + getRequestArgument(aRequestArguments, "ResourceType", &aResourceType); + bool bRemovable = false; + getRequestArgument(aRequestArguments, "Removable", &bRemovable); + nErrorCode = aResourceType == "volume" + ? (bRemovable + ? ERRCODE_UUI_IO_NOTREADY_VOLUME_REMOVABLE + : ERRCODE_UUI_IO_NOTREADY_VOLUME) + : (bRemovable + ? ERRCODE_UUI_IO_NOTREADY_REMOVABLE + : ERRCODE_UUI_IO_NOTREADY); + aArguments.push_back(aArgUri); + } + else + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][0]; + break; + } + + case ucb::IOErrorCode_DIFFERENT_DEVICES: + { + OUString aArgVolume; + OUString aArgOtherVolume; + if (getRequestArgument(aRequestArguments, "Volume", &aArgVolume) + && getRequestArgument(aRequestArguments, "OtherVolume", + &aArgOtherVolume)) + { + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][1]; + aArguments.reserve(2); + aArguments.push_back(aArgVolume); + aArguments.push_back(aArgOtherVolume); + } + else + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][0]; + break; + } + + case ucb::IOErrorCode_NOT_EXISTING: + { + OUString aArgUri; + if (getResourceNameRequestArgument(aRequestArguments, + &aArgUri)) + { + OUString aResourceType; + getRequestArgument(aRequestArguments, "ResourceType", + &aResourceType); + nErrorCode = aResourceType == "volume" + ? ERRCODE_UUI_IO_NOTEXISTS_VOLUME + : (aResourceType == "folder" + ? ERRCODE_UUI_IO_NOTEXISTS_FOLDER + : ERRCODE_UUI_IO_NOTEXISTS); + aArguments.push_back(aArgUri); + } + else + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][0]; + break; + } + + default: + { + OUString aArgUri; + if (getResourceNameRequestArgument(aRequestArguments, + &aArgUri)) + { + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][1]; + aArguments.push_back(aArgUri); + } + else + nErrorCode = aErrorCode[static_cast<sal_Int32>(aIoException.Code)][0]; + break; + } + } + + handleErrorHandlerRequest(aIoException.Classification, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-locking.cxx b/uui/source/iahndl-locking.cxx new file mode 100644 index 000000000..52b9d2108 --- /dev/null +++ b/uui/source/iahndl-locking.cxx @@ -0,0 +1,297 @@ +/* -*- 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 . + */ + +#include <com/sun/star/document/ChangedByOthersRequest.hpp> +#include <com/sun/star/document/LockedDocumentRequest.hpp> +#include <com/sun/star/document/LockedOnSavingRequest.hpp> +#include <com/sun/star/document/LockFileIgnoreRequest.hpp> +#include <com/sun/star/document/LockFileCorruptRequest.hpp> +#include <com/sun/star/document/OwnLockOnDocumentRequest.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> + +#include <unotools/resmgr.hxx> +#include <vcl/svapp.hxx> +#include <officecfg/Office/Common.hxx> + +#include <strings.hrc> +#include "getcontinuations.hxx" +#include "openlocked.hxx" +#include "trylater.hxx" +#include "alreadyopen.hxx" +#include "filechanged.hxx" +#include "lockfailed.hxx" +#include "lockcorrupt.hxx" + +#include "iahndl.hxx" + +#define UUI_DOC_LOAD_LOCK 0 +#define UUI_DOC_OWN_LOAD_LOCK 1 +#define UUI_DOC_SAVE_LOCK 2 +#define UUI_DOC_OWN_SAVE_LOCK 3 + +using namespace com::sun::star; + +namespace { + +void +handleLockedDocumentRequest_( + weld::Window * pParent, + const OUString& aDocumentURL, + const OUString& aInfo, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, + sal_uInt16 nMode ) +{ + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionDisapprove > xDisapprove; + uno::Reference< task::XInteractionAbort > xAbort; + // In case an option to ignore lock and open the file is available + uno::Reference< task::XInteractionRetry > xRetry; + getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort, &xRetry); + + if ( !xApprove.is() || !xDisapprove.is() || !xAbort.is() ) + return; + + SolarMutexGuard aGuard; + std::locale aResLocale = Translate::Create("uui"); + + OUString aMessage; + std::vector< OUString > aArguments; + aArguments.push_back( aDocumentURL ); + + bool bAllowOverride = xRetry.is() && officecfg::Office::Common::Misc::AllowOverrideLocking::get(); + + sal_Int32 nResult = RET_CANCEL; + if ( nMode == UUI_DOC_LOAD_LOCK ) + { + aArguments.push_back( !aInfo.isEmpty() + ? aInfo + : Translate::get( STR_UNKNOWNUSER, aResLocale) ); + aArguments.push_back( bAllowOverride + ? Translate::get( STR_OPENLOCKED_ALLOWIGNORE_MSG, aResLocale ) + : "" ); + aMessage = Translate::get(STR_OPENLOCKED_MSG, aResLocale); + aMessage = UUIInteractionHelper::replaceMessageWithArguments( + aMessage, aArguments ); + + OpenLockedQueryBox aDialog(pParent, aResLocale, aMessage, bAllowOverride); + nResult = aDialog.run(); + } + else if ( nMode == UUI_DOC_SAVE_LOCK ) + { + aArguments.push_back( !aInfo.isEmpty() + ? aInfo + : Translate::get( STR_UNKNOWNUSER, + aResLocale ) ); + aMessage = Translate::get(bAllowOverride ? STR_OVERWRITE_IGNORELOCK_MSG : STR_TRYLATER_MSG, + aResLocale); + aMessage = UUIInteractionHelper::replaceMessageWithArguments( + aMessage, aArguments ); + + TryLaterQueryBox aDialog(pParent, aResLocale, aMessage, bAllowOverride); + nResult = aDialog.run(); + } + else if ( nMode == UUI_DOC_OWN_LOAD_LOCK || + nMode == UUI_DOC_OWN_SAVE_LOCK ) + { + aArguments.push_back( aInfo ); + aMessage = Translate::get(nMode == UUI_DOC_OWN_SAVE_LOCK + ? STR_ALREADYOPEN_SAVE_MSG + : STR_ALREADYOPEN_MSG, + aResLocale ); + aMessage = UUIInteractionHelper::replaceMessageWithArguments( + aMessage, aArguments ); + + AlreadyOpenQueryBox aDialog(pParent, aResLocale, aMessage, nMode == UUI_DOC_OWN_SAVE_LOCK); + nResult = aDialog.run(); + } + + if ( nResult == RET_YES ) + xApprove->select(); + else if ( nResult == RET_NO ) + xDisapprove->select(); + else if ( nResult == RET_IGNORE && xRetry.is() ) + xRetry->select(); + else + xAbort->select(); +} + +void +handleChangedByOthersRequest_( + weld::Window * pParent, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations ) +{ + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionAbort > xAbort; + getContinuations(rContinuations, &xApprove, &xAbort); + + if ( !xApprove.is() || !xAbort.is() ) + return; + + SolarMutexGuard aGuard; + std::locale aResLocale = Translate::Create("uui"); + FileChangedQueryBox aDialog(pParent, aResLocale); + sal_Int32 nResult = aDialog.run(); + + if ( nResult == RET_YES ) + xApprove->select(); + else + xAbort->select(); +} + +const sal_uInt16 UUI_DOC_CreateErrDlg = 0; +const sal_uInt16 UUI_DOC_CorruptErrDlg = 1; + + + +void +handleLockFileProblemRequest_( + weld::Window * pParent, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, sal_uInt16 nWhichDlg ) +{ + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionAbort > xAbort; + getContinuations(rContinuations, &xApprove, &xAbort); + + if ( !xApprove.is() || !xAbort.is() ) + return; + + SolarMutexGuard aGuard; + std::locale aResLocale = Translate::Create("uui"); + + sal_Int32 nResult; + + if (nWhichDlg == UUI_DOC_CreateErrDlg) + { + LockFailedQueryBox aDialog(pParent, aResLocale); + nResult = aDialog.run(); + } + else + { + LockCorruptQueryBox aDialog(pParent, aResLocale); + nResult = aDialog.run(); + } + + if ( nResult == RET_OK ) + xApprove->select(); + else + xAbort->select(); +} + +} // namespace + +bool +UUIInteractionHelper::handleLockedDocumentRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + document::LockedDocumentRequest aLockedDocumentRequest; + if (aAnyRequest >>= aLockedDocumentRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleLockedDocumentRequest_(Application::GetFrameWeld(xParent), + aLockedDocumentRequest.DocumentURL, + aLockedDocumentRequest.UserInfo, + rRequest->getContinuations(), + UUI_DOC_LOAD_LOCK); + return true; + } + + document::OwnLockOnDocumentRequest aOwnLockOnDocumentRequest; + if (aAnyRequest >>= aOwnLockOnDocumentRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleLockedDocumentRequest_(Application::GetFrameWeld(xParent), + aOwnLockOnDocumentRequest.DocumentURL, + aOwnLockOnDocumentRequest.TimeInfo, + rRequest->getContinuations(), + aOwnLockOnDocumentRequest.IsStoring + ? UUI_DOC_OWN_SAVE_LOCK + : UUI_DOC_OWN_LOAD_LOCK); + return true; + } + + document::LockedOnSavingRequest aLockedOnSavingRequest; + if (aAnyRequest >>= aLockedOnSavingRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleLockedDocumentRequest_(Application::GetFrameWeld(xParent), + aLockedOnSavingRequest.DocumentURL, + aLockedOnSavingRequest.UserInfo, + rRequest->getContinuations(), + UUI_DOC_SAVE_LOCK); + return true; + } + return false; +} + +bool +UUIInteractionHelper::handleChangedByOthersRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + document::ChangedByOthersRequest aChangedByOthersRequest; + if (aAnyRequest >>= aChangedByOthersRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleChangedByOthersRequest_(Application::GetFrameWeld(xParent), + rRequest->getContinuations()); + return true; + } + return false; +} + + +bool +UUIInteractionHelper::handleLockFileProblemRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + document::LockFileIgnoreRequest aLockFileIgnoreRequest; + if (aAnyRequest >>= aLockFileIgnoreRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleLockFileProblemRequest_(Application::GetFrameWeld(xParent), + rRequest->getContinuations(), UUI_DOC_CreateErrDlg); + return true; + } + + document::LockFileCorruptRequest aLockFileCorruptRequest; + if (aAnyRequest >>= aLockFileCorruptRequest ) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleLockFileProblemRequest_(Application::GetFrameWeld(xParent), + rRequest->getContinuations(), UUI_DOC_CorruptErrDlg); + return true; + } + + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl-ssl.cxx b/uui/source/iahndl-ssl.cxx new file mode 100644 index 000000000..da5d69e38 --- /dev/null +++ b/uui/source/iahndl-ssl.cxx @@ -0,0 +1,364 @@ +/* -*- 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 . + */ + + +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/security/XCertificateExtension.hpp> +#include <com/sun/star/security/XSanExtension.hpp> +#include <com/sun/star/security/ExtAltNameType.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ucb/CertificateValidationRequest.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <comphelper/lok.hxx> +#include <comphelper/sequence.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <svl/zforlist.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#include <ids.hrc> +#include "getcontinuations.hxx" +#include "sslwarndlg.hxx" +#include "unknownauthdlg.hxx" + +#include "iahndl.hxx" + +#include <memory> + +#define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17" + + +using namespace com::sun::star; + +namespace { + +OUString +getContentPart( const OUString& _rRawString ) +{ + // search over some parts to find a string + static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", nullptr }; + OUString sPart; + int i = 0; + while ( aIDs[i] ) + { + OUString sPartId = OUString::createFromAscii( aIDs[i++] ); + sal_Int32 nContStart = _rRawString.indexOf( sPartId ); + if ( nContStart != -1 ) + { + nContStart += sPartId.getLength(); + sal_Int32 nContEnd = _rRawString.indexOf( ',', nContStart ); + if ( nContEnd != -1 ) + sPart = _rRawString.copy( nContStart, nContEnd - nContStart ); + else + sPart = _rRawString.copy( nContStart ); + break; + } + } + return sPart; +} + +bool +isDomainMatch( + const OUString& hostName, const uno::Sequence< OUString >& certHostNames) +{ + for ( const OUString& element : certHostNames){ + if (element.isEmpty()) + continue; + + if (hostName.equalsIgnoreAsciiCase( element )) + return true; + + if (element.startsWith("*") && + hostName.getLength() >= element.getLength() ) + { + OUString cmpStr = element.copy( 1 ); + if ( hostName.matchIgnoreAsciiCase( + cmpStr, hostName.getLength() - cmpStr.getLength()) ) + return true; + } + } + + return false; +} + +OUString +getLocalizedDatTimeStr( + uno::Reference< uno::XComponentContext> const & xContext, + util::DateTime const & rDateTime ) +{ + OUString aDateTimeStr; + Date aDate( Date::EMPTY ); + tools::Time aTime( tools::Time::EMPTY ); + + aDate = Date( rDateTime.Day, rDateTime.Month, rDateTime.Year ); + aTime = tools::Time( rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds ); + + LanguageType eUILang = Application::GetSettings().GetUILanguageTag().getLanguageType(); + SvNumberFormatter *pNumberFormatter = new SvNumberFormatter( xContext, eUILang ); + OUString aTmpStr; + Color* pColor = nullptr; + const Date& rNullDate = pNumberFormatter->GetNullDate(); + sal_uInt32 nFormat + = pNumberFormatter->GetStandardFormat( SvNumFormatType::DATE, eUILang ); + + pNumberFormatter->GetOutputString( aDate - rNullDate, nFormat, aTmpStr, &pColor ); + aDateTimeStr = aTmpStr + " "; + + nFormat = pNumberFormatter->GetStandardFormat( SvNumFormatType::TIME, eUILang ); + pNumberFormatter->GetOutputString( + aTime.GetTimeInDays(), nFormat, aTmpStr, &pColor ); + aDateTimeStr += aTmpStr; + + return aDateTimeStr; +} + +bool +executeUnknownAuthDialog( + weld::Window * pParent, + uno::Reference< uno::XComponentContext > const & xContext, + const uno::Reference< security::XCertificate >& rXCert) +{ + SolarMutexGuard aGuard; + + UnknownAuthDialog aDialog(pParent, rXCert, xContext); + + // Get correct resource string + OUString aMessage; + + std::vector< OUString > aArguments; + aArguments.push_back( getContentPart( rXCert->getSubjectName()) ); + + std::locale aResLocale(Translate::Create("uui")); + + aMessage = Translate::get(STR_UUI_UNKNOWNAUTH_UNTRUSTED, aResLocale); + aMessage = UUIInteractionHelper::replaceMessageWithArguments( + aMessage, aArguments ); + aDialog.setDescriptionText( aMessage ); + + return static_cast<bool>(aDialog.run()); +} + +enum class SslWarnType { + DOMAINMISMATCH, EXPIRED, INVALID +}; + +bool +executeSSLWarnDialog( + weld::Window * pParent, + uno::Reference< uno::XComponentContext > const & xContext, + const uno::Reference< security::XCertificate >& rXCert, + SslWarnType failure, + const OUString & hostName ) +{ + SolarMutexGuard aGuard; + + SSLWarnDialog aDialog(pParent, rXCert, xContext); + + // Get correct resource string + std::vector< OUString > aArguments_1; + char const * pMessageKey = nullptr; + char const * pTitleKey = nullptr; + + switch( failure ) + { + case SslWarnType::DOMAINMISMATCH: + pMessageKey = STR_UUI_SSLWARN_DOMAINMISMATCH; + pTitleKey = STR_UUI_SSLWARN_DOMAINMISMATCH_TITLE; + aArguments_1.push_back( hostName ); + aArguments_1.push_back( + getContentPart( rXCert->getSubjectName()) ); + aArguments_1.push_back( hostName ); + break; + case SslWarnType::EXPIRED: + pMessageKey = STR_UUI_SSLWARN_EXPIRED; + pTitleKey = STR_UUI_SSLWARN_EXPIRED_TITLE; + aArguments_1.push_back( + getContentPart( rXCert->getSubjectName()) ); + aArguments_1.push_back( + getLocalizedDatTimeStr( xContext, + rXCert->getNotValidAfter() ) ); + aArguments_1.push_back( + getLocalizedDatTimeStr( xContext, + rXCert->getNotValidAfter() ) ); + break; + case SslWarnType::INVALID: + pMessageKey = STR_UUI_SSLWARN_INVALID; + pTitleKey = STR_UUI_SSLWARN_INVALID_TITLE; + break; + default: assert(false); + } + + std::locale aResLocale(Translate::Create("uui")); + + OUString aMessage_1 = Translate::get(pMessageKey, aResLocale); + aMessage_1 = UUIInteractionHelper::replaceMessageWithArguments( + aMessage_1, aArguments_1 ); + aDialog.setDescription1Text( aMessage_1 ); + + OUString aTitle = Translate::get(pTitleKey, aResLocale); + aDialog.set_title(aTitle); + + return static_cast<bool>(aDialog.run()); +} + +void +handleCertificateValidationRequest_( + weld::Window * pParent, + uno::Reference< uno::XComponentContext > const & xContext, + ucb::CertificateValidationRequest const & rRequest, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations) +{ + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionAbort > xAbort; + getContinuations(rContinuations, &xApprove, &xAbort); + + if ( comphelper::LibreOfficeKit::isActive() && xApprove.is() ) + { + xApprove->select(); + return; + } + + sal_Int32 failures = rRequest.CertificateValidity; + bool trustCert = true; + + if ( ((failures & security::CertificateValidity::UNTRUSTED) + == security::CertificateValidity::UNTRUSTED ) || + ((failures & security::CertificateValidity::ISSUER_UNTRUSTED) + == security::CertificateValidity::ISSUER_UNTRUSTED) || + ((failures & security::CertificateValidity::ROOT_UNTRUSTED) + == security::CertificateValidity::ROOT_UNTRUSTED) ) + { + trustCert = executeUnknownAuthDialog( pParent, + xContext, + rRequest.Certificate ); + } + + uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = rRequest.Certificate->getExtensions(); + uno::Reference< security::XSanExtension > sanExtension; + auto pExtension = std::find_if(extensions.begin(), extensions.end(), + [](const uno::Reference< security::XCertificateExtension >& element) { + OString aId ( reinterpret_cast<const char *>(element->getExtensionId().getConstArray()), element->getExtensionId().getLength()); + return aId == OID_SUBJECT_ALTERNATIVE_NAME; + }); + if (pExtension != extensions.end()) + { + sanExtension = uno::Reference<security::XSanExtension>(*pExtension, uno::UNO_QUERY); + } + + std::vector<security::CertAltNameEntry> altNames; + if (sanExtension.is()) + { + altNames = comphelper::sequenceToContainer<std::vector<security::CertAltNameEntry>>(sanExtension->getAlternativeNames()); + } + + OUString certHostName = getContentPart( rRequest.Certificate->getSubjectName() ); + uno::Sequence< OUString > certHostNames(altNames.size() + 1); + + certHostNames[0] = certHostName; + + for (size_t n = 0; n < altNames.size(); ++n) + { + if (altNames[n].Type == security::ExtAltNameType_DNS_NAME) + { + altNames[n].Value >>= certHostNames[n+1]; + } + } + + if ( (!isDomainMatch( + rRequest.HostName, + certHostNames )) && + trustCert ) + { + trustCert = executeSSLWarnDialog( pParent, + xContext, + rRequest.Certificate, + SslWarnType::DOMAINMISMATCH, + rRequest.HostName ); + } + + else if ( (((failures & security::CertificateValidity::TIME_INVALID) + == security::CertificateValidity::TIME_INVALID) || + ((failures & security::CertificateValidity::NOT_TIME_NESTED) + == security::CertificateValidity::NOT_TIME_NESTED)) && + trustCert ) + { + trustCert = executeSSLWarnDialog( pParent, + xContext, + rRequest.Certificate, + SslWarnType::EXPIRED, + rRequest.HostName ); + } + + else if ( (((failures & security::CertificateValidity::REVOKED) + == security::CertificateValidity::REVOKED) || + ((failures & security::CertificateValidity::SIGNATURE_INVALID) + == security::CertificateValidity::SIGNATURE_INVALID) || + ((failures & security::CertificateValidity::EXTENSION_INVALID) + == security::CertificateValidity::EXTENSION_INVALID) || + ((failures & security::CertificateValidity::INVALID) + == security::CertificateValidity::INVALID)) && + trustCert ) + { + trustCert = executeSSLWarnDialog( pParent, + xContext, + rRequest.Certificate, + SslWarnType::INVALID, + rRequest.HostName ); + } + + if ( trustCert ) + { + if (xApprove.is()) + xApprove->select(); + } + else + { + if (xAbort.is()) + xAbort->select(); + } +} + +} // namespace + +bool +UUIInteractionHelper::handleCertificateValidationRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + uno::Any aAnyRequest(rRequest->getRequest()); + + ucb::CertificateValidationRequest aCertificateValidationRequest; + if (aAnyRequest >>= aCertificateValidationRequest) + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + handleCertificateValidationRequest_(Application::GetFrameWeld(xParent), + m_xContext, + aCertificateValidationRequest, + rRequest->getContinuations()); + return true; + } + + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl.cxx b/uui/source/iahndl.cxx new file mode 100644 index 000000000..14615bc9c --- /dev/null +++ b/uui/source/iahndl.cxx @@ -0,0 +1,1256 @@ +/* -*- 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 . + */ + +#include <memory> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/configuration/theDefaultProvider.hpp> +#include <com/sun/star/configuration/backend/MergeRecoveryRequest.hpp> +#include <com/sun/star/configuration/backend/StratumCreationException.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/document/BrokenPackageRequest.hpp> +#include <com/sun/star/document/ExoticFileLoadException.hpp> +#include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp> +#include <com/sun/star/java/WrongJavaVersionException.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/script/ModuleSizeExceededRequest.hpp> +#include <com/sun/star/task/ErrorCodeIOException.hpp> +#include <com/sun/star/task/ErrorCodeRequest.hpp> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionDisapprove.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ucb/AuthenticationFallbackRequest.hpp> +#include <com/sun/star/ucb/InteractiveAppException.hpp> +#include <com/sun/star/ucb/InteractiveLockingLockedException.hpp> +#include <com/sun/star/ucb/InteractiveLockingNotLockedException.hpp> +#include <com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> +#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/InteractiveWrongMediumException.hpp> +#include <com/sun/star/ucb/NameClashException.hpp> +#include <com/sun/star/ucb/NameClashResolveRequest.hpp> +#include <com/sun/star/ucb/UnsupportedNameClashException.hpp> +#include <com/sun/star/ucb/XInteractionReplaceExistingData.hpp> +#include <com/sun/star/ucb/XInteractionSupplyName.hpp> +#include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp> +#include <com/sun/star/loader/CannotActivateFactoryException.hpp> + +#include <sal/log.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/conditn.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/errinf.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/documentconstants.hxx> +#include <comphelper/propertysequence.hxx> +#include <svtools/sfxecode.hxx> +#include <unotools/configmgr.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <typelib/typedescription.hxx> +#include <unotools/confignode.hxx> + +#include <ids.hxx> +#include <ids.hrc> +#include <strings.hrc> + +#include "getcontinuations.hxx" +#include "secmacrowarnings.hxx" + +#include "iahndl.hxx" +#include "nameclashdlg.hxx" + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::task::XInteractionContinuation; +using ::com::sun::star::task::XInteractionAbort; +using ::com::sun::star::task::XInteractionApprove; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::lang::XInitialization; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::task::InteractionHandler; +using ::com::sun::star::task::XInteractionHandler2; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Any; +using ::com::sun::star::task::XInteractionRequest; +using ::com::sun::star::lang::XMultiServiceFactory; + +using namespace ::com::sun::star; + +namespace { + +class HandleData : public osl::Condition +{ +public: + explicit HandleData( + uno::Reference< task::XInteractionRequest > const & rRequest) + : osl::Condition(), + m_rRequest(rRequest), + bHandled( false ) + { + } + uno::Reference< task::XInteractionRequest > m_rRequest; + bool bHandled; + beans::Optional< OUString > m_aResult; +}; + +} /* namespace */ + +UUIInteractionHelper::UUIInteractionHelper( + uno::Reference< uno::XComponentContext > const & rxContext, + uno::Reference< awt::XWindow > const & rxWindowParam, + const OUString & rContextParam) + : m_xContext(rxContext), + m_xWindowParam(rxWindowParam), + m_aContextParam(rContextParam) +{ +} + +UUIInteractionHelper::UUIInteractionHelper( + uno::Reference< uno::XComponentContext > const & rxContext) + : m_xContext(rxContext) +{ +} + +UUIInteractionHelper::~UUIInteractionHelper() +{ +} + +void UUIInteractionHelper::handlerequest( + void* pHandleData, void* pInteractionHelper) +{ + HandleData* pHND + = static_cast< HandleData * >(pHandleData); + UUIInteractionHelper* pUUI + = static_cast< UUIInteractionHelper * >(pInteractionHelper); + bool bDummy = false; + OUString aDummy; + pHND->bHandled + = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy); + pHND->set(); +} + +bool +UUIInteractionHelper::handleRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + if(!Application::IsMainThread() && GetpApp()) + { + // we are not in the main thread, let it handle that stuff + HandleData aHD(rRequest); + Link<void*,void> aLink(&aHD,handlerequest); + Application::PostUserEvent(aLink,this); + comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex(); + sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0; + aHD.wait(); + if (nLockCount) + rSolarMutex.acquire(nLockCount); + return aHD.bHandled; + } + else + { + bool bDummy = false; + OUString aDummy; + return handleRequest_impl(rRequest, false, bDummy, aDummy); + } +} + +void UUIInteractionHelper::getstringfromrequest( + void* pHandleData,void* pInteractionHelper) +{ + HandleData* pHND = static_cast<HandleData*>(pHandleData); + UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper); + pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest); + pHND->set(); +} + +beans::Optional< OUString > +UUIInteractionHelper::getStringFromRequest_impl( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + bool bSuccess = false; + OUString aMessage; + handleRequest_impl(rRequest, true, bSuccess, aMessage); + + OSL_ENSURE(bSuccess || + !isInformationalErrorMessageRequest( + rRequest->getContinuations()), + "Interaction request is a candidate for a string representation." + "Please implement!"); + + return beans::Optional< OUString >(bSuccess, aMessage); +} + +beans::Optional< OUString > +UUIInteractionHelper::getStringFromRequest( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + if(!Application::IsMainThread() && GetpApp()) + { + // we are not in the main thread, let it handle that stuff + HandleData aHD(rRequest); + Link<void*,void> aLink(&aHD,getstringfromrequest); + Application::PostUserEvent(aLink,this); + comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex(); + sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0; + aHD.wait(); + if (nLockCount) + rSolarMutex.acquire(nLockCount); + return aHD.m_aResult; + } + else + return getStringFromRequest_impl(rRequest); +} + +OUString +UUIInteractionHelper::replaceMessageWithArguments( + const OUString& _aMessage, + std::vector< OUString > const & rArguments ) +{ + OUString aMessage = _aMessage; + + SAL_WARN_IF(rArguments.empty(), "uui", "replaceMessageWithArguments: No arguments passed!"); + for (size_t i = 0; i < rArguments.size(); ++i) + { + const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")"; + aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]); + } + + return aMessage; +} + +bool +UUIInteractionHelper::isInformationalErrorMessageRequest( + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations) +{ + // Only requests with a single continuation (user has no choice, request + // is just informational) + if (rContinuations.getLength() != 1 ) + return false; + + // user can only abort or approve, all other continuations are not + // considered to be informational. + uno::Reference< task::XInteractionApprove > xApprove( + rContinuations[0], uno::UNO_QUERY); + if (xApprove.is()) + return true; + + uno::Reference< task::XInteractionAbort > xAbort( + rContinuations[0], uno::UNO_QUERY); + return xAbort.is(); +} + +bool +UUIInteractionHelper::tryOtherInteractionHandler( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + InteractionHandlerDataList dataList; + getInteractionHandlerList(dataList); + + return std::any_of(dataList.cbegin(), dataList.cend(), + [&](const InteractionHandlerData& rData) { return handleCustomRequest( rRequest, rData.ServiceName ); }); +} + +namespace +{ + + bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, const OUString& i_rPropagation ) + { + const css::uno::TypeDescription aTypeDesc( i_rTypeName ); + const typelib_TypeDescription* pTypeDesc = aTypeDesc.get(); + if ( !pTypeDesc || !pTypeDesc->pWeakRef ) + { + SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" ); + return false; + } + const css::uno::Type aType( pTypeDesc->pWeakRef ); + + const bool bExactMatch = i_rPropagation == "named-only"; + if ( bExactMatch ) + return i_rRequest.getValueType().equals( aType ); + + return i_rRequest.isExtractableTo( aType ); + } +} + + +bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const +{ + try + { + Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW ); + + Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY ); + if ( xHandlerInit.is() ) + { + ::comphelper::NamedValueCollection aInitArgs; + aInitArgs.put( "Parent", getParentXWindow() ); + xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() ); + } + + if ( xHandler->handleInteractionRequest( i_rRequest ) ) + return true; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("uui"); + } + return false; +} + + +bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest ) +{ + // the request + const Any aRequest( rRequest->getRequest() ); + + const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() ); + if ( aCacheHitTest != m_aTypedCustomHandlers.end() ) + return handleCustomRequest( rRequest, aCacheHitTest->second ); + + // the base registration node for "typed" interaction handlers + const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext( + m_xContext, + "/org.openoffice.Interaction/InteractionHandlers", + -1, + ::utl::OConfigurationTreeRoot::CM_READONLY + ) ); + + // loop through all registered implementations + const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() ); + for ( auto const & handlerName : aRegisteredHandlers ) + { + const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) ); + const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) ); + + // loop through all the types which the current handler is registered for + const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() ); + for ( auto const & type : aHandledTypes ) + { + // the UNO type is the node name + ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) ); + // and there's a child denoting how the responsibility propagates + OUString sPropagation; + OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation ); + if ( lcl_matchesRequest( aRequest, type, sPropagation ) ) + { + // retrieve the service/implementation name of the handler + OUString sServiceName; + OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName ); + // cache the information who feels responsible for requests of this type + m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName; + // actually handle the request + return handleCustomRequest( rRequest, sServiceName ); + } + } + } + + return false; +} + +bool +UUIInteractionHelper::handleRequest_impl( + uno::Reference< task::XInteractionRequest > const & rRequest, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString) +{ + try + { + if (!rRequest.is()) + return false; + + uno::Any aAnyRequest(rRequest->getRequest()); + + script::ModuleSizeExceededRequest aModSizeException; + if (aAnyRequest >>= aModSizeException ) + { + std::vector< OUString > aArguments; + uno::Sequence< OUString > sModules + = aModSizeException.Names; + if ( sModules.hasElements() ) + { + OUStringBuffer aName; + for ( sal_Int32 index=0; index< sModules.getLength(); ++index ) + { + if ( index ) + aName.append(","); + aName.append(sModules[index]); + } + aArguments.push_back( aName.makeStringAndClear() ); + } + handleErrorHandlerRequest( task::InteractionClassification_WARNING, + ERRCODE_UUI_IO_MODULESIZEEXCEEDED, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + document::ExoticFileLoadException aExoticFileLoadException; + if (aAnyRequest >>= aExoticFileLoadException) + { + std::vector< OUString > aArguments; + + if( !aExoticFileLoadException.URL.isEmpty() ) + { + aArguments.push_back( aExoticFileLoadException.URL ); + } + if( !aExoticFileLoadException.FilterUIName.isEmpty() ) + { + aArguments.push_back( aExoticFileLoadException.FilterUIName ); + } + + handleErrorHandlerRequest( task::InteractionClassification_WARNING, + ERRCODE_UUI_IO_EXOTICFILEFORMAT, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + ucb::NameClashException aNCException; + if (aAnyRequest >>= aNCException) + { + ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS; + std::vector< OUString > aArguments; + + if( !aNCException.Name.isEmpty() ) + { + nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS; + aArguments.push_back( aNCException.Name ); + } + + handleErrorHandlerRequest( aNCException.Classification, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + ucb::UnsupportedNameClashException aUORequest; + if (aAnyRequest >>= aUORequest) + { + std::vector< OUString > aArguments; + + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionDisapprove > xDisapprove; + getContinuations( + rRequest->getContinuations(), &xApprove, &xDisapprove); + + if ( xApprove.is() && xDisapprove.is() ) + { + handleErrorHandlerRequest( task::InteractionClassification_QUERY, + ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + } + return true; + } + + if ( handleInteractiveIOException( rRequest, + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ) ) + return true; + + ucb::InteractiveAppException aAppException; + if (aAnyRequest >>= aAppException) + { + std::vector< OUString > aArguments; + handleErrorHandlerRequest( aAppException.Classification, + ErrCode(aAppException.Code), + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + ucb::InteractiveNetworkException aNetworkException; + if (aAnyRequest >>= aNetworkException) + { + ErrCode nErrorCode; + std::vector< OUString > aArguments; + ucb::InteractiveNetworkOffLineException aOffLineException; + ucb::InteractiveNetworkResolveNameException aResolveNameException; + ucb::InteractiveNetworkConnectException aConnectException; + ucb::InteractiveNetworkReadException aReadException; + ucb::InteractiveNetworkWriteException aWriteException; + if (aAnyRequest >>= aOffLineException) + nErrorCode = ERRCODE_INET_OFFLINE; + else if (aAnyRequest >>= aResolveNameException) + { + nErrorCode = ERRCODE_INET_NAME_RESOLVE; + aArguments.push_back(aResolveNameException.Server); + } + else if (aAnyRequest >>= aConnectException) + { + nErrorCode = ERRCODE_INET_CONNECT; + aArguments.push_back(aConnectException.Server); + } + else if (aAnyRequest >>= aReadException) + { + nErrorCode = ERRCODE_INET_READ; + aArguments.push_back(aReadException.Diagnostic); + } + else if (aAnyRequest >>= aWriteException) + { + nErrorCode = ERRCODE_INET_WRITE; + aArguments.push_back(aWriteException.Diagnostic); + } + else + nErrorCode = ERRCODE_INET_GENERAL; + + handleErrorHandlerRequest(aNetworkException.Classification, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + ucb::InteractiveWrongMediumException aWrongMediumException; + if (aAnyRequest >>= aWrongMediumException) + { + sal_Int32 nMedium = 0; + aWrongMediumException.Medium >>= nMedium; + std::vector< OUString > aArguments; + aArguments.push_back(OUString::number(nMedium + 1)); + handleErrorHandlerRequest(aWrongMediumException.Classification, + ERRCODE_UUI_WRONGMEDIUM, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + java::WrongJavaVersionException aWrongJavaVersionException; + if (aAnyRequest >>= aWrongJavaVersionException) + { + ErrCode nErrorCode; + std::vector< OUString > aArguments; + if (aWrongJavaVersionException.DetectedVersion.isEmpty()) + if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty()) + nErrorCode = ERRCODE_UUI_WRONGJAVA; + else + { + nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN; + aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion); + } + else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty()) + { + nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION; + aArguments.push_back(aWrongJavaVersionException.DetectedVersion); + } + else + { + nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN; + aArguments.reserve(2); + aArguments.push_back(aWrongJavaVersionException.DetectedVersion); + aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion); + } + handleErrorHandlerRequest(task::InteractionClassification_ERROR, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest; + if (aAnyRequest >>= aMergeRecoveryRequest) + { + ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest + ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE + : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE; + + std::vector< OUString > aArguments; + aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId); + + handleErrorHandlerRequest(task::InteractionClassification_ERROR, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + configuration::backend::StratumCreationException + aStratumCreationException; + + if (aAnyRequest >>= aStratumCreationException) + { + const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING; + + OUString aStratum = aStratumCreationException.StratumData; + if (aStratum.isEmpty()) + aStratum = aStratumCreationException.StratumService; + + std::vector< OUString > aArguments; + aArguments.push_back(aStratum); + + handleErrorHandlerRequest(task::InteractionClassification_ERROR, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException; + if (aAnyRequest >>= aInvalidDataOnSubmitException) + { + const ErrCode nErrorCode = + ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA; + + std::vector< OUString > aArguments; + + handleErrorHandlerRequest(task::InteractionClassification_QUERY, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + ucb::InteractiveLockingLockedException aLLException; + if (aAnyRequest >>= aLLException) + { + ErrCode nErrorCode = aLLException.SelfOwned + ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED; + std::vector< OUString > aArguments; + aArguments.push_back( aLLException.Url ); + + handleErrorHandlerRequest( aLLException.Classification, + nErrorCode, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ); + return true; + } + + ucb::InteractiveLockingNotLockedException aLNLException; + if (aAnyRequest >>= aLNLException) + { + std::vector< OUString > aArguments; + aArguments.push_back( aLNLException.Url ); + + handleErrorHandlerRequest( aLNLException.Classification, + ERRCODE_UUI_LOCKING_NOT_LOCKED, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ); + return true; + } + + ucb::InteractiveLockingLockExpiredException aLLEException; + if (aAnyRequest >>= aLLEException) + { + std::vector< OUString > aArguments; + aArguments.push_back( aLLEException.Url ); + + handleErrorHandlerRequest( aLLEException.Classification, + ERRCODE_UUI_LOCKING_LOCK_EXPIRED, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ); + return true; + } + + document::BrokenPackageRequest aBrokenPackageRequest; + if (aAnyRequest >>= aBrokenPackageRequest) + { + std::vector< OUString > aArguments; + + if( !aBrokenPackageRequest.aName.isEmpty() ) + aArguments.push_back( aBrokenPackageRequest.aName ); + + handleBrokenPackageRequest( aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ); + return true; + } + + task::ErrorCodeRequest aErrorCodeRequest; + if (aAnyRequest >>= aErrorCodeRequest) + { + handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode), + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + task::ErrorCodeIOException aErrorCodeIOException; + if (aAnyRequest >>= aErrorCodeIOException) + { + handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode), + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString); + return true; + } + + loader::CannotActivateFactoryException aCannotActivateFactoryException; + if (aAnyRequest >>= aCannotActivateFactoryException) + { + std::vector< OUString > aArguments; + aArguments.push_back( aCannotActivateFactoryException.Message ); + + handleErrorHandlerRequest( task::InteractionClassification_ERROR, + ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY, + aArguments, + rRequest->getContinuations(), + bObtainErrorStringOnly, + bHasErrorString, + rErrorString ); + return true; + } + + + // Handle requests which do not have a plain string representation. + + if (!bObtainErrorStringOnly) + { + ucb::AuthenticationFallbackRequest anAuthFallbackRequest; + if ( aAnyRequest >>= anAuthFallbackRequest ) + { + handleAuthFallbackRequest( anAuthFallbackRequest.instructions, + anAuthFallbackRequest.url, rRequest->getContinuations() ); + return true; + } + + if ( handleAuthenticationRequest( rRequest ) ) + return true; + + if ( handleCertificateValidationRequest( rRequest ) ) + return true; + + ucb::NameClashResolveRequest aNameClashResolveRequest; + if (aAnyRequest >>= aNameClashResolveRequest) + { + handleNameClashResolveRequest(aNameClashResolveRequest, + rRequest->getContinuations()); + return true; + } + + if ( handleMasterPasswordRequest( rRequest ) ) + return true; + + if ( handlePasswordRequest( rRequest ) ) + return true; + + if ( handleNoSuchFilterRequest( rRequest ) ) + return true; + + if ( handleFilterOptionsRequest( rRequest ) ) + return true; + + if ( handleLockedDocumentRequest( rRequest ) ) + return true; + + if ( handleChangedByOthersRequest( rRequest ) ) + return true; + + if ( handleLockFileProblemRequest( rRequest ) ) + return true; + + task::DocumentMacroConfirmationRequest aMacroConfirmRequest; + if (aAnyRequest >>= aMacroConfirmRequest) + { + handleMacroConfirmRequest( + aMacroConfirmRequest.DocumentURL, + aMacroConfirmRequest.DocumentStorage, + !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_013_TEXT, + aMacroConfirmRequest.DocumentSignatureInformation, + rRequest->getContinuations()); + return true; + } + + // Last chance: interaction handlers registered in the configuration + + + // typed InteractionHandlers (ooo.Interactions) + if ( handleTypedHandlerImplementations( rRequest ) ) + return true; + + // legacy configuration (ooo.ucb.InteractionHandlers) + if (tryOtherInteractionHandler( rRequest )) + return true; + } + + // Not handled. + return false; + } + catch( const uno::RuntimeException& ) + { + throw; // allowed to leave here + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("uui"); + } + return false; +} + +void +UUIInteractionHelper::getInteractionHandlerList( + InteractionHandlerDataList &rdataList) +{ + try + { + uno::Reference< lang::XMultiServiceFactory > xConfigProv = + configuration::theDefaultProvider::get( m_xContext ); + + OUString aFullPath = "/org.openoffice.ucb.InteractionHandler/InteractionHandlers"; + + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {"nodepath", uno::Any(aFullPath)} + })); + + uno::Reference< uno::XInterface > xInterface( + xConfigProv->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess" , aArguments ) ); + + if ( !xInterface.is() ) + throw uno::RuntimeException("unable to instantiate config access"); + + uno::Reference< container::XNameAccess > xNameAccess( + xInterface, uno::UNO_QUERY_THROW ); + const uno::Sequence< OUString > aElems = xNameAccess->getElementNames(); + + if ( aElems.hasElements() ) + { + uno::Reference< container::XHierarchicalNameAccess > + xHierNameAccess( xInterface, uno::UNO_QUERY_THROW ); + + // Iterate over children. + for ( const auto& rElem : aElems ) + { + try + { + InteractionHandlerData aInfo; + + // Obtain service name. + OUString aKeyBuffer = "['" + rElem + "']/ServiceName"; + + OUString aValue; + if ( !( xHierNameAccess->getByHierarchicalName( + aKeyBuffer ) >>= aValue ) ) + { + OSL_FAIL( "GetInteractionHandlerList - " + "Error getting item value!" ); + continue; + } + + aInfo.ServiceName = aValue; + + // Append info to list. + rdataList.push_back( aInfo ); + } + catch ( container::NoSuchElementException& ) + { + // getByHierarchicalName + + OSL_FAIL( "GetInteractionHandlerList - " + "caught NoSuchElementException!" ); + } + } + } + } + catch ( uno::RuntimeException const & ) + { + throw; + } + catch ( uno::Exception const & ) + { + OSL_FAIL( "GetInteractionHandlerList - Caught Exception!" ); + } +} + +const uno::Reference< awt::XWindow>& +UUIInteractionHelper::getParentXWindow() const +{ + return m_xWindowParam; +} + +uno::Reference< task::XInteractionHandler2 > +UUIInteractionHelper::getInteractionHandler() const +{ + return InteractionHandler::createWithParentAndContext( + m_xContext, m_xWindowParam, + m_aContextParam); +} + +namespace { + +DialogMask +executeMessageBox( + weld::Window * pParent, + OUString const & rTitle, + OUString const & rMessage, + VclMessageType eMessageType) +{ + SolarMutexGuard aGuard; + + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eMessageType, + eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage)); + xBox->set_title(rTitle); + + short nMessResult = xBox->run(); + DialogMask aResult = DialogMask::NONE; + switch (nMessResult) + { + case RET_OK: + aResult = DialogMask::ButtonsOk; + break; + case RET_CANCEL: + aResult = DialogMask::ButtonsCancel; + break; + case RET_YES: + aResult = DialogMask::ButtonsYes; + break; + case RET_NO: + aResult = DialogMask::ButtonsNo; + break; + default: + assert(false); + } + + return aResult; +} + +NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent, + OUString const & rTargetFolderURL, + OUString const & rClashingName, + OUString & rProposedNewName, + bool bAllowOverwrite) +{ + std::locale aResLocale = Translate::Create("uui"); + NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL, + rClashingName, rProposedNewName, bAllowOverwrite); + + NameClashResolveDialogResult eResult = static_cast<NameClashResolveDialogResult>(aDialog.run()); + rProposedNewName = aDialog.getNewName(); + return eResult; +} + +} // namespace + +void +UUIInteractionHelper::handleNameClashResolveRequest( + ucb::NameClashResolveRequest const & rRequest, + uno::Sequence< uno::Reference< + task::XInteractionContinuation > > const & rContinuations) +{ + OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(), + "NameClashResolveRequest must not contain empty TargetFolderURL" ); + + OSL_ENSURE(!rRequest.ClashingName.isEmpty(), + "NameClashResolveRequest must not contain empty ClashingName" ); + + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< ucb::XInteractionSupplyName > xSupplyName; + uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData; + getContinuations( + rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData); + + OSL_ENSURE( xAbort.is(), + "NameClashResolveRequest must contain Abort continuation" ); + + OSL_ENSURE( xSupplyName.is(), + "NameClashResolveRequest must contain SupplyName continuation" ); + + NameClashResolveDialogResult eResult = ABORT; + OUString aProposedNewName( rRequest.ProposedNewName ); + + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent), + rRequest.TargetFolderURL, + rRequest.ClashingName, + aProposedNewName, + xReplaceExistingData.is()); + + switch ( eResult ) + { + case ABORT: + xAbort->select(); + break; + + case RENAME: + xSupplyName->setName( aProposedNewName ); + xSupplyName->select(); + break; + + case OVERWRITE: + OSL_ENSURE( + xReplaceExistingData.is(), + "Invalid NameClashResolveDialogResult: OVERWRITE - " + "No ReplaceExistingData continuation available!" ); + xReplaceExistingData->select(); + break; + } +} + +void +UUIInteractionHelper::handleGenericErrorRequest( + ErrCode nErrorCode, + uno::Sequence< uno::Reference< + task::XInteractionContinuation > > const & rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString) +{ + if (bObtainErrorStringOnly) + { + bHasErrorString = isInformationalErrorMessageRequest(rContinuations); + if (bHasErrorString) + { + OUString aErrorString; + ErrorHandler::GetErrorString(nErrorCode, aErrorString); + rErrorString = aErrorString; + } + } + else + { + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< task::XInteractionApprove > xApprove; + getContinuations(rContinuations, &xApprove, &xAbort); + + // Note: It's important to convert the transported long to the + // required unsigned long value. Otherwise using as flag field + // can fail ... + ErrCode nError(nErrorCode); + bool bWarning = !nError.IgnoreWarning(); + + if ( nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION ) + { + // the security warning box needs a special title + OUString aErrorString; + ErrorHandler::GetErrorString( nErrorCode, aErrorString ); + + std::locale aResLocale = Translate::Create("uui"); + OUString aTitle( utl::ConfigManager::getProductName() ); + + OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale); + + if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() ) + aTitle += " - " ; + aTitle += aErrTitle; + + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error); + } + else + { + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent)); + } + + if (xApprove.is() && bWarning) + xApprove->select(); + else if (xAbort.is()) + xAbort->select(); + } +} + +void +UUIInteractionHelper::handleMacroConfirmRequest( + const OUString& aDocumentURL, + const uno::Reference< embed::XStorage >& xZipStorage, + const OUString& aDocumentVersion, + const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations ) +{ + uno::Reference< task::XInteractionAbort > xAbort; + uno::Reference< task::XInteractionApprove > xApprove; + getContinuations( rContinuations, &xApprove, &xAbort ); + + bool bApprove = false; + + bool bShowSignatures = aSignInfo.hasElements(); + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures); + + aWarning.SetDocumentURL(aDocumentURL); + if ( aSignInfo.getLength() > 1 ) + { + aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo); + } + else if ( aSignInfo.getLength() == 1 ) + { + aWarning.SetCertificate(aSignInfo[0].Signer); + } + + bApprove = aWarning.run() == RET_OK; + + if ( bApprove && xApprove.is() ) + xApprove->select(); + else if ( xAbort.is() ) + xAbort->select(); +} + +void +UUIInteractionHelper::handleBrokenPackageRequest( + std::vector< OUString > const & rArguments, + uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & + rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString) +{ + if (bObtainErrorStringOnly) + { + bHasErrorString = isInformationalErrorMessageRequest(rContinuations); + if (!bHasErrorString) + return; + } + + uno::Reference< task::XInteractionApprove > xApprove; + uno::Reference< task::XInteractionDisapprove > xDisapprove; + uno::Reference< task::XInteractionAbort > xAbort; + getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort); + + ErrCode nErrorCode; + if( xApprove.is() && xDisapprove.is() ) + { + nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE; + } + else if ( xAbort.is() ) + { + nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR; + } + else + return; + + OUString aMessage; + { + std::locale aResLocale = Translate::Create("uui"); + ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale); + if (!aErrorResource.getString(nErrorCode, aMessage)) + return; + } + + aMessage = replaceMessageWithArguments( aMessage, rArguments ); + + if (bObtainErrorStringOnly) + { + rErrorString = aMessage; + return; + } + + VclMessageType eMessageType; + if( xApprove.is() && xDisapprove.is() ) + eMessageType = VclMessageType::Question; + else if ( xAbort.is() ) + eMessageType = VclMessageType::Warning; + else + return; + + OUString title( + utl::ConfigManager::getProductName() + + " " + + utl::ConfigManager::getProductVersion() ); + + uno::Reference<awt::XWindow> xParent = getParentXWindow(); + switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType)) + { + case DialogMask::ButtonsOk: + OSL_ENSURE( xAbort.is(), "unexpected situation" ); + if (xAbort.is()) + xAbort->select(); + break; + + case DialogMask::ButtonsNo: + OSL_ENSURE(xDisapprove.is(), "unexpected situation"); + if (xDisapprove.is()) + xDisapprove->select(); + break; + + case DialogMask::ButtonsYes: + OSL_ENSURE(xApprove.is(), "unexpected situation"); + if (xApprove.is()) + xApprove->select(); + break; + + default: break; + } +} + +// ErrorResource Implementation +bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const +{ + for (const std::pair<const char*, ErrCode>* pStringArray = m_pStringArray; pStringArray->first != nullptr; ++pStringArray) + { + if (nErrorCode.StripWarningAndDynamic() == pStringArray->second.StripWarningAndDynamic()) + { + rString = Translate::get(pStringArray->first, m_rResLocale); + return true; + } + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/iahndl.hxx b/uui/source/iahndl.hxx new file mode 100644 index 000000000..872bc13ac --- /dev/null +++ b/uui/source/iahndl.hxx @@ -0,0 +1,262 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_IAHNDL_HXX +#define INCLUDED_UUI_SOURCE_IAHNDL_HXX + +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <com/sun/star/beans/Optional.hpp> +#include <com/sun/star/task/InteractionClassification.hpp> + +#include <vcl/errcode.hxx> + +#include <unordered_map> +#include <vector> + +namespace com::sun::star { + namespace awt { + class XWindow; + } + namespace embed { + class XStorage; + } + namespace lang { + class XMultiServiceFactory; + } + namespace security { + struct DocumentSignatureInformation; + } + namespace task { + class XInteractionContinuation; + class XInteractionHandler2; + class XInteractionRequest; + } + namespace ucb { + class NameClashResolveRequest; + } +} + +namespace vcl { class Window; } + +struct InteractionHandlerData +{ + /** The UNO service name to use to instantiate the content provider. + */ + OUString ServiceName; +}; + +typedef std::vector< InteractionHandlerData > InteractionHandlerDataList; + +typedef std::unordered_map< OUString, OUString > StringHashMap; + +class UUIInteractionHelper +{ +private: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::awt::XWindow > m_xWindowParam; + const OUString m_aContextParam; + StringHashMap m_aTypedCustomHandlers; + UUIInteractionHelper(UUIInteractionHelper const &) = delete; + UUIInteractionHelper& operator =(UUIInteractionHelper const &) = delete; + +public: + UUIInteractionHelper( + css::uno::Reference< css::uno::XComponentContext > const & rxContext, + css::uno::Reference< css::awt::XWindow > const & rxWindow, + const OUString & rContextParam); + explicit UUIInteractionHelper( + css::uno::Reference< css::uno::XComponentContext > const & rxContext); + + css::uno::Reference<css::awt::XWindow> GetParentWindow() const { return m_xWindowParam; } + void SetParentWindow(const css::uno::Reference<css::awt::XWindow>& rWindow) { m_xWindowParam = rWindow; } + + ~UUIInteractionHelper(); + + bool handleRequest( css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + css::beans::Optional< OUString > + getStringFromRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + // Helper. + static OUString + replaceMessageWithArguments( + const OUString& aMessage, + std::vector< OUString > const & rArguments ); + + const css::uno::Reference< css::uno::XComponentContext >& + getORB() const + { return m_xContext; } +private: + bool + handleRequest_impl( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString); + + static void handlerequest(void* pHandleData, void* pInteractionHandler); + + css::beans::Optional< OUString > + getStringFromRequest_impl( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + static void getstringfromrequest(void* pHandleData, void* pInteractionHandler); + + const css::uno::Reference< css::awt::XWindow>& + getParentXWindow() const; + + css::uno::Reference< css::task::XInteractionHandler2 > + getInteractionHandler() const; + + bool handleTypedHandlerImplementations( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest + ); + + bool + tryOtherInteractionHandler( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + void + getInteractionHandlerList(InteractionHandlerDataList &rdataList); + + static bool + isInformationalErrorMessageRequest( + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations); + + bool + handleInteractiveIOException( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString); + + bool + handleAuthenticationRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool + handleCertificateValidationRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + void + handleNameClashResolveRequest( + css::ucb::NameClashResolveRequest const & rRequest, + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations); + + bool + handleMasterPasswordRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool + handlePasswordRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool + handleNoSuchFilterRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool + handleFilterOptionsRequest( + css::uno::Reference< + css::task::XInteractionRequest > const & rRequest); + + void + handleErrorHandlerRequest( + css::task::InteractionClassification eClassification, + ErrCode nErrorCode, + std::vector< OUString > const & rArguments, + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString); + + void + handleGenericErrorRequest( + ErrCode nErrorCode, + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString); + + void + handleMacroConfirmRequest( + const OUString& aDocumentURL, + const css::uno::Reference< css::embed::XStorage >& xZipStorage, + const OUString& aDocumentVersion, + const css::uno::Sequence< css::security::DocumentSignatureInformation >& aSignInfo, + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations); + + void + handleBrokenPackageRequest( + std::vector< OUString > const & rArguments, + css::uno::Sequence< + css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations, + bool bObtainErrorStringOnly, + bool & bHasErrorString, + OUString & rErrorString); + + bool handleLockedDocumentRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool handleChangedByOthersRequest( + css::uno::Reference< + css::task::XInteractionRequest > const & rRequest); + + bool handleLockFileProblemRequest( + css::uno::Reference< css::task::XInteractionRequest > const & rRequest); + + bool handleCustomRequest( + const css::uno::Reference< css::task::XInteractionRequest >& i_rRequest, + const OUString& i_rServiceName + ) const; + + void + handleAuthFallbackRequest( + const OUString & instructions, + const OUString & url, + css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > const & rContinuations ); +}; + +class ErrorResource +{ + const std::pair<const char*, ErrCode>* m_pStringArray; + const std::locale& m_rResLocale; +public: + explicit ErrorResource(const std::pair<const char*, ErrCode>* pStringArray, const std::locale& rResLocale) + : m_pStringArray(pStringArray) + , m_rResLocale(rResLocale) + { + } + bool getString(ErrCode nErrorCode, OUString &rString) const; +}; + +#endif // INCLUDED_UUI_SOURCE_IAHNDL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/interactionhandler.cxx b/uui/source/interactionhandler.cxx new file mode 100644 index 000000000..cc5579fd1 --- /dev/null +++ b/uui/source/interactionhandler.cxx @@ -0,0 +1,231 @@ +/* -*- 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 . + */ + +#include <memory> +#include <sal/config.h> +#include <osl/diagnose.h> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> + +#include "iahndl.hxx" +#include <comphelper/namedvaluecollection.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace com::sun::star; + +namespace { + +class UUIInteractionHandler: + public cppu::WeakImplHelper<css::lang::XServiceInfo, + css::lang::XInitialization, + css::task::XInteractionHandler2, + css::beans::XPropertySet> +{ +private: + std::unique_ptr<UUIInteractionHelper> m_pImpl; + +public: + explicit UUIInteractionHandler(css::uno::Reference< css::uno::XComponentContext > const & rxContext); + + UUIInteractionHandler(const UUIInteractionHandler&) = delete; + UUIInteractionHandler& operator=(const UUIInteractionHandler&) = delete; + + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(OUString const & rServiceName) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual void SAL_CALL + initialize( + css::uno::Sequence< css::uno::Any > const & rArguments) override; + + virtual void SAL_CALL + handle(css::uno::Reference< css::task::XInteractionRequest > const & rRequest) override; + + virtual sal_Bool SAL_CALL + handleInteractionRequest( + const css::uno::Reference< css::task::XInteractionRequest >& Request + ) override; + + virtual void SAL_CALL + addPropertyChangeListener( const OUString& /*aPropertyName*/, const css::uno::Reference< css::beans::XPropertyChangeListener >& /*xListener*/ ) override + { + throw css::uno::RuntimeException( + "UUIInteractionHandler addPropertyChangeListener is not supported"); + } + + virtual void SAL_CALL + removePropertyChangeListener( const OUString& /*aPropertyName*/, const css::uno::Reference< css::beans::XPropertyChangeListener >& /*xListener*/ ) override + { + throw css::uno::RuntimeException( + "UUIInteractionHandler removePropertyChangeListener is not supported"); + } + + virtual void SAL_CALL + addVetoableChangeListener( const OUString& /*aPropertyName*/, const css::uno::Reference< css::beans::XVetoableChangeListener >& /*xListener*/ ) override + { + throw css::uno::RuntimeException( + "UUIInteractionHandler addVetoableChangeListener is not supported"); + } + + virtual void SAL_CALL + removeVetoableChangeListener( const OUString& /*aPropertyName*/, const css::uno::Reference< css::beans::XVetoableChangeListener >& /*xListener*/ ) override + { + throw css::uno::RuntimeException( + "UUIInteractionHandler removeVetoableChangeListener is not supported"); + } + + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override + { + return nullptr; + } + + virtual void SAL_CALL setPropertyValue(const OUString& rPropertyName, const css::uno::Any& rValue) override + { + if (rPropertyName == "ParentWindow") + { + css::uno::Reference<css::awt::XWindow> xWindow; + rValue >>= xWindow; + m_pImpl->SetParentWindow(xWindow); + return; + } + throw css::beans::UnknownPropertyException(rPropertyName); + } + + virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& rPropertyName) override + { + if (rPropertyName == "ParentWindow") + { + return uno::Any(m_pImpl->GetParentWindow()); + } + throw css::beans::UnknownPropertyException(rPropertyName); + } +}; + +UUIInteractionHandler::UUIInteractionHandler( + uno::Reference< uno::XComponentContext > const & rxContext) + : m_pImpl(new UUIInteractionHelper(rxContext)) +{ +} + +OUString SAL_CALL UUIInteractionHandler::getImplementationName() +{ + return "com.sun.star.comp.uui.UUIInteractionHandler"; +} + +sal_Bool SAL_CALL +UUIInteractionHandler::supportsService(OUString const & rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SAL_CALL +UUIInteractionHandler::getSupportedServiceNames() +{ + return { "com.sun.star.task.InteractionHandler", + // added to indicate support for configuration.backend.MergeRecoveryRequest + "com.sun.star.configuration.backend.InteractionHandler", + // for backwards compatibility + "com.sun.star.uui.InteractionHandler" }; +} + +void SAL_CALL +UUIInteractionHandler::initialize( + uno::Sequence< uno::Any > const & rArguments) +{ + uno::Reference<uno::XComponentContext> xContext = m_pImpl->getORB(); + m_pImpl.reset(); + + // The old-style InteractionHandler service supported a sequence of + // PropertyValue, while the new-style service now uses constructors to pass + // in Parent and Context values; for backwards compatibility, keep support + // for a PropertyValue sequence, too: + uno::Reference< awt::XWindow > xWindow; + OUString aContext; + if (!((rArguments.getLength() == 1 && (rArguments[0] >>= xWindow)) || + (rArguments.getLength() == 2 && (rArguments[0] >>= xWindow) && + (rArguments[1] >>= aContext)))) + { + ::comphelper::NamedValueCollection aProperties( rArguments ); + if ( aProperties.has( "Parent" ) ) + { + OSL_VERIFY( aProperties.get( "Parent" ) >>= xWindow ); + } + if ( aProperties.has( "Context" ) ) + { + OSL_VERIFY( aProperties.get( "Context" ) >>= aContext ); + } + } + + m_pImpl.reset( new UUIInteractionHelper(xContext, xWindow, aContext) ); +} + +void SAL_CALL +UUIInteractionHandler::handle( + uno::Reference< task::XInteractionRequest > const & rRequest) +{ + try + { + m_pImpl->handleRequest(rRequest); + } + catch (uno::RuntimeException const & ex) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetRuntimeException( ex.Message, + *this, anyEx ); + } +} + +sal_Bool SAL_CALL UUIInteractionHandler::handleInteractionRequest( + const uno::Reference< task::XInteractionRequest >& Request ) +{ + try + { + return m_pImpl->handleRequest( Request ); + } + catch (uno::RuntimeException const & ex) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetRuntimeException( ex.Message, + *this, anyEx ); + } +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_uui_UUIInteractionHandler_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new UUIInteractionHandler(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/lockcorrupt.cxx b/uui/source/lockcorrupt.cxx new file mode 100644 index 000000000..28e8e71f0 --- /dev/null +++ b/uui/source/lockcorrupt.cxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include "lockcorrupt.hxx" +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> + +LockCorruptQueryBox::LockCorruptQueryBox(weld::Window* pParent, const std::locale& rResLocale) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, + VclButtonsType::NONE, Translate::get(STR_LOCKCORRUPT_MSG, rResLocale))) +{ + m_xQueryBox->set_title(Translate::get(STR_LOCKCORRUPT_TITLE, rResLocale)); + m_xQueryBox->add_button(Translate::get(STR_LOCKCORRUPT_OPENREADONLY_BTN, rResLocale), RET_OK); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_OK); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/lockcorrupt.hxx b/uui/source/lockcorrupt.hxx new file mode 100644 index 000000000..146757f27 --- /dev/null +++ b/uui/source/lockcorrupt.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_LOCKCORRUPT_HXX +#define INCLUDED_UUI_SOURCE_LOCKCORRUPT_HXX + +#include <vcl/weld.hxx> + +class LockCorruptQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; + +public: + LockCorruptQueryBox(weld::Window* pParent, const std::locale& rResLocale); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/lockfailed.cxx b/uui/source/lockfailed.cxx new file mode 100644 index 000000000..8254b19e5 --- /dev/null +++ b/uui/source/lockfailed.cxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include "lockfailed.hxx" +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> + +LockFailedQueryBox::LockFailedQueryBox(weld::Window* pParent, const std::locale& rLocale) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Error, + VclButtonsType::NONE, Translate::get(STR_LOCKFAILED_MSG, rLocale))) +{ + m_xQueryBox->set_title(Translate::get(STR_LOCKFAILED_TITLE, rLocale)); + m_xQueryBox->add_button(Translate::get(STR_LOCKFAILED_OPENREADONLY_BTN, rLocale), RET_OK); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_OK); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/lockfailed.hxx b/uui/source/lockfailed.hxx new file mode 100644 index 000000000..d7c4c11f3 --- /dev/null +++ b/uui/source/lockfailed.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_LOCKFAILED_HXX +#define INCLUDED_UUI_SOURCE_LOCKFAILED_HXX + +#include <vcl/weld.hxx> + +class LockFailedQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; + +public: + LockFailedQueryBox(weld::Window* pParent, const std::locale& rResLocale); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/logindlg.cxx b/uui/source/logindlg.cxx new file mode 100644 index 000000000..5264c26f8 --- /dev/null +++ b/uui/source/logindlg.cxx @@ -0,0 +1,168 @@ +/* -*- 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 . + */ + +#include <comphelper/string.hxx> +#include "logindlg.hxx" + +#ifdef UNX +#include <limits.h> +#define _MAX_PATH PATH_MAX +#endif + +using namespace com::sun::star; + +LoginDialog::~LoginDialog() +{ +} + +void LoginDialog::SetPassword( const OUString& rNew ) +{ + m_xPasswordED->set_text( rNew ); + SetRequest(); +} + +void LoginDialog::HideControls_Impl( LoginFlags nFlags ) +{ + if ( nFlags & LoginFlags::UsernameReadonly ) + { + m_xNameED->set_sensitive( false ); + } + + if ( nFlags & LoginFlags::NoSavePassword ) + m_xSavePasswdBtn->hide(); + + if ( nFlags & LoginFlags::NoErrorText ) + { + m_xErrorInfo->hide(); + m_xErrorFT->hide(); + } + + if ( nFlags & LoginFlags::NoAccount ) + { + m_xAccountFT->hide(); + m_xAccountED->hide(); + } + + if ( nFlags & LoginFlags::NoUseSysCreds ) + { + m_xUseSysCredsCB->hide(); + } +} + +void LoginDialog::EnableUseSysCredsControls_Impl( bool bUseSysCredsset_sensitived ) +{ + m_xErrorInfo->set_sensitive( !bUseSysCredsset_sensitived ); + m_xErrorFT->set_sensitive( !bUseSysCredsset_sensitived ); + m_xRequestInfo->set_sensitive( !bUseSysCredsset_sensitived ); + m_xNameFT->set_sensitive( !bUseSysCredsset_sensitived ); + m_xNameED->set_sensitive( !bUseSysCredsset_sensitived ); + m_xPasswordFT->set_sensitive( !bUseSysCredsset_sensitived ); + m_xPasswordED->set_sensitive( !bUseSysCredsset_sensitived ); + m_xAccountFT->set_sensitive( !bUseSysCredsset_sensitived ); + m_xAccountED->set_sensitive( !bUseSysCredsset_sensitived ); +} + +void LoginDialog::SetRequest() +{ + bool oldPwd = !m_xPasswordED->get_text().isEmpty(); + OUString aRequest; + if (m_xAccountFT->get_visible() && !m_realm.isEmpty()) + { + std::unique_ptr<weld::Label> xText(m_xBuilder->weld_label(oldPwd ? "wrongloginrealm" : "loginrealm")); + aRequest = xText->get_label(); + aRequest = aRequest.replaceAll("%2", m_realm); + } + else + { + std::unique_ptr<weld::Label> xText(m_xBuilder->weld_label(oldPwd ? "wrongrequestinfo" : "requestinfo")); + aRequest = xText->get_label(); + } + aRequest = aRequest.replaceAll("%1", m_server); + m_xRequestInfo->set_label(aRequest); +} + +IMPL_LINK_NOARG(LoginDialog, OKHdl_Impl, weld::Button&, void) +{ + // trim the strings + m_xNameED->set_text(comphelper::string::strip(m_xNameED->get_text(), ' ')); + m_xPasswordED->set_text(comphelper::string::strip(m_xPasswordED->get_text(), ' ')); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(LoginDialog, UseSysCredsHdl_Impl, weld::Button&, void) +{ + EnableUseSysCredsControls_Impl( m_xUseSysCredsCB->get_active() ); +} + +LoginDialog::LoginDialog(weld::Window* pParent, LoginFlags nFlags, + const OUString& rServer, const OUString& rRealm) + : GenericDialogController(pParent, "uui/ui/logindialog.ui", "LoginDialog") + , m_xErrorFT(m_xBuilder->weld_label("errorft")) + , m_xErrorInfo(m_xBuilder->weld_label("errorinfo")) + , m_xRequestInfo(m_xBuilder->weld_label("requestinfo")) + , m_xNameFT(m_xBuilder->weld_label("nameft")) + , m_xNameED(m_xBuilder->weld_entry("nameed")) + , m_xPasswordFT(m_xBuilder->weld_label("passwordft")) + , m_xPasswordED(m_xBuilder->weld_entry("passworded")) + , m_xAccountFT(m_xBuilder->weld_label("accountft")) + , m_xAccountED(m_xBuilder->weld_entry("accounted")) + , m_xSavePasswdBtn(m_xBuilder->weld_check_button("remember")) + , m_xUseSysCredsCB(m_xBuilder->weld_check_button("syscreds")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_server(rServer), m_realm(rRealm) +{ + if ( !( nFlags & LoginFlags::NoUseSysCreds ) ) + EnableUseSysCredsControls_Impl( m_xUseSysCredsCB->get_active() ); + + SetRequest(); + + m_xNameED->set_max_length( _MAX_PATH ); + + m_xOKBtn->connect_clicked( LINK( this, LoginDialog, OKHdl_Impl ) ); + m_xUseSysCredsCB->connect_clicked( LINK( this, LoginDialog, UseSysCredsHdl_Impl ) ); + + HideControls_Impl( nFlags ); +} + +void LoginDialog::SetUseSystemCredentials( bool bUse ) +{ + if ( m_xUseSysCredsCB->get_visible() ) + { + m_xUseSysCredsCB->set_active( bUse ); + EnableUseSysCredsControls_Impl( bUse ); + } +} + +void LoginDialog::ClearPassword() +{ + m_xPasswordED->set_text( OUString() ); + + if ( m_xNameED->get_text().isEmpty() ) + m_xNameED->grab_focus(); + else + m_xPasswordED->grab_focus(); +} + +void LoginDialog::ClearAccount() +{ + m_xAccountED->set_text( OUString() ); + m_xAccountED->grab_focus(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/logindlg.hxx b/uui/source/logindlg.hxx new file mode 100644 index 000000000..ff799f450 --- /dev/null +++ b/uui/source/logindlg.hxx @@ -0,0 +1,87 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_LOGINDLG_HXX +#define INCLUDED_UUI_SOURCE_LOGINDLG_HXX + +#include <vcl/weld.hxx> +#include <o3tl/typed_flags_set.hxx> + + +enum class LoginFlags { + NONE = 0x0000, + NoSavePassword = 0x0008, // hide "save password" + NoErrorText = 0x0010, // hide message + UsernameReadonly = 0x0040, // "name" readonly + NoAccount = 0x0080, // hide "account" + NoUseSysCreds = 0x0100, // hide "use system credentials" +}; +namespace o3tl { + template<> struct typed_flags<LoginFlags> : is_typed_flags<LoginFlags, 0x01d8> {}; +} + + +class LoginDialog : public weld::GenericDialogController +{ + std::unique_ptr<weld::Label> m_xErrorFT; + std::unique_ptr<weld::Label> m_xErrorInfo; + std::unique_ptr<weld::Label> m_xRequestInfo; + std::unique_ptr<weld::Label> m_xNameFT; + std::unique_ptr<weld::Entry> m_xNameED; + std::unique_ptr<weld::Label> m_xPasswordFT; + std::unique_ptr<weld::Entry> m_xPasswordED; + std::unique_ptr<weld::Label> m_xAccountFT; + std::unique_ptr<weld::Entry> m_xAccountED; + std::unique_ptr<weld::CheckButton> m_xSavePasswdBtn; + std::unique_ptr<weld::CheckButton> m_xUseSysCredsCB; + std::unique_ptr<weld::Button> m_xOKBtn; + OUString m_server; + OUString m_realm; + + void HideControls_Impl( LoginFlags nFlags ); + void EnableUseSysCredsControls_Impl( bool bUseSysCredsEnabled ); + void SetRequest(); + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(UseSysCredsHdl_Impl, weld::Button&, void); + +public: + LoginDialog(weld::Window* pParent, LoginFlags nFlags, + const OUString& rServer, const OUString &rRealm); + virtual ~LoginDialog() override; + + OUString GetName() const { return m_xNameED->get_text(); } + void SetName( const OUString& rNewName ) { m_xNameED->set_text( rNewName ); } + OUString GetPassword() const { return m_xPasswordED->get_text(); } + void SetPassword( const OUString& rNew ); + OUString GetAccount() const { return m_xAccountED->get_text(); } + bool IsSavePassword() const { return m_xSavePasswdBtn->get_active(); } + void SetSavePassword( bool bSave ) { m_xSavePasswdBtn->set_active( bSave ); } + void SetSavePasswordText( const OUString& rTxt ) { m_xSavePasswdBtn->set_label( rTxt ); } + bool IsUseSystemCredentials() const { return m_xUseSysCredsCB->get_active(); } + void SetUseSystemCredentials( bool bUse ); + void SetErrorText( const OUString& rTxt ) { m_xErrorInfo->set_label( rTxt ); } + void ClearPassword(); + void ClearAccount(); +}; + + +#endif // INCLUDED_UUI_SOURCE_LOGINDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/loginerr.hxx b/uui/source/loginerr.hxx new file mode 100644 index 000000000..f0dd879e4 --- /dev/null +++ b/uui/source/loginerr.hxx @@ -0,0 +1,161 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_LOGINERR_HXX +#define INCLUDED_UUI_SOURCE_LOGINERR_HXX + +#include <rtl/ustring.hxx> +#include <vcl/errinf.hxx> + +#define LOGINERROR_FLAG_MODIFY_ACCOUNT 1 +#define LOGINERROR_FLAG_MODIFY_USER_NAME 2 +#define LOGINERROR_FLAG_CAN_REMEMBER_PASSWORD 4 +#define LOGINERROR_FLAG_IS_REMEMBER_PASSWORD 8 +#define LOGINERROR_FLAG_CAN_USE_SYSCREDS 16 +#define LOGINERROR_FLAG_IS_USE_SYSCREDS 32 +#define LOGINERROR_FLAG_REMEMBER_PERSISTENT 64 + +class LoginErrorInfo +{ +private: + OUString m_aServer; + OUString m_aAccount; + OUString m_aUserName; + OUString m_aPassword; + OUString m_aPasswordToModify; + OUString m_aErrorText; + sal_uInt8 m_nFlags; + DialogMask m_nRet; + bool m_bRecommendToOpenReadonly; + +public: + LoginErrorInfo() + : m_nFlags(LOGINERROR_FLAG_MODIFY_USER_NAME) + , m_nRet(DialogMask::ButtonsCancel) + , m_bRecommendToOpenReadonly(false) + { + } + + const OUString& GetServer() const { return m_aServer; } + const OUString& GetAccount() const { return m_aAccount; } + const OUString& GetUserName() const { return m_aUserName; } + const OUString& GetPassword() const { return m_aPassword; } + const OUString& GetPasswordToModify() const { return m_aPasswordToModify; } + bool IsRecommendToOpenReadonly() const { return m_bRecommendToOpenReadonly; } + const OUString& GetErrorText() const { return m_aErrorText; } + bool GetCanRememberPassword() const { return ( m_nFlags & LOGINERROR_FLAG_CAN_REMEMBER_PASSWORD ); } + bool GetIsRememberPersistent() const { return ( m_nFlags & LOGINERROR_FLAG_REMEMBER_PERSISTENT ); } + bool GetIsRememberPassword() const { return ( m_nFlags & LOGINERROR_FLAG_IS_REMEMBER_PASSWORD ); } + + bool GetCanUseSystemCredentials() const + { return ( m_nFlags & LOGINERROR_FLAG_CAN_USE_SYSCREDS ); } + bool GetIsUseSystemCredentials() const + { return ( m_nFlags & LOGINERROR_FLAG_IS_USE_SYSCREDS ) == + LOGINERROR_FLAG_IS_USE_SYSCREDS; } + sal_uInt8 GetFlags() const { return m_nFlags; } + DialogMask GetResult() const { return m_nRet; } + + void SetServer( const OUString& aServer ) + { m_aServer = aServer; } + void SetAccount( const OUString& aAccount ) + { m_aAccount = aAccount; } + void SetUserName( const OUString& aUserName ) + { m_aUserName = aUserName; } + void SetPassword( const OUString& aPassword ) + { m_aPassword = aPassword; } + void SetPasswordToModify( const OUString& aPassword ) + { m_aPasswordToModify = aPassword; } + void SetRecommendToOpenReadonly( bool bVal ) + { m_bRecommendToOpenReadonly = bVal; } + void SetErrorText( const OUString& aErrorText ) + { m_aErrorText = aErrorText; } + + inline void SetCanRememberPassword( bool bSet ); + inline void SetIsRememberPassword( bool bSet ); + inline void SetIsRememberPersistent( bool bSet ); + + inline void SetCanUseSystemCredentials( bool bSet ); + inline void SetIsUseSystemCredentials( bool bSet ); + inline void SetModifyAccount( bool bSet ); + inline void SetModifyUserName( bool bSet ); + + void SetResult( DialogMask nRet ) + { m_nRet = nRet; } +}; + +inline void LoginErrorInfo::SetCanRememberPassword( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_CAN_REMEMBER_PASSWORD; + else + m_nFlags &= ~LOGINERROR_FLAG_CAN_REMEMBER_PASSWORD; +} + +inline void LoginErrorInfo::SetIsRememberPassword( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_IS_REMEMBER_PASSWORD; + else + m_nFlags &= ~LOGINERROR_FLAG_IS_REMEMBER_PASSWORD; +} + +inline void LoginErrorInfo::SetIsRememberPersistent( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_REMEMBER_PERSISTENT; + else + m_nFlags &= ~LOGINERROR_FLAG_REMEMBER_PERSISTENT; +} + +inline void LoginErrorInfo::SetCanUseSystemCredentials( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_CAN_USE_SYSCREDS; + else + m_nFlags &= ~LOGINERROR_FLAG_CAN_USE_SYSCREDS; +} + +inline void LoginErrorInfo::SetIsUseSystemCredentials( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_IS_USE_SYSCREDS; + else + m_nFlags &= ~LOGINERROR_FLAG_IS_USE_SYSCREDS; +} + +inline void LoginErrorInfo::SetModifyAccount( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_MODIFY_ACCOUNT; + else + m_nFlags &= ~LOGINERROR_FLAG_MODIFY_ACCOUNT; +} + +inline void LoginErrorInfo::SetModifyUserName( bool bSet ) +{ + if ( bSet ) + m_nFlags |= LOGINERROR_FLAG_MODIFY_USER_NAME; + else + m_nFlags &= ~LOGINERROR_FLAG_MODIFY_USER_NAME; +} + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/masterpasscrtdlg.cxx b/uui/source/masterpasscrtdlg.cxx new file mode 100644 index 000000000..4801bec28 --- /dev/null +++ b/uui/source/masterpasscrtdlg.cxx @@ -0,0 +1,68 @@ +/* -*- 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 . + */ + +#include <unotools/resmgr.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <strings.hrc> +#include "masterpasscrtdlg.hxx" + +// MasterPasswordCreateDialog--------------------------------------------------- + + +IMPL_LINK_NOARG(MasterPasswordCreateDialog, EditHdl_Impl, weld::Entry&, void) +{ + m_xOKBtn->set_sensitive(m_xEDMasterPasswordCrt->get_text().getLength() >= 1); +} + +IMPL_LINK_NOARG(MasterPasswordCreateDialog, OKHdl_Impl, weld::Button&, void) +{ + // compare both passwords and show message box if there are not equal!! + if (m_xEDMasterPasswordCrt->get_text() == m_xEDMasterPasswordRepeat->get_text()) + m_xDialog->response(RET_OK); + else + { + OUString aErrorMsg(Translate::get(STR_ERROR_PASSWORDS_NOT_IDENTICAL, rResLocale)); + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + aErrorMsg)); + xErrorBox->run(); + m_xEDMasterPasswordCrt->set_text( OUString() ); + m_xEDMasterPasswordRepeat->set_text( OUString() ); + m_xEDMasterPasswordCrt->grab_focus(); + } +} + +MasterPasswordCreateDialog::MasterPasswordCreateDialog(weld::Window* pParent, const std::locale& rLocale) + : GenericDialogController(pParent, "uui/ui/setmasterpassworddlg.ui", "SetMasterPasswordDialog") + , rResLocale(rLocale) + , m_xEDMasterPasswordCrt(m_xBuilder->weld_entry("password1")) + , m_xEDMasterPasswordRepeat(m_xBuilder->weld_entry("password2")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + m_xOKBtn->set_sensitive(false); + m_xOKBtn->connect_clicked( LINK( this, MasterPasswordCreateDialog, OKHdl_Impl ) ); + m_xEDMasterPasswordCrt->connect_changed( LINK( this, MasterPasswordCreateDialog, EditHdl_Impl ) ); +} + +MasterPasswordCreateDialog::~MasterPasswordCreateDialog() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/masterpasscrtdlg.hxx b/uui/source/masterpasscrtdlg.hxx new file mode 100644 index 000000000..c19ecb23e --- /dev/null +++ b/uui/source/masterpasscrtdlg.hxx @@ -0,0 +1,46 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_MASTERPASSCRTDLG_HXX +#define INCLUDED_UUI_SOURCE_MASTERPASSCRTDLG_HXX + +#include <vcl/weld.hxx> + +class MasterPasswordCreateDialog : public weld::GenericDialogController +{ +private: + const std::locale& rResLocale; + + std::unique_ptr<weld::Entry> m_xEDMasterPasswordCrt; + std::unique_ptr<weld::Entry> m_xEDMasterPasswordRepeat; + std::unique_ptr<weld::Button> m_xOKBtn; + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(EditHdl_Impl, weld::Entry&, void); + +public: + MasterPasswordCreateDialog(weld::Window* pParent, const std::locale& rLocale); + virtual ~MasterPasswordCreateDialog() override; + + OUString GetMasterPassword() const { return m_xEDMasterPasswordCrt->get_text(); } +}; + +#endif // INCLUDED_UUI_SOURCE_MASTERPASSCRTDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/masterpassworddlg.cxx b/uui/source/masterpassworddlg.cxx new file mode 100644 index 000000000..7fcc7f2d7 --- /dev/null +++ b/uui/source/masterpassworddlg.cxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ + +#include <unotools/resmgr.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <strings.hrc> +#include "masterpassworddlg.hxx" + +// MasterPasswordDialog--------------------------------------------------- + +IMPL_LINK_NOARG(MasterPasswordDialog, OKHdl_Impl, weld::Button&, void) +{ + m_xDialog->response(RET_OK); +} + +MasterPasswordDialog::MasterPasswordDialog +( + weld::Window* pParent, + css::task::PasswordRequestMode nDialogMode, + const std::locale& rLocale +) + : GenericDialogController(pParent, "uui/ui/masterpassworddlg.ui", "MasterPasswordDialog") + , m_xEDMasterPassword(m_xBuilder->weld_entry("password")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) +{ + if( nDialogMode == css::task::PasswordRequestMode_PASSWORD_REENTER ) + { + OUString aErrorMsg(Translate::get(STR_ERROR_MASTERPASSWORD_WRONG, rLocale)); + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pParent, + VclMessageType::Warning, VclButtonsType::Ok, aErrorMsg)); + xErrorBox->run(); + } + + m_xOKBtn->connect_clicked( LINK( this, MasterPasswordDialog, OKHdl_Impl ) ); +}; + +MasterPasswordDialog::~MasterPasswordDialog() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/masterpassworddlg.hxx b/uui/source/masterpassworddlg.hxx new file mode 100644 index 000000000..6e3e94f29 --- /dev/null +++ b/uui/source/masterpassworddlg.hxx @@ -0,0 +1,43 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_MASTERPASSWORDDLG_HXX +#define INCLUDED_UUI_SOURCE_MASTERPASSWORDDLG_HXX + +#include <com/sun/star/task/PasswordRequestMode.hpp> +#include <vcl/weld.hxx> + +class MasterPasswordDialog : public weld::GenericDialogController +{ +private: + std::unique_ptr<weld::Entry> m_xEDMasterPassword; + std::unique_ptr<weld::Button> m_xOKBtn; + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + +public: + MasterPasswordDialog(weld::Window* pParent, css::task::PasswordRequestMode nDlgMode, const std::locale& rLocale); + virtual ~MasterPasswordDialog() override; + + OUString GetMasterPassword() const { return m_xEDMasterPassword->get_text(); } +}; + +#endif // INCLUDED_UUI_SOURCE_MASTERPASSWORDDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/nameclashdlg.cxx b/uui/source/nameclashdlg.cxx new file mode 100644 index 000000000..5c64583da --- /dev/null +++ b/uui/source/nameclashdlg.cxx @@ -0,0 +1,102 @@ +/* -*- 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 . + */ + +#include <osl/file.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +#include <strings.hrc> +#include "nameclashdlg.hxx" + +// NameClashDialog --------------------------------------------------------- + +IMPL_LINK(NameClashDialog, ButtonHdl_Impl, weld::Button&, rBtn, void) +{ + long nRet = long(ABORT); + if (m_xBtnRename.get() == &rBtn) + { + nRet = long(RENAME); + OUString aNewName = m_xEDNewName->get_text(); + if ( ( aNewName == m_aNewName ) || aNewName.isEmpty() ) + { + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + m_aSameName)); + xErrorBox->run(); + return; + } + m_aNewName = aNewName; + } + else if (m_xBtnOverwrite.get() == &rBtn) + nRet = long(OVERWRITE); + + m_xDialog->response(nRet); +} + + +NameClashDialog::NameClashDialog( weld::Window* pParent, const std::locale& rResLocale, + OUString const & rTargetFolderURL, + OUString const & rClashingName, + OUString const & rProposedNewName, + bool bAllowOverwrite ) + : GenericDialogController(pParent, "uui/ui/simplenameclash.ui", "SimpleNameClashDialog") + , m_aNewName(rClashingName) + , m_xFTMessage(m_xBuilder->weld_label("warning")) + , m_xEDNewName(m_xBuilder->weld_entry("newname")) + , m_xBtnOverwrite(m_xBuilder->weld_button("replace")) + , m_xBtnRename(m_xBuilder->weld_button("rename")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) +{ + Link<weld::Button&,void> aLink( LINK( this, NameClashDialog, ButtonHdl_Impl ) ); + m_xBtnOverwrite->connect_clicked( aLink ); + m_xBtnRename->connect_clicked( aLink ); + m_xBtnCancel->connect_clicked( aLink ); + + OUString aInfo; + if ( bAllowOverwrite ) + { + aInfo = Translate::get(STR_RENAME_OR_REPLACE, rResLocale); + } + else + { + aInfo = Translate::get(STR_NAME_CLASH_RENAME_ONLY, rResLocale); + m_xBtnOverwrite->hide(); + } + + OUString aPath; + if ( osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( rTargetFolderURL, aPath ) ) + aPath = rTargetFolderURL; + + m_aSameName = Translate::get(STR_SAME_NAME_USED, rResLocale); + + aInfo = aInfo.replaceFirst( "%NAME", rClashingName ); + aInfo = aInfo.replaceFirst( "%FOLDER", aPath ); + m_xFTMessage->set_label(aInfo); + if ( !rProposedNewName.isEmpty() ) + m_xEDNewName->set_text( rProposedNewName ); + else + m_xEDNewName->set_text( rClashingName ); +} + +NameClashDialog::~NameClashDialog() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/nameclashdlg.hxx b/uui/source/nameclashdlg.hxx new file mode 100644 index 000000000..39d9af835 --- /dev/null +++ b/uui/source/nameclashdlg.hxx @@ -0,0 +1,52 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_NAMECLASHDLG_HXX +#define INCLUDED_UUI_SOURCE_NAMECLASHDLG_HXX + +#include <vcl/weld.hxx> + +enum NameClashResolveDialogResult { ABORT, RENAME, OVERWRITE }; + +class NameClashDialog : public weld::GenericDialogController +{ + OUString m_aSameName; + OUString m_aNewName; + + std::unique_ptr<weld::Label> m_xFTMessage; + std::unique_ptr<weld::Entry> m_xEDNewName; + std::unique_ptr<weld::Button> m_xBtnOverwrite; + std::unique_ptr<weld::Button> m_xBtnRename; + std::unique_ptr<weld::Button> m_xBtnCancel; + + DECL_LINK(ButtonHdl_Impl, weld::Button&, void); + +public: + NameClashDialog(weld::Window* pParent, const std::locale& rLocale, + OUString const & rTargetFolderURL, + OUString const & rClashingName, + OUString const & rProposedNewName, + bool bAllowOverwrite); + virtual ~NameClashDialog() override; + const OUString& getNewName() const { return m_aNewName; } +}; + +#endif // UUI_COOKIEDG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/openlocked.cxx b/uui/source/openlocked.cxx new file mode 100644 index 000000000..fa2a4616c --- /dev/null +++ b/uui/source/openlocked.cxx @@ -0,0 +1,41 @@ +/* -*- 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 . + */ + +#include <strings.hrc> +#include "openlocked.hxx" +#include <officecfg/Office/Common.hxx> +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> + +OpenLockedQueryBox::OpenLockedQueryBox(weld::Window* pParent, const std::locale& rResLocale, const OUString& rMessage, bool bEnableOverride) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, rMessage)) +{ + m_xQueryBox->set_title(Translate::get(STR_OPENLOCKED_TITLE, rResLocale)); + m_xQueryBox->add_button(Translate::get(STR_OPENLOCKED_OPENREADONLY_BTN, rResLocale), RET_YES); + m_xQueryBox->add_button(Translate::get(STR_OPENLOCKED_OPENCOPY_BTN, rResLocale), RET_NO); + if (bEnableOverride && officecfg::Office::Common::Misc::AllowOverrideLocking::get()) + { + // Present option to ignore the (stale?) lock file and open the document + m_xQueryBox->add_button(Translate::get(STR_ALREADYOPEN_OPEN_BTN, rResLocale), RET_IGNORE); + } + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/openlocked.hxx b/uui/source/openlocked.hxx new file mode 100644 index 000000000..c4835c8c1 --- /dev/null +++ b/uui/source/openlocked.hxx @@ -0,0 +1,35 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_OPENLOCKED_HXX +#define INCLUDED_UUI_SOURCE_OPENLOCKED_HXX + +#include <vcl/weld.hxx> + +class OpenLockedQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; +public: + OpenLockedQueryBox(weld::Window* pParent, const std::locale& rResLocale, const OUString& rMessage, bool bEnableOverride); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/passwordcontainer.cxx b/uui/source/passwordcontainer.cxx new file mode 100644 index 000000000..a97725ef1 --- /dev/null +++ b/uui/source/passwordcontainer.cxx @@ -0,0 +1,425 @@ +/* -*- 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 . + */ + +#include <comphelper/processfactory.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <osl/diagnose.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/task/NoMasterException.hpp> +#include <com/sun/star/task/PasswordContainer.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/ucb/AuthenticationRequest.hpp> +#include <com/sun/star/ucb/URLAuthenticationRequest.hpp> +#include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp> +#include <com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp> +#include <officecfg/Office/Common.hxx> + +#include "passwordcontainer.hxx" + +using namespace com::sun::star; + +namespace { + + +bool fillContinuation( + bool bUseSystemCredentials, + const ucb::AuthenticationRequest & rRequest, + const task::UrlRecord & aRec, + const uno::Reference< ucb::XInteractionSupplyAuthentication > & + xSupplyAuthentication, + const uno::Reference< ucb::XInteractionSupplyAuthentication2 > & + xSupplyAuthentication2, + bool bCanUseSystemCredentials, + bool bCheckForEqualPasswords ) +{ + if ( bUseSystemCredentials ) + { + // "use system creds" record found. + // Wants client that we use it? + if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials ) + { + xSupplyAuthentication2->setUseSystemCredentials( true ); + return true; + } + return false; + } + else if (aRec.UserList.hasElements()) + { + if (!aRec.UserList[0].Passwords.hasElements()) + { + // Password sequence can be empty, for instance if master + // password was not given (e.g. master pw dialog canceled) + // pw container does not throw NoMasterException in this case. + // bug??? + return false; + } + + // "user/pass" record found. + if (!bCheckForEqualPasswords || !rRequest.HasPassword + || rRequest.Password != aRec.UserList[0].Passwords[0]) // failed login attempt? + { + if (xSupplyAuthentication->canSetUserName()) + xSupplyAuthentication-> + setUserName(aRec.UserList[0].UserName); + + if (xSupplyAuthentication->canSetPassword()) + xSupplyAuthentication-> + setPassword(aRec.UserList[0].Passwords[0]); + if (aRec.UserList[0].Passwords.getLength() > 1) + { + if (rRequest.HasRealm) + { + if (xSupplyAuthentication->canSetRealm()) + xSupplyAuthentication-> + setRealm(aRec.UserList[0].Passwords[1]); + } + else if (xSupplyAuthentication->canSetAccount()) + xSupplyAuthentication-> + setAccount(aRec.UserList[0].Passwords[1]); + } + + if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials ) + xSupplyAuthentication2->setUseSystemCredentials( false ); + + return true; + } + } + return false; +} + +} // namespace + +namespace uui { + + +PasswordContainerHelper::PasswordContainerHelper( + uno::Reference< uno::XComponentContext > const & xContext ): + m_xPasswordContainer(task::PasswordContainer::create(xContext)) +{} + + +bool PasswordContainerHelper::handleAuthenticationRequest( + ucb::AuthenticationRequest const & rRequest, + uno::Reference< ucb::XInteractionSupplyAuthentication > const & + xSupplyAuthentication, + OUString const & rURL, + uno::Reference< task::XInteractionHandler2 > const & xIH ) +{ + // Is continuation even a XInteractionSupplyAuthentication2, which + // is derived from XInteractionSupplyAuthentication? + uno::Reference< ucb::XInteractionSupplyAuthentication2 > + xSupplyAuthentication2(xSupplyAuthentication, uno::UNO_QUERY); + + bool bCanUseSystemCredentials = false; + if (xSupplyAuthentication2.is()) + { + sal_Bool bDefaultUseSystemCredentials; + bCanUseSystemCredentials + = xSupplyAuthentication2->canUseSystemCredentials( + bDefaultUseSystemCredentials ); + } + + if ( bCanUseSystemCredentials ) + { + // Does the configuration mandate that we try system credentials first? + bool bUseSystemCredentials = ::officecfg::Office::Common::Passwords::TrySystemCredentialsFirst::get(); + if (!bUseSystemCredentials) + { + // Runtime / Persistent info avail for current auth request? + OUString aResult = m_xPasswordContainer->findUrl( + rURL.isEmpty() ? rRequest.ServerName : rURL); + bUseSystemCredentials = !aResult.isEmpty(); + } + if ( bUseSystemCredentials ) + { + if ( fillContinuation( true, + rRequest, + task::UrlRecord(), + xSupplyAuthentication, + xSupplyAuthentication2, + bCanUseSystemCredentials, + false ) ) + { + return true; + } + } + } + + // m_xPasswordContainer works with userName passwdSequences pairs: + if (rRequest.HasUserName && rRequest.HasPassword) + { + try + { + if (rRequest.UserName.isEmpty()) + { + task::UrlRecord aRec; + if ( !rURL.isEmpty() ) + aRec = m_xPasswordContainer->find(rURL, xIH); + + if ( !aRec.UserList.hasElements() ) + { + // compat: try server name. + aRec = m_xPasswordContainer->find(rRequest.ServerName, xIH); + } + + if ( fillContinuation( false, + rRequest, + aRec, + xSupplyAuthentication, + xSupplyAuthentication2, + bCanUseSystemCredentials, + false ) ) + { + return true; + } + } + else + { + task::UrlRecord aRec; + if ( !rURL.isEmpty() ) + aRec = m_xPasswordContainer->findForName( + rURL, rRequest.UserName, xIH); + + if ( !aRec.UserList.hasElements() ) + { + // compat: try server name. + aRec = m_xPasswordContainer->findForName( + rRequest.ServerName, rRequest.UserName, xIH); + } + + if ( fillContinuation( false, + rRequest, + aRec, + xSupplyAuthentication, + xSupplyAuthentication2, + bCanUseSystemCredentials, + true ) ) + { + return true; + } + } + } + catch (task::NoMasterException const &) + {} // user did not enter master password + } + return false; +} + + +bool PasswordContainerHelper::addRecord( + OUString const & rURL, + OUString const & rUsername, + uno::Sequence< OUString > const & rPasswords, + uno::Reference< task::XInteractionHandler2 > const & xIH, + bool bPersist ) +{ + try + { + if ( !rUsername.isEmpty() ) + { + OSL_ENSURE( m_xPasswordContainer.is(), + "Got no XPasswordContainer!" ); + if ( !m_xPasswordContainer.is() ) + return false; + + if ( bPersist ) + { + // If persistent storing of passwords is not yet + // allowed, enable it. + if ( !m_xPasswordContainer->isPersistentStoringAllowed() ) + m_xPasswordContainer->allowPersistentStoring( true ); + + m_xPasswordContainer->addPersistent( rURL, + rUsername, + rPasswords, + xIH ); + } + else + m_xPasswordContainer->add( rURL, + rUsername, + rPasswords, + xIH ); + } + else + { + m_xPasswordContainer->addUrl( rURL, bPersist ); + } + } + catch ( task::NoMasterException const & ) + { + // user did not enter master password + return false; + } + return true; +} + + +PasswordContainerInteractionHandler::PasswordContainerInteractionHandler( + const uno::Reference< uno::XComponentContext >& xContext ) +: m_aPwContainerHelper( xContext ) +{ +} + + +// virtual +PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler() +{ +} + + +// XServiceInfo methods. + + +// virtual +OUString SAL_CALL +PasswordContainerInteractionHandler::getImplementationName() +{ + return getImplementationName_Static(); +} + + +// virtual +sal_Bool SAL_CALL +PasswordContainerInteractionHandler::supportsService( + const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + + +// virtual +uno::Sequence< OUString > SAL_CALL +PasswordContainerInteractionHandler::getSupportedServiceNames() +{ + return getSupportedServiceNames_Static(); +} + + +// static +OUString +PasswordContainerInteractionHandler::getImplementationName_Static() +{ + return "com.sun.star.comp.uui.PasswordContainerInteractionHandler"; +} + + +// static +uno::Sequence< OUString > +PasswordContainerInteractionHandler::getSupportedServiceNames_Static() +{ + uno::Sequence< OUString > aSNS { "com.sun.star.task.PasswordContainerInteractionHandler" }; + return aSNS; +} + + +// XInteractionHandler2 methods. + + +// virtual +void SAL_CALL +PasswordContainerInteractionHandler::handle( + const uno::Reference< task::XInteractionRequest >& rRequest ) +{ + handleInteractionRequest( rRequest ); +} + +// virtual +sal_Bool SAL_CALL +PasswordContainerInteractionHandler::handleInteractionRequest( + const uno::Reference< task::XInteractionRequest >& rRequest ) +{ + if ( !rRequest.is() ) + return false; + + uno::Any aAnyRequest( rRequest->getRequest() ); + + ucb::AuthenticationRequest aAuthenticationRequest; + if ( !( aAnyRequest >>= aAuthenticationRequest ) ) + return false; + + OUString aURL; + ucb::URLAuthenticationRequest aURLAuthenticationRequest; + if ( aAnyRequest >>= aURLAuthenticationRequest ) + aURL = aURLAuthenticationRequest.URL; + + const uno::Sequence< uno::Reference< task::XInteractionContinuation > > + rContinuations = rRequest->getContinuations(); + + uno::Reference< ucb::XInteractionSupplyAuthentication > + xSupplyAuthentication; + + for ( const auto& rContinuation : rContinuations ) + { + xSupplyAuthentication.set( rContinuation, uno::UNO_QUERY ); + if( xSupplyAuthentication.is() ) + break; + } + + if ( !xSupplyAuthentication.is() ) + return false; + + // Try to obtain credentials from password container. + if ( m_aPwContainerHelper. + handleAuthenticationRequest( aAuthenticationRequest, + xSupplyAuthentication, + aURL, + // @@@ FIXME: this not able to + // handle master pw request! + // master pw request is never + // solvable without UI! + this ) ) + { + // successfully handled + xSupplyAuthentication->select(); + return true; + } + return false; +} + + +// Service factory implementation. + +/// @throws uno::Exception +static uno::Reference< uno::XInterface > +PasswordContainerInteractionHandler_CreateInstance( + const uno::Reference< lang::XMultiServiceFactory> & rSMgr ) +{ + lang::XServiceInfo* pX + = new PasswordContainerInteractionHandler(comphelper::getComponentContext(rSMgr)); + return uno::Reference< uno::XInterface >::query( pX ); +} + + +// static +uno::Reference< lang::XSingleServiceFactory > +PasswordContainerInteractionHandler::createServiceFactory( + const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr ) +{ + return cppu::createOneInstanceFactory( + rxServiceMgr, + PasswordContainerInteractionHandler::getImplementationName_Static(), + PasswordContainerInteractionHandler_CreateInstance, + PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ); +} + +} // namespace uui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/passwordcontainer.hxx b/uui/source/passwordcontainer.hxx new file mode 100644 index 000000000..2e2545fa6 --- /dev/null +++ b/uui/source/passwordcontainer.hxx @@ -0,0 +1,171 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_PASSWORDCONTAINER_HXX +#define INCLUDED_UUI_SOURCE_PASSWORDCONTAINER_HXX + +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/task/XPasswordContainer2.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +namespace com { + namespace sun { + namespace star { + namespace lang { + class XMultiServiceFactory; + } + namespace ucb { + class AuthenticationRequest; + class XInteractionSupplyAuthentication; +} } } } + +namespace uui { + + +/** Passwordcontainer UNO service (com.sun.star.task.PasswordContainer) helper. + */ +class PasswordContainerHelper +{ +public: + explicit PasswordContainerHelper( + css::uno::Reference< css::uno::XComponentContext > const & xContext ); + + + /** This member function tries to handle an authentication interaction + request by looking up credentials for the given URL in the password + container service. + + In case of success the given interaction continuation + (XInteractionSupplyAuthentication) is filled with the credentials found + in the password container. + + Please note the continuation gets not "selected" by this + implementation. "Selecting" the continuation is up to the caller (e.g. + an implementation of XInteractionHandler::handle) of this function. + + @param rRequest + The authentication request. + + @param xSupplyAuthentication + The "supply authentication" interaction continuation. + + @param rURL + The URL to lookup credentials for. + + @param xIH + The interaction handler to use, for example if a master password is + needed to access the password container. + + @return + True, if the authentication request was handled successfully. + False, otherwise. + */ + bool handleAuthenticationRequest( + css::ucb::AuthenticationRequest const & rRequest, + css::uno::Reference< css::ucb::XInteractionSupplyAuthentication > const & xSupplyAuthentication, + OUString const & rURL, + css::uno::Reference< css::task::XInteractionHandler2 > const & xIH ); + + /** This member function adds credentials for the given URL to the password + container. + + @param rURL + The URL the credentials are valid for. rURL must not be empty. + + @param rUsername + The user name. + + @param rPasswords + This list of passwords. + + @param xIH + The interaction handler to use, for example if a master password is + needed to access the password container. + + @param bPersist + True, the record will get stored persistently; restored upon + password container initialization + False, the record will be stored until password container instance + gets destroyed. + + @return + True, if the record was added successfully. + False, otherwise. + + */ + bool addRecord( OUString const & rURL, + OUString const & rUsername, + css::uno::Sequence< OUString > const & rPasswords, + css::uno::Reference< css::task::XInteractionHandler2 > const & xIH, + bool bPersist ); + + +private: + css::uno::Reference< css::task::XPasswordContainer2 > m_xPasswordContainer; +}; + + +class PasswordContainerInteractionHandler : + public cppu::WeakImplHelper< css::lang::XServiceInfo, + css::task::XInteractionHandler2 > +{ +public: + explicit PasswordContainerInteractionHandler( + const css::uno::Reference< css::uno::XComponentContext >& xContext ); + virtual ~PasswordContainerInteractionHandler() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL + supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + // XInteractionHandler2 + virtual void SAL_CALL + handle( const css::uno::Reference< css::task::XInteractionRequest >& Request ) override; + + virtual sal_Bool SAL_CALL + handleInteractionRequest( const css::uno::Reference< css::task::XInteractionRequest >& Request ) override; + + // Non-UNO interfaces + static OUString + getImplementationName_Static(); + + static css::uno::Sequence< OUString > + getSupportedServiceNames_Static(); + + static css::uno::Reference< css::lang::XSingleServiceFactory > + createServiceFactory( const css::uno::Reference< css::lang::XMultiServiceFactory > & rxServiceMgr ); + +private: + PasswordContainerHelper m_aPwContainerHelper; +}; + +} // namespace uui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/passworddlg.cxx b/uui/source/passworddlg.cxx new file mode 100644 index 000000000..3e8d1550f --- /dev/null +++ b/uui/source/passworddlg.cxx @@ -0,0 +1,113 @@ +/* -*- 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 . + */ + +#include "passworddlg.hxx" +#include <strings.hrc> + +#include <unotools/resmgr.hxx> +#include <tools/urlobj.hxx> +#include <tools/debug.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +using namespace ::com::sun::star; + +PasswordDialog::PasswordDialog(weld::Window* pParent, + task::PasswordRequestMode nDialogMode, const std::locale& rResLocale, + const OUString& aDocURL, bool bOpenToModify, bool bIsSimplePasswordRequest) + : GenericDialogController(pParent, "uui/ui/password.ui", "PasswordDialog") + , m_xFTPassword(m_xBuilder->weld_label("newpassFT")) + , m_xEDPassword(m_xBuilder->weld_entry("newpassEntry")) + , m_xFTConfirmPassword(m_xBuilder->weld_label("confirmpassFT")) + , m_xEDConfirmPassword(m_xBuilder->weld_entry("confirmpassEntry")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , nMinLen(1) + , aPasswdMismatch(Translate::get(STR_PASSWORD_MISMATCH, rResLocale)) +{ + // tdf#115964 we can be launched before the parent has resized to its final size + m_xDialog->set_centered_on_parent(true); + + if( nDialogMode == task::PasswordRequestMode_PASSWORD_REENTER ) + { + const char* pOpenToModifyErrStrId = bOpenToModify ? STR_ERROR_PASSWORD_TO_MODIFY_WRONG : STR_ERROR_PASSWORD_TO_OPEN_WRONG; + const char* pErrStrId = bIsSimplePasswordRequest ? STR_ERROR_SIMPLE_PASSWORD_WRONG : pOpenToModifyErrStrId; + OUString aErrorMsg(Translate::get(pErrStrId, rResLocale)); + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, + VclMessageType::Warning, VclButtonsType::Ok, aErrorMsg)); + xBox->run(); + } + + // default settings for enter password or reenter passwd... + OUString aTitle(Translate::get(STR_TITLE_ENTER_PASSWORD, rResLocale)); + m_xFTConfirmPassword->hide(); + m_xEDConfirmPassword->hide(); + m_xFTConfirmPassword->set_sensitive(false); + m_xEDConfirmPassword->set_sensitive(false); + + // settings for create password + if (nDialogMode == task::PasswordRequestMode_PASSWORD_CREATE) + { + aTitle = Translate::get(STR_TITLE_CREATE_PASSWORD, rResLocale); + + m_xFTConfirmPassword->set_label(Translate::get(STR_CONFIRM_SIMPLE_PASSWORD, rResLocale)); + + m_xFTConfirmPassword->show(); + m_xEDConfirmPassword->show(); + m_xFTConfirmPassword->set_sensitive(true); + m_xEDConfirmPassword->set_sensitive(true); + } + + m_xDialog->set_title(aTitle); + + const char* pStrId = bOpenToModify ? STR_ENTER_PASSWORD_TO_MODIFY : STR_ENTER_PASSWORD_TO_OPEN; + OUString aMessage(Translate::get(pStrId, rResLocale)); + INetURLObject url(aDocURL); + aMessage += url.HasError() + ? aDocURL : url.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous); + m_xFTPassword->set_label(aMessage); + + if (bIsSimplePasswordRequest) + { + DBG_ASSERT( aDocURL.isEmpty(), "A simple password request should not have a document URL! Use document password request instead." ); + m_xFTPassword->set_label(Translate::get(STR_ENTER_SIMPLE_PASSWORD, rResLocale)); + } + + m_xOKBtn->connect_clicked(LINK(this, PasswordDialog, OKHdl_Impl)); +} + +IMPL_LINK_NOARG(PasswordDialog, OKHdl_Impl, weld::Button&, void) +{ + bool bEDPasswdValid = m_xEDPassword->get_text().getLength() >= nMinLen; + bool bPasswdMismatch = m_xEDConfirmPassword->get_text() != m_xEDPassword->get_text(); + bool bValid = (!m_xEDConfirmPassword->get_visible() && bEDPasswdValid) || + (m_xEDConfirmPassword->get_visible() && bEDPasswdValid && !bPasswdMismatch); + + if (m_xEDConfirmPassword->get_visible() && bPasswdMismatch) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + aPasswdMismatch)); + xBox->run(); + } + else if (bValid) + m_xDialog->response(RET_OK); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/uui/source/passworddlg.hxx b/uui/source/passworddlg.hxx new file mode 100644 index 000000000..2f9c21b71 --- /dev/null +++ b/uui/source/passworddlg.hxx @@ -0,0 +1,49 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_PASSWORDDLG_HXX +#define INCLUDED_UUI_SOURCE_PASSWORDDLG_HXX + +#include <com/sun/star/task/PasswordRequestMode.hpp> +#include <vcl/weld.hxx> + +class PasswordDialog : public weld::GenericDialogController +{ + std::unique_ptr<weld::Label> m_xFTPassword; + std::unique_ptr<weld::Entry> m_xEDPassword; + std::unique_ptr<weld::Label> m_xFTConfirmPassword; + std::unique_ptr<weld::Entry> m_xEDConfirmPassword; + std::unique_ptr<weld::Button> m_xOKBtn; + sal_uInt16 nMinLen; + OUString aPasswdMismatch; + + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + +public: + PasswordDialog(weld::Window* pParent, css::task::PasswordRequestMode nDlgMode, const std::locale& rLocale, const OUString& aDocURL, + bool bOpenToModify, bool bIsSimplePasswordRequest); + + void SetMinLen( sal_uInt16 nMin ) { nMinLen = nMin; } + OUString GetPassword() const { return m_xEDPassword->get_text(); } +}; + +#endif // INCLUDED_UUI_SOURCE_PASSWORDDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/requeststringresolver.cxx b/uui/source/requeststringresolver.cxx new file mode 100644 index 000000000..e9d73f074 --- /dev/null +++ b/uui/source/requeststringresolver.cxx @@ -0,0 +1,84 @@ +/* -*- 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 . + */ + +#include "requeststringresolver.hxx" +#include "iahndl.hxx" +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace css; + +UUIInteractionRequestStringResolver::UUIInteractionRequestStringResolver( + uno::Reference< uno::XComponentContext > const & + rxContext) + : m_pImpl(new UUIInteractionHelper(rxContext)) +{ +} + +UUIInteractionRequestStringResolver::~UUIInteractionRequestStringResolver() +{ +} + +OUString SAL_CALL +UUIInteractionRequestStringResolver::getImplementationName() +{ + return "com.sun.star.comp.uui.UUIInteractionRequestStringResolver"; +} + +sal_Bool SAL_CALL +UUIInteractionRequestStringResolver::supportsService( + OUString const & rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + + +uno::Sequence< OUString > SAL_CALL +UUIInteractionRequestStringResolver::getSupportedServiceNames() +{ + return { "com.sun.star.task.InteractionRequestStringResolver" }; +} + +beans::Optional< OUString > SAL_CALL +UUIInteractionRequestStringResolver::getStringFromInformationalRequest( + const uno::Reference< + task::XInteractionRequest >& Request ) +{ + try + { + return m_pImpl->getStringFromRequest(Request); + } + catch (uno::RuntimeException const & ex) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetRuntimeException( ex.Message, + *this, anyEx ); + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_uui_UUIInteractionRequestStringResolver_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new UUIInteractionRequestStringResolver(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/requeststringresolver.hxx b/uui/source/requeststringresolver.hxx new file mode 100644 index 000000000..27a94e6ba --- /dev/null +++ b/uui/source/requeststringresolver.hxx @@ -0,0 +1,63 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_REQUESTSTRINGRESOLVER_HXX +#define INCLUDED_UUI_SOURCE_REQUESTSTRINGRESOLVER_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/task/XInteractionRequestStringResolver.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <memory> + +class UUIInteractionHelper; + +class UUIInteractionRequestStringResolver: + public cppu::WeakImplHelper< + css::lang::XServiceInfo, + css::task::XInteractionRequestStringResolver > +{ +public: + explicit UUIInteractionRequestStringResolver( + css::uno::Reference< css::uno::XComponentContext > const & rxContext); + +private: + std::unique_ptr<UUIInteractionHelper> m_pImpl; + + UUIInteractionRequestStringResolver(UUIInteractionRequestStringResolver const &) = delete; + void operator =(UUIInteractionRequestStringResolver const &) = delete; + + virtual ~UUIInteractionRequestStringResolver() override; + + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(OUString const & + rServiceName) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + virtual css::beans::Optional< OUString > SAL_CALL + getStringFromInformationalRequest( + const css::uno::Reference< css::task::XInteractionRequest >& Request ) override; +}; + +#endif // INCLUDED_UUI_SOURCE_REQUESTSTRINGRESOLVER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/secmacrowarnings.cxx b/uui/source/secmacrowarnings.cxx new file mode 100644 index 000000000..2f987b241 --- /dev/null +++ b/uui/source/secmacrowarnings.cxx @@ -0,0 +1,189 @@ +/* -*- 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 . + */ + +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/security/DocumentDigitalSignatures.hpp> +#include <comphelper/processfactory.hxx> +#include <osl/file.h> +#include <rtl/ustrbuf.hxx> +#include <tools/debug.hxx> +#include <unotools/securityoptions.hxx> + +using namespace ::com::sun::star::security; + +#include "secmacrowarnings.hxx" + +using namespace ::com::sun::star; + + +// HACK!!! copied from xmlsecurity/source/dialog/resourcemanager.cxx + +namespace +{ + OUString GetContentPart( const OUString& _rRawString, const OUString& _rPartId ) + { + OUString s; + + sal_Int32 nContStart = _rRawString.indexOf( _rPartId ); + if( nContStart != -1 ) + { + nContStart = nContStart + _rPartId.getLength(); + ++nContStart; // now its start of content, directly after Id + + sal_Int32 nContEnd = _rRawString.indexOf( ',', nContStart ); + + if ( nContEnd != -1 ) + s = _rRawString.copy( nContStart, nContEnd - nContStart ); + else + s = _rRawString.copy( nContStart ); + } + + return s; + } +} + +MacroWarning::MacroWarning(weld::Window* pParent, bool _bWithSignatures) + : MessageDialogController(pParent, "uui/ui/macrowarnmedium.ui", "MacroWarnMedium", "grid") + , mxGrid(m_xBuilder->weld_widget("grid")) + , mxSignsFI(m_xBuilder->weld_label("signsLabel")) + , mxViewSignsBtn(m_xBuilder->weld_button("viewSignsButton")) + , mxAlwaysTrustCB(m_xBuilder->weld_check_button("alwaysTrustCheckbutton")) + , mxEnableBtn(m_xBuilder->weld_button("ok")) + , mxDisableBtn(m_xBuilder->weld_button("cancel")) + , mpInfos ( nullptr ) + , mbShowSignatures ( _bWithSignatures ) + , mnActSecLevel ( 0 ) +{ + InitControls(); + + mxEnableBtn->connect_clicked(LINK(this, MacroWarning, EnableBtnHdl)); + mxDisableBtn->grab_focus(); // Default button, but focus is on view button +} + +void MacroWarning::SetDocumentURL( const OUString& rDocURL ) +{ + OUString aAbbreviatedPath; + osl_abbreviateSystemPath(rDocURL.pData, &aAbbreviatedPath.pData, 50, nullptr); + m_xDialog->set_primary_text(aAbbreviatedPath); +} + +IMPL_LINK_NOARG(MacroWarning, ViewSignsBtnHdl, weld::Button&, void) +{ + DBG_ASSERT( mxCert.is(), "*MacroWarning::ViewSignsBtnHdl(): no certificate set!" ); + + uno::Reference< security::XDocumentDigitalSignatures > xD( + security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), maODFVersion)); + if( xD.is() ) + { + xD->setParentWindow(m_xDialog->GetXWindow()); + if( mxCert.is() ) + xD->showCertificate( mxCert ); + else if( mxStore.is() ) + xD->showScriptingContentSignatures( mxStore, uno::Reference< io::XInputStream >() ); + } +} + +IMPL_LINK_NOARG(MacroWarning, EnableBtnHdl, weld::Button&, void) +{ + if (mxAlwaysTrustCB->get_active()) + { + uno::Reference< security::XDocumentDigitalSignatures > xD( + security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), maODFVersion)); + xD->setParentWindow(m_xDialog->GetXWindow()); + if( mxCert.is() ) + xD->addAuthorToTrustedSources( mxCert ); + else if( mxStore.is() ) + { + DBG_ASSERT( mpInfos, "-MacroWarning::EnableBtnHdl(): no infos, search in nirvana..." ); + + sal_Int32 nCnt = mpInfos->getLength(); + for( sal_Int32 i = 0 ; i < nCnt ; ++i ) + xD->addAuthorToTrustedSources( (*mpInfos)[ i ].Signer ); + } + } + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(MacroWarning, AlwaysTrustCheckHdl, weld::Button&, void) +{ + const bool bEnable = (mnActSecLevel < 2 || mxAlwaysTrustCB->get_active()); + mxEnableBtn->set_sensitive(bEnable); + mxDisableBtn->set_sensitive(!mxAlwaysTrustCB->get_active()); +} + +void MacroWarning::InitControls() +{ + // show signature controls? + if (mbShowSignatures) + { + mxViewSignsBtn->connect_clicked(LINK(this, MacroWarning, ViewSignsBtnHdl)); + mxViewSignsBtn->set_sensitive(false); + + const SvtSecurityOptions aSecOption; + if (!aSecOption.IsReadOnly(SvtSecurityOptions::EOption::MacroTrustedAuthors)) + mxAlwaysTrustCB->connect_clicked(LINK(this, MacroWarning, AlwaysTrustCheckHdl)); + else + mxAlwaysTrustCB->set_visible(false); + + mnActSecLevel = aSecOption.GetMacroSecurityLevel(); + if ( mnActSecLevel >= 2 ) + mxEnableBtn->set_sensitive(false); + } + else + { + mxGrid->hide(); + } +} + +void MacroWarning::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore, + const OUString& aODFVersion, + const css::uno::Sequence< security::DocumentSignatureInformation >& rInfos ) +{ + mxStore = rxStore; + maODFVersion = aODFVersion; + sal_Int32 nCnt = rInfos.getLength(); + if( mxStore.is() && nCnt > 0 ) + { + mpInfos = &rInfos; + OUString aCN_Id("CN"); + OUStringBuffer s = GetContentPart( rInfos[ 0 ].Signer->getSubjectName(), aCN_Id ); + + for( sal_Int32 i = 1 ; i < nCnt ; ++i ) + { + s.append("\n"); + s.append(GetContentPart( rInfos[ i ].Signer->getSubjectName(), aCN_Id )); + } + + mxSignsFI->set_label(s.makeStringAndClear()); + mxViewSignsBtn->set_sensitive(true); + } +} + +void MacroWarning::SetCertificate( const css::uno::Reference< css::security::XCertificate >& _rxCert ) +{ + mxCert = _rxCert; + if( mxCert.is() ) + { + OUString s = GetContentPart( mxCert->getSubjectName(), "CN" ); + mxSignsFI->set_label(s); + mxViewSignsBtn->set_sensitive(true); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/secmacrowarnings.hxx b/uui/source/secmacrowarnings.hxx new file mode 100644 index 000000000..590ef0768 --- /dev/null +++ b/uui/source/secmacrowarnings.hxx @@ -0,0 +1,72 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_UUI_SOURCE_SECMACROWARNINGS_HXX +#define INCLUDED_UUI_SOURCE_SECMACROWARNINGS_HXX + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/security/DocumentSignatureInformation.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <vcl/weld.hxx> + +namespace com { +namespace sun { +namespace star { +namespace security { + class XCertificate; } +}}} + +class MacroWarning : public weld::MessageDialogController +{ +private: + std::unique_ptr<weld::Widget> mxGrid; + std::unique_ptr<weld::Label> mxSignsFI; + std::unique_ptr<weld::Button> mxViewSignsBtn; + std::unique_ptr<weld::CheckButton> mxAlwaysTrustCB; + std::unique_ptr<weld::Button> mxEnableBtn; + std::unique_ptr<weld::Button> mxDisableBtn; + + css::uno::Reference< css::security::XCertificate > mxCert; + css::uno::Reference< css::embed::XStorage > mxStore; + OUString maODFVersion; + const css::uno::Sequence< css::security::DocumentSignatureInformation >* mpInfos; + + const bool mbShowSignatures; + sal_Int32 mnActSecLevel; + + DECL_LINK(ViewSignsBtnHdl, weld::Button&, void); + DECL_LINK(EnableBtnHdl, weld::Button&, void); + DECL_LINK(AlwaysTrustCheckHdl, weld::Button&, void); + + void InitControls(); + +public: + MacroWarning(weld::Window* pParent, bool _bShowSignatures); + + void SetDocumentURL( const OUString& rDocURL ); + + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore, + const OUString& aODFVersion, + const css::uno::Sequence< css::security::DocumentSignatureInformation >& _rInfos ); + void SetCertificate( const css::uno::Reference< css::security::XCertificate >& _rxCert ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/services.cxx b/uui/source/services.cxx new file mode 100644 index 000000000..7709e4176 --- /dev/null +++ b/uui/source/services.cxx @@ -0,0 +1,63 @@ +/* -*- 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 . + */ + +#include <cppuhelper/factory.hxx> +#include <rtl/ustring.hxx> +#include <sal/types.h> + +#include "passwordcontainer.hxx" + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; + + +extern "C" SAL_DLLPUBLIC_EXPORT void * uui_component_getFactory(char const * pImplName, + void * pServiceManager, + void *) +{ + if (!pImplName) + return nullptr; + + void * pRet = nullptr; + + Reference< XMultiServiceFactory > xSMgr( + static_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + // UUI Password Container Interaction Handler. + + if ( uui::PasswordContainerInteractionHandler::getImplementationName_Static(). + equalsAscii( pImplName ) ) + { + xFactory = + uui::PasswordContainerInteractionHandler::createServiceFactory( xSMgr ); + } + + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/sslwarndlg.cxx b/uui/source/sslwarndlg.cxx new file mode 100644 index 000000000..be57ea1b2 --- /dev/null +++ b/uui/source/sslwarndlg.cxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ + +#include "sslwarndlg.hxx" + +#include <com/sun/star/security/DocumentDigitalSignatures.hpp> + +using namespace css; + +IMPL_LINK_NOARG(SSLWarnDialog, ViewCertHdl, weld::Button&, void) +{ + uno::Reference< css::security::XDocumentDigitalSignatures > xDocumentDigitalSignatures + = css::security::DocumentDigitalSignatures::createDefault( m_xContext ); + xDocumentDigitalSignatures->setParentWindow(m_xDialog->GetXWindow()); + xDocumentDigitalSignatures->showCertificate(m_rXCert); +} + +SSLWarnDialog::SSLWarnDialog(weld::Window* pParent, + const css::uno::Reference< css::security::XCertificate >& rXCert, + const css::uno::Reference< css::uno::XComponentContext >& xContext) + : MessageDialogController(pParent, "uui/ui/sslwarndialog.ui", "SSLWarnDialog") + , m_xView(m_xBuilder->weld_button("view")) + , m_xContext(xContext) + , m_rXCert(rXCert) +{ + m_xView->connect_clicked(LINK(this, SSLWarnDialog, ViewCertHdl)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/sslwarndlg.hxx b/uui/source/sslwarndlg.hxx new file mode 100644 index 000000000..bd02b0041 --- /dev/null +++ b/uui/source/sslwarndlg.hxx @@ -0,0 +1,48 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_SSLWARNDLG_HXX +#define INCLUDED_UUI_SOURCE_SSLWARNDLG_HXX + +#include <vcl/weld.hxx> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + + +//= Https_WarnDialog + +class SSLWarnDialog : public weld::MessageDialogController +{ +private: + std::unique_ptr<weld::Button> m_xView; + const css::uno::Reference< css::uno::XComponentContext >& m_xContext; + const css::uno::Reference< css::security::XCertificate >& m_rXCert; + + DECL_LINK(ViewCertHdl, weld::Button&, void); + +public: + SSLWarnDialog(weld::Window* pParent, + const css::uno::Reference< css::security::XCertificate >& rXCert, + const css::uno::Reference< css::uno::XComponentContext >& xContext ); + + void setDescription1Text(const OUString &rText) { m_xDialog->set_primary_text(rText); } +}; + +#endif // INCLUDED_UUI_SOURCE_SSLWARNDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/trylater.cxx b/uui/source/trylater.cxx new file mode 100644 index 000000000..115061394 --- /dev/null +++ b/uui/source/trylater.cxx @@ -0,0 +1,49 @@ +/* -*- 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 . + */ + +#include <unotools/resmgr.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/svapp.hxx> +#include <strings.hrc> +#include "trylater.hxx" + +TryLaterQueryBox::TryLaterQueryBox(weld::Window* pParent, const std::locale& rResLocale, const OUString& rMessage, bool bEnableOverride) + : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, rMessage)) +{ + m_xQueryBox->set_title(Translate::get(STR_TRYLATER_TITLE, rResLocale)); + + // Currently we don't have the retry/save-as functionality implemented for cases when file is locked. + // So threat them mutually exclusive with overwrite here. TODO/LATER: just add the overwrite option + // as third option when retrying and saving with another name would be possible along with overwriting + if (bEnableOverride) + { + m_xQueryBox->add_button(Translate::get(STR_FILECHANGED_SAVEANYWAY_BTN, rResLocale), RET_IGNORE); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_IGNORE); + } + else + { + m_xQueryBox->add_button(Translate::get(STR_TRYLATER_RETRYSAVING_BTN, rResLocale), RET_YES); + m_xQueryBox->add_button(Translate::get(STR_TRYLATER_SAVEAS_BTN, rResLocale), RET_NO); + m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); + m_xQueryBox->set_default_response(RET_YES); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/trylater.hxx b/uui/source/trylater.hxx new file mode 100644 index 000000000..26b1d6714 --- /dev/null +++ b/uui/source/trylater.hxx @@ -0,0 +1,35 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_TRYLATER_HXX +#define INCLUDED_UUI_SOURCE_TRYLATER_HXX + +#include <vcl/weld.hxx> + +class TryLaterQueryBox +{ +private: + std::unique_ptr<weld::MessageDialog> m_xQueryBox; +public: + TryLaterQueryBox(weld::Window* pParent, const std::locale& rLocale, const OUString& aMessage, bool bEnableOverride); + short run() { return m_xQueryBox->run(); } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/unknownauthdlg.cxx b/uui/source/unknownauthdlg.cxx new file mode 100644 index 000000000..ca84be371 --- /dev/null +++ b/uui/source/unknownauthdlg.cxx @@ -0,0 +1,63 @@ +/* -*- 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 . + */ + +#include "unknownauthdlg.hxx" + +#include <com/sun/star/security/DocumentDigitalSignatures.hpp> + +using namespace css; + + +IMPL_LINK_NOARG(UnknownAuthDialog, OKHdl_Impl, weld::Button&, void) +{ + if (m_xOptionButtonAccept->get_active()) + { + m_xDialog->response(RET_OK); + } + else + { + m_xDialog->response(RET_CANCEL); + } +} + +IMPL_LINK_NOARG(UnknownAuthDialog, ViewCertHdl_Impl, weld::Button&, void) +{ + uno::Reference< css::security::XDocumentDigitalSignatures > xDocumentDigitalSignatures( + css::security::DocumentDigitalSignatures::createDefault(m_xContext) ); + xDocumentDigitalSignatures->setParentWindow(m_xDialog->GetXWindow()); + xDocumentDigitalSignatures->showCertificate(m_rXCert); +} + +UnknownAuthDialog::UnknownAuthDialog(weld::Window* pParent, + const css::uno::Reference< css::security::XCertificate >& rXCert, + const css::uno::Reference< css::uno::XComponentContext >& xContext) + : MessageDialogController(pParent, "uui/ui/unknownauthdialog.ui", + "UnknownAuthDialog") + , m_xCommandButtonOK(m_xBuilder->weld_button("ok")) + , m_xView_Certificate(m_xBuilder->weld_button("examine")) + , m_xOptionButtonAccept(m_xBuilder->weld_radio_button("accept")) + , m_xOptionButtonDontAccept(m_xBuilder->weld_radio_button("reject")) + , m_xContext(xContext) + , m_rXCert(rXCert) +{ + m_xView_Certificate->connect_clicked(LINK(this, UnknownAuthDialog, ViewCertHdl_Impl)); + m_xCommandButtonOK->connect_clicked(LINK(this, UnknownAuthDialog, OKHdl_Impl)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uui/source/unknownauthdlg.hxx b/uui/source/unknownauthdlg.hxx new file mode 100644 index 000000000..43e5b062e --- /dev/null +++ b/uui/source/unknownauthdlg.hxx @@ -0,0 +1,56 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_UUI_SOURCE_UNKNOWNAUTHDLG_HXX +#define INCLUDED_UUI_SOURCE_UNKNOWNAUTHDLG_HXX + +#include <vcl/weld.hxx> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + + +//= Https_UADialog + +class UnknownAuthDialog : public weld::MessageDialogController +{ +private: + std::unique_ptr<weld::Button> m_xCommandButtonOK; + std::unique_ptr<weld::Button> m_xView_Certificate; + std::unique_ptr<weld::RadioButton> m_xOptionButtonAccept; + std::unique_ptr<weld::RadioButton> m_xOptionButtonDontAccept; + + const css::uno::Reference< css::uno::XComponentContext >& m_xContext; + const css::uno::Reference< css::security::XCertificate >& m_rXCert; + + DECL_LINK(OKHdl_Impl, weld::Button&, void); + DECL_LINK(ViewCertHdl_Impl, weld::Button&, void); + +public: + UnknownAuthDialog(weld::Window* pParent, + const css::uno::Reference< css::security::XCertificate >& rXCert, + const css::uno::Reference< css::uno::XComponentContext >& xContext); + + void setDescriptionText(const OUString &rText) + { + m_xDialog->set_primary_text(rText); + } +}; + +#endif // INCLUDED_UUI_SOURCE_UNKNOWNAUTHDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |