rhbz#1691287 tdf#53029 ui prompt for printer authentication

refactor and reuse existing dialog to add potential domain entry

Change-Id: Ib884931f8ccc62aad9b3e92ecf93d1da7ffe607b
Reviewed-on: https://gerrit.libreoffice.org/69739
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/vcl/inc/printerinfomanager.hxx b/vcl/inc/printerinfomanager.hxx
index 95aebae..825e1c1 100644
--- a/vcl/inc/printerinfomanager.hxx
+++ b/vcl/inc/printerinfomanager.hxx
@@ -53,6 +53,8 @@
    // a list of special features separated by ',' not used by psprint
    // but assigned from the outside (currently for "fax","pdf=","autoqueue","external_dialog")
    OUString             m_aFeatures;
    // auth-info-required, potential [domain],[username],[password] to prompt for to authenticate printing
    OUString             m_aAuthInfoRequired;
    PrinterSetupMode     meSetupMode;

    PrinterInfo()
diff --git a/vcl/uiconfig/ui/cupspassworddialog.ui b/vcl/uiconfig/ui/cupspassworddialog.ui
index 9b37d3e..0bae757 100644
--- a/vcl/uiconfig/ui/cupspassworddialog.ui
+++ b/vcl/uiconfig/ui/cupspassworddialog.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<!-- Generated with glade 3.22.1 -->
<interface domain="vcl">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkDialog" id="CUPSPasswordDialog">
@@ -10,6 +10,9 @@
    <property name="default_width">0</property>
    <property name="default_height">0</property>
    <property name="type_hint">normal</property>
    <child>
      <placeholder/>
    </child>
    <child internal-child="vbox">
      <object class="GtkBox" id="dialog-vbox1">
        <property name="can_focus">False</property>
@@ -76,7 +79,7 @@
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
@@ -90,7 +93,7 @@
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">2</property>
                <property name="top_attach">3</property>
              </packing>
            </child>
            <child>
@@ -118,7 +121,7 @@
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
@@ -128,10 +131,37 @@
                <property name="hexpand">True</property>
                <property name="visibility">False</property>
                <property name="activates_default">True</property>
                <property name="input_purpose">password</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">2</property>
                <property name="top_attach">3</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label3">
                <property name="can_focus">False</property>
                <property name="no_show_all">True</property>
                <property name="label" translatable="yes" context="cupspassworddialog|label1">_Domain:</property>
                <property name="use_underline">True</property>
                <property name="mnemonic_widget">domain</property>
                <property name="xalign">1</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="domain">
                <property name="can_focus">True</property>
                <property name="no_show_all">True</property>
                <property name="hexpand">True</property>
                <property name="activates_default">True</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
          </object>
@@ -147,8 +177,5 @@
      <action-widget response="-5">ok</action-widget>
      <action-widget response="-6">cancel</action-widget>
    </action-widgets>
    <child>
      <placeholder/>
    </child>
  </object>
</interface>
diff --git a/vcl/unx/generic/printer/cupsmgr.cxx b/vcl/unx/generic/printer/cupsmgr.cxx
index 7535e64..5609c3c 100644
--- a/vcl/unx/generic/printer/cupsmgr.cxx
+++ b/vcl/unx/generic/printer/cupsmgr.cxx
@@ -334,6 +334,8 @@
                aPrinter.m_aInfo.m_aComment=OStringToOUString(pDest->options[k].value, aEncoding);
            if(!strcmp(pDest->options[k].name, "printer-location"))
                aPrinter.m_aInfo.m_aLocation=OStringToOUString(pDest->options[k].value, aEncoding);
            if(!strcmp(pDest->options[k].name, "auth-info-required"))
                aPrinter.m_aInfo.m_aAuthInfoRequired=OStringToOUString(pDest->options[k].value, aEncoding);
        }

        OUStringBuffer aBuf( 256 );
@@ -653,6 +655,88 @@
    }
}

namespace
{
    class RTSPWDialog : public weld::GenericDialogController
    {
        std::unique_ptr<weld::Label> m_xText;
        std::unique_ptr<weld::Label> m_xDomainLabel;
        std::unique_ptr<weld::Entry> m_xDomainEdit;
        std::unique_ptr<weld::Label> m_xUserLabel;
        std::unique_ptr<weld::Entry> m_xUserEdit;
        std::unique_ptr<weld::Label> m_xPassLabel;
        std::unique_ptr<weld::Entry> m_xPassEdit;

    public:
        RTSPWDialog(weld::Window* pParent, const OString& rServer, const OString& rUserName);

        OString getDomain() const
        {
            return OUStringToOString( m_xDomainEdit->get_text(), osl_getThreadTextEncoding() );
        }

        OString getUserName() const
        {
            return OUStringToOString( m_xUserEdit->get_text(), osl_getThreadTextEncoding() );
        }

        OString getPassword() const
        {
            return OUStringToOString( m_xPassEdit->get_text(), osl_getThreadTextEncoding() );
        }

        void SetDomainVisible(bool bShow)
        {
            m_xDomainLabel->set_visible(bShow);
            m_xDomainEdit->set_visible(bShow);
        }

        void SetUserVisible(bool bShow)
        {
            m_xUserLabel->set_visible(bShow);
            m_xUserEdit->set_visible(bShow);
        }

        void SetPassVisible(bool bShow)
        {
            m_xPassLabel->set_visible(bShow);
            m_xPassEdit->set_visible(bShow);
        }
    };

    RTSPWDialog::RTSPWDialog(weld::Window* pParent, const OString& rServer, const OString& rUserName)
        : GenericDialogController(pParent, "vcl/ui/cupspassworddialog.ui", "CUPSPasswordDialog")
        , m_xText(m_xBuilder->weld_label("text"))
        , m_xDomainLabel(m_xBuilder->weld_label("label3"))
        , m_xDomainEdit(m_xBuilder->weld_entry("domain"))
        , m_xUserLabel(m_xBuilder->weld_label("label1"))
        , m_xUserEdit(m_xBuilder->weld_entry("user"))
        , m_xPassLabel(m_xBuilder->weld_label("label2"))
        , m_xPassEdit(m_xBuilder->weld_entry("pass"))
    {
        OUString aText(m_xText->get_label());
        aText = aText.replaceFirst("%s", OStringToOUString(rServer, osl_getThreadTextEncoding()));
        m_xText->set_label(aText);
        m_xUserEdit->set_text(OStringToOUString(rUserName, osl_getThreadTextEncoding()));
    }

    bool AuthenticateQuery(const OString& rServer, OString& rUserName, OString& rPassword)
    {
        bool bRet = false;

        vcl::Window* pWin = Application::GetDefDialogParent();
        RTSPWDialog aDialog(pWin ? pWin->GetFrameWeld() : nullptr, rServer, rUserName);
        if (aDialog.run() == RET_OK)
        {
            rUserName = aDialog.getUserName();
            rPassword = aDialog.getPassword();
            bRet = true;
        }

        return bRet;
    }
}

bool CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner, const OUString& rFaxNumber )
{
    SAL_INFO( "vcl.unx.print", "endSpool: " << rPrintername << "," << rJobTitle << " copy count = " << rDocumentJobData.m_nCopies );
@@ -678,7 +762,56 @@
        // setup cups options
        int nNumOptions = 0;
        cups_option_t* pOptions = nullptr;
        getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, reinterpret_cast<void**>(&pOptions) );
        auto ppOptions = reinterpret_cast<void**>(&pOptions);
        getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, ppOptions );

        PrinterInfo aInfo(getPrinterInfo(rPrintername));
        if (!aInfo.m_aAuthInfoRequired.isEmpty())
        {
            bool bDomain(false), bUser(false), bPass(false);
            sal_Int32 nIndex = 0;
            do
            {
                OUString aToken = aInfo.m_aAuthInfoRequired.getToken(0, ',', nIndex);
                if (aToken == "domain")
                    bDomain = true;
                else if (aToken == "username")
                    bUser = true;
                else if (aToken == "password")
                    bPass = true;
            }
            while (nIndex >= 0);

            if (bDomain || bUser || bPass)
            {
                OString sPrinterName(OUStringToOString(rPrintername, RTL_TEXTENCODING_UTF8));
                vcl::Window* pWin = Application::GetDefDialogParent();
                RTSPWDialog aDialog(pWin ? pWin->GetFrameWeld() : nullptr, sPrinterName, "");
                aDialog.SetDomainVisible(bDomain);
                aDialog.SetUserVisible(bUser);
                aDialog.SetPassVisible(bPass);

                if (aDialog.run() == RET_OK)
                {
                    OString sAuth;
                    if (bDomain)
                        sAuth = aDialog.getDomain().replaceAll(",", "\\,");
                    if (bUser)
                    {
                        if (!sAuth.isEmpty())
                            sAuth += ",";
                        sAuth += aDialog.getUserName().replaceAll(",", "\\,");
                    }
                    if (bPass)
                    {
                        if (!sAuth.isEmpty())
                            sAuth += ",";
                        sAuth += aDialog.getPassword().replaceAll(",", "\\,");
                    }
                    nNumOptions = cupsAddOption("auth-info", sAuth.getStr(), nNumOptions, &pOptions);
                }
            }
        }

        OString sJobName(OUStringToOString(rJobTitle, aEnc));

@@ -768,59 +901,6 @@
    return bChanged;
}

namespace
{
    class RTSPWDialog : public weld::GenericDialogController
    {
        std::unique_ptr<weld::Label> m_xText;
        std::unique_ptr<weld::Entry> m_xUserEdit;
        std::unique_ptr<weld::Entry> m_xPassEdit;

    public:
        RTSPWDialog(const OString& rServer, const OString& rUserName, weld::Window* pParent);
        OString getUserName() const;
        OString getPassword() const;
    };

    RTSPWDialog::RTSPWDialog( const OString& rServer, const OString& rUserName, weld::Window* pParent )
        : GenericDialogController(pParent, "vcl/ui/cupspassworddialog.ui", "CUPSPasswordDialog")
        , m_xText(m_xBuilder->weld_label("text"))
        , m_xUserEdit(m_xBuilder->weld_entry("user"))
        , m_xPassEdit(m_xBuilder->weld_entry("pass"))
    {
        OUString aText(m_xText->get_label());
        aText = aText.replaceFirst("%s", OStringToOUString(rServer, osl_getThreadTextEncoding()));
        m_xText->set_label(aText);
        m_xUserEdit->set_text(OStringToOUString(rUserName, osl_getThreadTextEncoding()));
    }

    OString RTSPWDialog::getUserName() const
    {
        return OUStringToOString( m_xUserEdit->get_text(), osl_getThreadTextEncoding() );
    }

    OString RTSPWDialog::getPassword() const
    {
        return OUStringToOString( m_xPassEdit->get_text(), osl_getThreadTextEncoding() );
    }

    bool AuthenticateQuery(const OString& rServer, OString& rUserName, OString& rPassword)
    {
        bool bRet = false;

        vcl::Window* pWin = Application::GetDefDialogParent();
        RTSPWDialog aDialog(rServer, rUserName, pWin ? pWin->GetFrameWeld() : nullptr);
        if (aDialog.run() == RET_OK)
        {
            rUserName = aDialog.getUserName();
            rPassword = aDialog.getPassword();
            bRet = true;
        }

        return bRet;
    }
}

const char* CUPSManager::authenticateUser()
{
    const char* pRet = nullptr;