1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <com/sun/star/task/InteractionHandler.hpp>
11 #include <com/sun/star/task/PasswordContainer.hpp>
12 #include <com/sun/star/task/XPasswordContainer2.hpp>
13 #include <com/sun/star/ucb/XContentAccess.hpp>
14 #include <com/sun/star/sdbc/XResultSet.hpp>
15 #include <com/sun/star/sdbc/XRow.hpp>
17 #include <comphelper/processfactory.hxx>
18 #include <o3tl/safeint.hxx>
19 #include <rtl/uri.hxx>
20 #include <ucbhelper/content.hxx>
21 #include <ucbhelper/commandenvironment.hxx>
22 #include <comphelper/diagnose_ex.hxx>
24 #include <svtools/PlaceEditDialog.hxx>
26 #include <config_oauth2.h>
28 #include "ServerDetailsControls.hxx"
30 using namespace com::sun::star::sdbc
;
31 using namespace com::sun::star::task
;
32 using namespace com::sun::star::ucb
;
33 using namespace com::sun::star::uno
;
35 DetailsContainer::DetailsContainer(PlaceEditDialog
* pDialog
)
38 m_pDialog
->m_xEDPort
->connect_output(LINK(this, DetailsContainer
, FormatPortHdl
));
41 //format without thousand separator
42 IMPL_STATIC_LINK(DetailsContainer
, FormatPortHdl
, weld::SpinButton
&, rSpinButton
, void)
44 rSpinButton
.set_text(OUString::number(rSpinButton
.get_value()));
47 DetailsContainer::~DetailsContainer( )
51 void DetailsContainer::set_visible( bool )
53 m_pDialog
->m_xDetailsGrid
->set_sensitive(true);
55 m_pDialog
->m_xEDHost
->connect_changed( LINK( this, DetailsContainer
, ValueChangeHdl
) );
56 m_pDialog
->m_xEDPort
->connect_changed( LINK( this, DetailsContainer
, ValueChangeHdl
) );
57 m_pDialog
->m_xEDRoot
->connect_changed( LINK( this, DetailsContainer
, ValueChangeHdl
) );
60 INetURLObject
DetailsContainer::getUrl( )
62 // Don't use that class directly: make it smarter by subclassing it.
63 return INetURLObject( );
66 bool DetailsContainer::setUrl( const INetURLObject
& )
68 // That class doesn't contain any logic... it defers the dirty work
69 // to the sub classes.
73 void DetailsContainer::notifyChange( )
75 m_aChangeHdl
.Call( this );
78 IMPL_LINK_NOARG( DetailsContainer
, ValueChangeHdl
, weld::Entry
&, void )
83 HostDetailsContainer::HostDetailsContainer(PlaceEditDialog
* pDialog
, sal_uInt16 nPort
, OUString sScheme
) :
84 DetailsContainer( pDialog
),
85 m_nDefaultPort( nPort
),
86 m_sScheme(std::move( sScheme
))
91 void HostDetailsContainer::set_visible( bool bShow
)
93 m_pDialog
->m_xFTHost
->set_visible( bShow
);
94 m_pDialog
->m_xHostBox
->set_visible( bShow
);
95 m_pDialog
->m_xEDRoot
->set_visible( bShow
);
96 m_pDialog
->m_xFTRoot
->set_visible( bShow
);
98 DetailsContainer::set_visible( bShow
);
102 if (m_pDialog
->m_xEDPort
->get_value() == 0)
103 m_pDialog
->m_xEDPort
->set_value( m_nDefaultPort
);
104 m_pDialog
->m_xEDHost
->set_text( m_sHost
);
107 m_pDialog
->m_xEDPort
->set_value( 0 );
110 INetURLObject
HostDetailsContainer::getUrl( )
112 OUString sHost
= m_pDialog
->m_xEDHost
->get_text().trim();
113 sal_Int64 nPort
= m_pDialog
->m_xEDPort
->get_value();
114 OUString sPath
= m_pDialog
->m_xEDRoot
->get_text().trim();
117 if ( !sHost
.isEmpty( ) )
119 sUrl
= m_sScheme
+ "://" + sHost
;
120 if ( nPort
!= m_nDefaultPort
)
121 sUrl
+= ":" + OUString::number( nPort
);
122 if ( !sPath
.isEmpty( ) )
123 if ( sPath
.indexOf( '/' ) != 0 )
128 return INetURLObject( sUrl
);
131 bool HostDetailsContainer::setUrl( const INetURLObject
& rUrl
)
133 bool bSuccess
= verifyScheme( INetURLObject::GetScheme( rUrl
.GetProtocol( ) ) );
137 m_sHost
= rUrl
.GetHost( );
138 m_pDialog
->m_xEDHost
->set_text( rUrl
.GetHost( ) );
139 m_pDialog
->m_xEDPort
->set_value( rUrl
.GetPort( ) );
140 m_pDialog
->m_xEDRoot
->set_text( rUrl
.GetURLPath() );
146 bool HostDetailsContainer::verifyScheme( const OUString
& sScheme
)
148 return sScheme
== Concat2View( m_sScheme
+ "://" );
151 DavDetailsContainer::DavDetailsContainer(PlaceEditDialog
* pBuilder
)
152 : HostDetailsContainer(pBuilder
, 80, u
"http"_ustr
)
154 m_pDialog
->m_xCBDavs
->connect_toggled(LINK(this, DavDetailsContainer
, ToggledDavsHdl
));
156 set_visible( false );
159 void DavDetailsContainer::set_visible( bool bShow
)
161 HostDetailsContainer::set_visible( bShow
);
164 m_pDialog
->m_xCBDavs
->set_active(false);
166 m_pDialog
->m_xCBDavs
->set_visible(bShow
);
169 bool DavDetailsContainer::verifyScheme( const OUString
& rScheme
)
172 if ( rScheme
== "http://" )
175 m_pDialog
->m_xCBDavs
->set_active(false);
176 ToggledDavsHdl(*m_pDialog
->m_xCBDavs
);
178 else if ( rScheme
== "https://" )
181 m_pDialog
->m_xCBDavs
->set_active(true);
182 ToggledDavsHdl(*m_pDialog
->m_xCBDavs
);
187 IMPL_LINK( DavDetailsContainer
, ToggledDavsHdl
, weld::Toggleable
&, rCheckBox
, void )
189 // Change default port if needed
190 bool bCheckedDavs
= rCheckBox
.get_active();
191 if ( m_pDialog
->m_xEDPort
->get_value() == 80 && bCheckedDavs
)
192 m_pDialog
->m_xEDPort
->set_value( 443 );
193 else if ( m_pDialog
->m_xEDPort
->get_value() == 443 && !bCheckedDavs
)
194 m_pDialog
->m_xEDPort
->set_value( 80 );
196 OUString
sScheme( u
"http"_ustr
);
199 setScheme( sScheme
);
204 SmbDetailsContainer::SmbDetailsContainer(PlaceEditDialog
* pDialog
)
205 : DetailsContainer(pDialog
)
207 m_pDialog
->m_xEDShare
->connect_changed( LINK( this, DetailsContainer
, ValueChangeHdl
) );
209 set_visible( false );
212 INetURLObject
SmbDetailsContainer::getUrl( )
214 OUString sHost
= m_pDialog
->m_xEDHost
->get_text().trim( );
215 OUString sShare
= m_pDialog
->m_xEDShare
->get_text().trim( );
216 OUString sPath
= m_pDialog
->m_xEDRoot
->get_text().trim( );
219 if ( !sHost
.isEmpty( ) )
221 sUrl
= "smb://" + sHost
+ "/";
222 if ( !sShare
.isEmpty( ) )
224 if ( !sPath
.isEmpty( ) )
225 if ( sPath
.indexOf( '/' ) != 0 )
230 return INetURLObject( sUrl
);
233 bool SmbDetailsContainer::setUrl( const INetURLObject
& rUrl
)
235 bool bSuccess
= rUrl
.GetProtocol() == INetProtocol::Smb
;
239 OUString sShare
= rUrl
.getName( 0 );
240 OUString sFullPath
= rUrl
.GetURLPath( );
242 if ( sFullPath
.getLength( ) > sShare
.getLength( ) )
244 sal_Int32 nPos
= sShare
.getLength( );
247 sPath
= sFullPath
.copy( nPos
);
250 m_sHost
= rUrl
.GetHost( );
251 m_pDialog
->m_xEDHost
->set_text( m_sHost
);
252 m_pDialog
->m_xEDShare
->set_text( sShare
);
253 m_pDialog
->m_xEDRoot
->set_text( sPath
);
259 void SmbDetailsContainer::set_visible( bool bShow
)
261 m_pDialog
->m_xEDShare
->set_visible( bShow
);
262 m_pDialog
->m_xFTShare
->set_visible( bShow
);
263 m_pDialog
->m_xEDRoot
->set_visible( bShow
);
264 m_pDialog
->m_xFTRoot
->set_visible( bShow
);
266 m_pDialog
->m_xFTHost
->set_visible( bShow
);
267 m_pDialog
->m_xHostBox
->set_visible( bShow
);
268 m_pDialog
->m_xEDPort
->set_sensitive( !bShow
);
269 m_pDialog
->m_xFTPort
->set_sensitive( !bShow
);
272 m_pDialog
->m_xEDHost
->set_text( m_sHost
);
275 CmisDetailsContainer::CmisDetailsContainer(PlaceEditDialog
* pParentDialog
, OUString sBinding
) :
276 DetailsContainer( pParentDialog
),
281 m_sBinding(std::move( sBinding
)),
282 m_xParentDialog(pParentDialog
->getDialog()->GetXWindow())
284 const Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
285 Reference
< XInteractionHandler
> xGlobalInteractionHandler
=
286 InteractionHandler::createWithParent(xContext
, m_xParentDialog
);
287 m_xCmdEnv
= new ucbhelper::CommandEnvironment( xGlobalInteractionHandler
, Reference
< XProgressHandler
>() );
289 set_visible( false );
292 void CmisDetailsContainer::set_visible( bool bShow
)
294 m_pDialog
->m_xLBRepository
->connect_changed( LINK( this, CmisDetailsContainer
, SelectRepoHdl
) );
295 m_pDialog
->m_xBTRepoRefresh
->connect_clicked( LINK( this, CmisDetailsContainer
, RefreshReposHdl
) );
297 m_pDialog
->m_xEDHost
->set_text( m_sBinding
);
299 if( ( m_sBinding
== GDRIVE_BASE_URL
)
300 || m_sBinding
.startsWith( ALFRESCO_CLOUD_BASE_URL
)
301 || ( m_sBinding
== ONEDRIVE_BASE_URL
) )
303 m_pDialog
->m_xFTHost
->hide();
304 m_pDialog
->m_xHostBox
->hide();
305 m_pDialog
->m_xFTRepository
->hide();
306 m_pDialog
->m_xRepositoryBox
->hide();
307 m_pDialog
->m_xEDRoot
->hide();
308 m_pDialog
->m_xFTRoot
->hide();
312 m_pDialog
->m_xFTHost
->set_visible( bShow
);
313 m_pDialog
->m_xHostBox
->set_visible( bShow
);
314 m_pDialog
->m_xFTRepository
->set_visible( bShow
);
315 m_pDialog
->m_xRepositoryBox
->set_visible( bShow
);
316 m_pDialog
->m_xEDRoot
->set_visible( bShow
);
317 m_pDialog
->m_xFTRoot
->set_visible( bShow
);
320 DetailsContainer::set_visible( bShow
);
321 m_pDialog
->m_xEDPort
->set_sensitive( !bShow
);
322 m_pDialog
->m_xFTPort
->set_sensitive( !bShow
);
325 INetURLObject
CmisDetailsContainer::getUrl( )
327 OUString sBindingUrl
= m_pDialog
->m_xEDHost
->get_text().trim();
328 OUString sPath
= m_pDialog
->m_xEDRoot
->get_text().trim();
331 if( ( m_sBinding
== GDRIVE_BASE_URL
)
332 || m_sBinding
.startsWith( ALFRESCO_CLOUD_BASE_URL
)
333 || ( m_sBinding
== ONEDRIVE_BASE_URL
) )
335 bSkip
= m_sUsername
.isEmpty();
339 bSkip
= m_sRepoId
.isEmpty();
343 if ( !sBindingUrl
.isEmpty( ) && !bSkip
)
345 OUString sEncodedBinding
= rtl::Uri::encode(
346 sBindingUrl
+ "#" + m_sRepoId
,
347 rtl_UriCharClassRelSegment
,
348 rtl_UriEncodeKeepEscapes
,
349 RTL_TEXTENCODING_UTF8
);
350 sUrl
= "vnd.libreoffice.cmis://" + sEncodedBinding
;
354 return INetURLObject( sUrl
);
357 bool CmisDetailsContainer::setUrl( const INetURLObject
& rUrl
)
359 bool bSuccess
= rUrl
.GetProtocol() == INetProtocol::Cmis
;
363 OUString sDecodedHost
= rUrl
.GetHost( INetURLObject::DecodeMechanism::WithCharset
);
364 INetURLObject
aHostUrl( sDecodedHost
);
365 m_sBinding
= aHostUrl
.GetURLNoMark( );
366 m_sRepoId
= aHostUrl
.GetMark( );
368 m_pDialog
->m_xEDHost
->set_text( m_sBinding
);
369 m_pDialog
->m_xEDRoot
->set_text( rUrl
.GetURLPath() );
374 void CmisDetailsContainer::setUsername( const OUString
& rUsername
)
376 m_sUsername
= rUsername
;
379 void CmisDetailsContainer::setPassword( const OUString
& rPass
)
384 void CmisDetailsContainer::selectRepository( )
386 // Get the repo ID and call the Change listener
387 const int nPos
= m_pDialog
->m_xLBRepository
->get_active();
388 if( o3tl::make_unsigned(nPos
) < m_aRepoIds
.size() )
390 m_sRepoId
= m_aRepoIds
[nPos
];
395 IMPL_LINK_NOARG( CmisDetailsContainer
, RefreshReposHdl
, weld::Button
&, void )
397 const Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
398 Reference
< XPasswordContainer2
> xMasterPasswd
= PasswordContainer::create( xContext
);
401 OUString sBindingUrl
= m_pDialog
->m_xEDHost
->get_text().trim( );
403 OUString sEncodedUsername
= u
""_ustr
;
405 if ( !m_sUsername
.isEmpty( ) )
407 sEncodedUsername
= rtl::Uri::encode(m_sUsername
,
408 rtl_UriCharClassUserinfo
,
409 rtl_UriEncodeKeepEscapes
,
410 RTL_TEXTENCODING_UTF8
)
415 m_pDialog
->m_xLBRepository
->clear();
420 if ( !sBindingUrl
.isEmpty( ) )
422 OUString sEncodedBinding
= rtl::Uri::encode(
424 rtl_UriCharClassRelSegment
,
425 rtl_UriEncodeKeepEscapes
,
426 RTL_TEXTENCODING_UTF8
);
427 sUrl
= "vnd.libreoffice.cmis://" + sEncodedUsername
+ sEncodedBinding
;
430 // temporary remember the password
433 if( !sUrl
.isEmpty() && !m_sUsername
.isEmpty() && !m_sPassword
.isEmpty() )
435 Reference
< XInteractionHandler
> xInteractionHandler
=
436 InteractionHandler::createWithParent(xContext
, m_xParentDialog
);
438 Sequence
<OUString
> aPasswd
{ m_sPassword
};
441 sUrl
, m_sUsername
, aPasswd
, xInteractionHandler
);
444 catch( const Exception
& )
450 ::ucbhelper::Content
aCnt( sUrl
, m_xCmdEnv
, comphelper::getProcessComponentContext() );
451 Sequence
<OUString
> aProps
{ u
"Title"_ustr
};
452 Reference
< XResultSet
> xResultSet( aCnt
.createCursor( aProps
), UNO_SET_THROW
);
453 Reference
< XContentAccess
> xAccess( xResultSet
, UNO_QUERY_THROW
);
454 while ( xResultSet
->next() )
456 OUString sURL
= xAccess
->queryContentIdentifierString( );
457 INetURLObject
aURL( sURL
);
458 OUString sId
= aURL
.GetURLPath( INetURLObject::DecodeMechanism::WithCharset
);
460 m_aRepoIds
.push_back( sId
);
462 Reference
< XRow
> xRow( xResultSet
, UNO_QUERY
);
463 OUString sName
= xRow
->getString( 1 );
464 m_pDialog
->m_xLBRepository
->append_text(sName
);
467 catch ( const Exception
&)
469 TOOLS_WARN_EXCEPTION( "svtools.dialogs", "RefreshReposHdl" );
472 // Auto-select the first one
473 if (m_pDialog
->m_xLBRepository
->get_count() > 0)
475 m_pDialog
->m_xLBRepository
->set_active(0);
479 // remove temporary password
482 xMasterPasswd
->remove( sUrl
, m_sUsername
);
484 catch( const Exception
& )
488 IMPL_LINK_NOARG( CmisDetailsContainer
, SelectRepoHdl
, weld::ComboBox
&, void )
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */