ucbhelper,ucb,desktop: InternetProxyServer is problematic
It turns out that every single client of InternetProxyDecider simply concatenates the 2 members of InternetProxyServer into a single string and passes it on to curl_easy_setopt(CURLOPT_PROXY), which will happily take a URL including scheme and everything. It turns out that the awful GetUnixSystemProxy() tries to cut off the scheme in a terrible way, but GetPACProxy() does no such thing and WINHTTP_PROXY_INFO::lpszProxy may or may not contain scheme in its entries; fix this to only separate the port and leave the rest alone. So why do we need a InternetProxyServer struct? Because officecfg has separate entries that correspond to its members, and so InternetProxyDecider gets separate events on its listener interface when any of them changes, which is easiest to handle if it stores these separately. So just return a concatenated URL with or without scheme in getProxy(). Change-Id: I43c696471c8bec90667b5930fa00975adb432fe1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155840 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
committed by
Noel Grandin
parent
9b30b4b167
commit
f88af95552
@@ -139,7 +139,7 @@ void CrashReporter::writeCommonInfo()
|
||||
static constexpr OUStringLiteral url = u"crashreport.libreoffice.org";
|
||||
const sal_Int32 port = 443;
|
||||
|
||||
const ucbhelper::InternetProxyServer proxy_server = proxy_decider.getProxy(protocol, url, port);
|
||||
const OUString proxy_server = proxy_decider.getProxy(protocol, url, port);
|
||||
|
||||
// save the new Keys
|
||||
vmaKeyValues atlast = maKeyValues;
|
||||
@@ -152,9 +152,9 @@ void CrashReporter::writeCommonInfo()
|
||||
addKeyValue("BuildID", utl::Bootstrap::getBuildIdData(""), AddItem);
|
||||
addKeyValue("URL", protocol + "://" + url + "/submit/", AddItem);
|
||||
|
||||
if (!proxy_server.aName.isEmpty())
|
||||
if (!proxy_server.isEmpty())
|
||||
{
|
||||
addKeyValue("Proxy", proxy_server.aName + ":" + OUString::number(proxy_server.nPort), AddItem);
|
||||
addKeyValue("Proxy", proxy_server, AddItem);
|
||||
}
|
||||
|
||||
// write the new keys at the end
|
||||
|
@@ -116,10 +116,10 @@ public:
|
||||
* If host is not empty this parameter must always contain a valid
|
||||
* port number, for instance the default port for the requested
|
||||
* protocol(i.e. 80 or http).
|
||||
* @return a InternetProxyServer struct. If member aName of the
|
||||
* InternetProxyServer is empty no proxy server is to be used.
|
||||
* @return an URL, with or without scheme.
|
||||
* If empty no proxy server is to be used.
|
||||
*/
|
||||
InternetProxyServer
|
||||
OUString
|
||||
getProxy( const OUString & rProtocol,
|
||||
const OUString & rHost,
|
||||
sal_Int32 nPort ) const;
|
||||
|
@@ -304,11 +304,8 @@ namespace cmis
|
||||
// Set the proxy if needed. We are doing that all times as the proxy data shouldn't be cached.
|
||||
ucbhelper::InternetProxyDecider aProxyDecider( m_xContext );
|
||||
INetURLObject aBindingUrl( m_aURL.getBindingUrl( ) );
|
||||
const ucbhelper::InternetProxyServer& rProxy = aProxyDecider.getProxy(
|
||||
const OUString sProxy = aProxyDecider.getProxy(
|
||||
INetURLObject::GetScheme( aBindingUrl.GetProtocol( ) ), aBindingUrl.GetHost(), aBindingUrl.GetPort() );
|
||||
OUString sProxy = rProxy.aName;
|
||||
if ( rProxy.nPort > 0 )
|
||||
sProxy += ":" + OUString::number( rProxy.nPort );
|
||||
libcmis::SessionFactory::setProxySettings( OUSTR_TO_STDSTR( sProxy ), std::string(), std::string(), std::string() );
|
||||
|
||||
// Look for a cached session, key is binding url + repo id
|
||||
|
@@ -134,11 +134,8 @@ namespace cmis
|
||||
// Set the proxy if needed. We are doing that all times as the proxy data shouldn't be cached.
|
||||
ucbhelper::InternetProxyDecider aProxyDecider( m_xContext );
|
||||
INetURLObject aBindingUrl( m_aURL.getBindingUrl( ) );
|
||||
const ucbhelper::InternetProxyServer& rProxy = aProxyDecider.getProxy(
|
||||
const OUString sProxy = aProxyDecider.getProxy(
|
||||
INetURLObject::GetScheme( aBindingUrl.GetProtocol( ) ), aBindingUrl.GetHost(), aBindingUrl.GetPort() );
|
||||
OUString sProxy = rProxy.aName;
|
||||
if ( rProxy.nPort > 0 )
|
||||
sProxy += ":" + OUString::number( rProxy.nPort );
|
||||
libcmis::SessionFactory::setProxySettings( OUSTR_TO_STDSTR( sProxy ), std::string(), std::string(), std::string() );
|
||||
|
||||
if ( !m_aRepositories.empty() )
|
||||
|
@@ -693,18 +693,15 @@ CurlSession::CurlSession(uno::Reference<uno::XComponentContext> xContext,
|
||||
rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||
assert(rc == CURLE_OK); // ANY is always available
|
||||
// always set CURLOPT_PROXY to suppress proxy detection in libcurl
|
||||
OString const utf8Proxy(OUStringToOString(m_Proxy.aName, RTL_TEXTENCODING_UTF8));
|
||||
OString const utf8Proxy(OUStringToOString(m_Proxy, RTL_TEXTENCODING_UTF8));
|
||||
rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_PROXY, utf8Proxy.getStr());
|
||||
if (rc != CURLE_OK)
|
||||
{
|
||||
SAL_WARN("ucb.ucp.webdav.curl", "CURLOPT_PROXY failed: " << GetErrorString(rc));
|
||||
throw DAVException(DAVException::DAV_SESSION_CREATE,
|
||||
ConnectionEndPointString(m_Proxy.aName, m_Proxy.nPort));
|
||||
throw DAVException(DAVException::DAV_SESSION_CREATE, m_Proxy);
|
||||
}
|
||||
if (!m_Proxy.aName.isEmpty())
|
||||
if (!m_Proxy.isEmpty())
|
||||
{
|
||||
rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_PROXYPORT, static_cast<long>(m_Proxy.nPort));
|
||||
assert(rc == CURLE_OK);
|
||||
// set this initially, may be overwritten during authentication
|
||||
rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
||||
assert(rc == CURLE_OK); // ANY is always available
|
||||
@@ -749,7 +746,7 @@ auto CurlSession::CanUse(OUString const& rURI, uno::Sequence<beans::NamedValue>
|
||||
auto CurlSession::UsesProxy() -> bool
|
||||
{
|
||||
assert(m_URI.GetScheme() == "http" || m_URI.GetScheme() == "https");
|
||||
return !m_Proxy.aName.isEmpty();
|
||||
return !m_Proxy.isEmpty();
|
||||
}
|
||||
|
||||
auto CurlSession::abort() -> void
|
||||
@@ -967,9 +964,7 @@ auto CurlProcessor::ProcessRequestImpl(
|
||||
case CURLE_UNSUPPORTED_PROTOCOL:
|
||||
throw DAVException(DAVException::DAV_UNSUPPORTED);
|
||||
case CURLE_COULDNT_RESOLVE_PROXY:
|
||||
throw DAVException(
|
||||
DAVException::DAV_HTTP_LOOKUP,
|
||||
ConnectionEndPointString(rSession.m_Proxy.aName, rSession.m_Proxy.nPort));
|
||||
throw DAVException(DAVException::DAV_HTTP_LOOKUP, rSession.m_Proxy);
|
||||
case CURLE_COULDNT_RESOLVE_HOST:
|
||||
throw DAVException(
|
||||
DAVException::DAV_HTTP_LOOKUP,
|
||||
@@ -1214,12 +1209,12 @@ auto CurlProcessor::ProcessRequest(
|
||||
};
|
||||
::std::optional<Auth> oAuth;
|
||||
::std::optional<Auth> oAuthProxy;
|
||||
if (pEnv && !rSession.m_isAuthenticatedProxy && !rSession.m_Proxy.aName.isEmpty())
|
||||
if (pEnv && !rSession.m_isAuthenticatedProxy && !rSession.m_Proxy.isEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
// the hope is that this must be a URI
|
||||
CurlUri const uri(rSession.m_Proxy.aName);
|
||||
CurlUri const uri(rSession.m_Proxy);
|
||||
if (!uri.GetUser().isEmpty() || !uri.GetPassword().isEmpty())
|
||||
{
|
||||
oAuthProxy.emplace(uri.GetUser(), uri.GetPassword(), CURLAUTH_ANY);
|
||||
@@ -1452,7 +1447,7 @@ auto CurlProcessor::ProcessRequest(
|
||||
auto const ret = pEnv->m_xAuthListener->authenticate(
|
||||
oRealm ? *oRealm : "",
|
||||
statusCode == SC_UNAUTHORIZED ? rSession.m_URI.GetHost()
|
||||
: rSession.m_Proxy.aName,
|
||||
: rSession.m_Proxy,
|
||||
userName, passWord, isSystemCredSupported);
|
||||
|
||||
if (ret == 0)
|
||||
|
@@ -31,8 +31,8 @@ private:
|
||||
CurlUri const m_URI;
|
||||
/// buffer for libcurl detailed error messages
|
||||
char m_ErrorBuffer[CURL_ERROR_SIZE];
|
||||
/// proxy is used if aName is non-empty
|
||||
::ucbhelper::InternetProxyServer const m_Proxy;
|
||||
/// proxy is used if non-empty
|
||||
OUString const m_Proxy;
|
||||
/// once authentication was successful, rely on m_pCurl's data
|
||||
bool m_isAuthenticated = false;
|
||||
bool m_isAuthenticatedProxy = false;
|
||||
|
@@ -585,8 +585,9 @@ InternetProxyServer GetUnixSystemProxy(const OUString & rProtocol)
|
||||
OUString tmp = OUString::createFromAscii(pEnvProxy);
|
||||
if (tmp.getLength() < (rProtocol.getLength() + 3))
|
||||
return aProxy;
|
||||
tmp = tmp.copy(rProtocol.getLength() + 3);
|
||||
sal_Int32 x = tmp.indexOf(':');
|
||||
sal_Int32 x = tmp.indexOf("://");
|
||||
sal_Int32 at = tmp.indexOf('@', x == -1 ? 0 : x + 3);
|
||||
x = tmp.indexOf(':', at == -1 ? x == -1 ? 0 : x + 3 : at + 1);
|
||||
if (x == -1)
|
||||
return aProxy;
|
||||
int nPort = o3tl::toInt32(tmp.subView(x + 1));
|
||||
@@ -937,13 +938,19 @@ bool InternetProxyDecider::shouldUseProxy( const OUString & rProtocol,
|
||||
return !rData.aName.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
InternetProxyServer InternetProxyDecider::getProxy(
|
||||
OUString InternetProxyDecider::getProxy(
|
||||
const OUString & rProtocol,
|
||||
const OUString & rHost,
|
||||
sal_Int32 nPort ) const
|
||||
{
|
||||
return m_xImpl->getProxy( rProtocol, rHost, nPort );
|
||||
InternetProxyServer ret(m_xImpl->getProxy(rProtocol, rHost, nPort));
|
||||
|
||||
if (ret.aName.isEmpty() || ret.nPort == -1)
|
||||
{
|
||||
return ret.aName;
|
||||
}
|
||||
|
||||
return ret.aName + ":" + OUString::number(ret.nPort);
|
||||
}
|
||||
|
||||
} // namespace ucbhelper
|
||||
|
Reference in New Issue
Block a user