libzypp 17.38.5

proxyinfolibproxy.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include <zypp-core/AutoDispose.h>
14#include <iostream>
15#include <optional>
16#include <cstdlib>
17
18#include <zypp-core/base/Logger.h>
19#include <zypp-core/base/String.h>
20#include <zypp-core/fs/WatchFile>
21#include <zypp-core/Pathname.h>
22#include <zypp-core/base/Env.h>
23
24#include <zypp-curl/proxyinfo/ProxyInfoLibproxy>
25
26#include <dlfcn.h> // for dlload, dlsym, dlclose
27#include <glib.h> // g_clear_pointer and g_strfreev
28
29 using std::endl;
30 using namespace zypp::base;
31
32 namespace zypp {
33 namespace env {
34 inline bool inYAST()
35 {
36 static const bool _inYAST { static_cast<bool>(::getenv("YAST_IS_RUNNING")) };
37 return _inYAST;
38 }
39
40 inline bool PX_DEBUG()
41 {
42 static const bool _pxdebug { env::getenvBool("PX_DEBUG") };
43 return _pxdebug;
44 }
45 }
46
47 namespace media {
48
49 namespace {
50
51 using CreateFactoryCb = CreateFactorySig<pxProxyFactoryType>;
52 using DelFactoryCb = DelFactorySig<pxProxyFactoryType>;
53 using GetProxiesCb = GetProxiesSig<pxProxyFactoryType>;
54
55 struct LibProxyAPI
56 {
57 zypp::AutoDispose<void *> libProxyLibHandle;
58 CreateFactoryCb createProxyFactory = nullptr;
59 DelFactoryCb deleteProxyFactory = nullptr;
60 GetProxiesCb getProxies = nullptr;
61 FreeProxiesCb freeProxies = nullptr;
62
68 static void fallbackFreeProxies( char **proxies ) {
69 g_clear_pointer (&proxies, g_strfreev);
70 }
71
72 static std::unique_ptr<LibProxyAPI> create() {
73 MIL << "Detecting libproxy availability" << std::endl;
74 zypp::AutoDispose<void *> handle( dlopen("libproxy.so.1", RTLD_LAZY ), []( void *ptr ){ if ( ptr ) ::dlclose(ptr); });
75 if ( !handle ) {
76 MIL << "No libproxy support detected (could not load library): " << dlerror() << std::endl;
77 return nullptr;
78 }
79
80 std::unique_ptr<LibProxyAPI> apiInstance = std::make_unique<LibProxyAPI>();
81 apiInstance->libProxyLibHandle = std::move(handle);
82 apiInstance->createProxyFactory = (CreateFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_new" );
83 if ( !apiInstance->createProxyFactory ){
84 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_new): " << dlerror() << std::endl;
85 return nullptr;
86 }
87 apiInstance->deleteProxyFactory = (DelFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free" );
88 if ( !apiInstance->deleteProxyFactory ){
89 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_free): " << dlerror() << std::endl;
90 return nullptr;
91 }
92 apiInstance->getProxies = (GetProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_get_proxies" );
93 if ( !apiInstance->getProxies ){
94 ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_get_proxies): " << dlerror() << std::endl;
95 return nullptr;
96 }
97 apiInstance->freeProxies = (FreeProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free_proxies" );
98 if ( !apiInstance->freeProxies ){
99 MIL << "Older version of libproxy detected, using fallback function to free the proxy list (could not resolve px_proxy_factory_free_proxies): " << dlerror() << std::endl;
100 apiInstance->freeProxies = &fallbackFreeProxies;
101 }
102
103 MIL << "Libproxy is available" << std::endl;
104 return apiInstance;
105 }
106 };
107
108 LibProxyAPI *proxyApi() {
109 static std::unique_ptr<LibProxyAPI> api = LibProxyAPI::create();
110 return api.get();
111 }
112
113 LibProxyAPI &assertProxyApi() {
114 auto api = proxyApi();
115 if ( !api )
116 ZYPP_THROW( zypp::Exception("LibProxyAPI is not available.") );
117 return *api;
118 }
119 }
120
121 struct TmpUnsetEnv : private env::ScopedSet
122 {
123 TmpUnsetEnv( const char * var_r )
124 : env::ScopedSet( var_r, nullptr )
125 {}
126 };
127
128 static pxProxyFactoryType * getProxyFactory()
129 {
130 static pxProxyFactoryType * proxyFactory = 0;
131
132 // Force libproxy into using "/etc/sysconfig/proxy"
133 // if it exists.
134 static WatchFile sysconfigProxy( "/etc/sysconfig/proxy", WatchFile::NO_INIT );
135 if ( sysconfigProxy.hasChanged() )
136 {
137 MIL << "Build Libproxy Factory from /etc/sysconfig/proxy" << endl;
138 if ( proxyFactory )
139 assertProxyApi().deleteProxyFactory( proxyFactory );
140
141 TmpUnsetEnv envguard[] __attribute__ ((__unused__)) = { "KDE_FULL_SESSION", "GNOME_DESKTOP_SESSION_ID", "DESKTOP_SESSION" };
142 proxyFactory = assertProxyApi().createProxyFactory();
143 }
144 else if ( ! proxyFactory )
145 {
146 MIL << "Build Libproxy Factory" << endl;
147 proxyFactory = assertProxyApi().createProxyFactory();
148 }
149
150 return proxyFactory;
151 }
152
153 ProxyInfoLibproxy::ProxyInfoLibproxy()
154 : ProxyInfo::Impl()
155 , _factory( getProxyFactory())
156 {
157 _enabled = !(_factory == NULL);
158 }
159
160 ProxyInfoLibproxy::~ProxyInfoLibproxy()
161 {}
162
163 bool ProxyInfoLibproxy::isAvailabe()
164 {
165 return ( proxyApi () != nullptr );
166 }
167
168 std::string ProxyInfoLibproxy::proxy(const Url & url_r) const
169 {
170 if (!_enabled)
171 return "";
172
173 const url::ViewOption vopt =
174 url::ViewOption::WITH_SCHEME
175 + url::ViewOption::WITH_HOST
176 + url::ViewOption::WITH_PORT
177 + url::ViewOption::WITH_PATH_NAME;
178
179 auto &api = assertProxyApi ();
180
181 zypp::AutoDispose<char **> proxies(
182 api.getProxies(_factory, url_r.asString(vopt).c_str())
183 , api.freeProxies
184 );
185 if ( !proxies.value() )
186 return "";
187
188 // bsc#1244710: libproxy appears to return /etc/sysconfig/proxy
189 // values after $*_proxy environment variables.
190 // In YAST, e.g after changing the proxy settings, we'd like
191 // /etc/sysconfig/proxy changes to take effect immediately.
192 // So we pick the last proxy accessible via http/https.
193 // (sorts out direct:// or other directives returned by libproxy)
194 std::optional<std::string> result;
195 for ( int i = 0; proxies[i]; ++i ) {
196 if ( str::hasPrefix( proxies[i], "http" ) ) { // Filter for http/https
197 result = str::asString( proxies[i] );
198 if ( not env::inYAST() )
199 break;
200 }
201 }
202
203 if ( env::PX_DEBUG() ) {
204 L_DBG("PX_DEBUG") << "Url " << url_r << endl;
205 for ( int i = 0; proxies[i]; ++i ) {
206 L_DBG("PX_DEBUG") << "got " << proxies[i] << endl;
207 }
208 L_DBG("PX_DEBUG") << "--> " << result.value_or( "" ) << endl;
209 }
210
211 return result.value_or( "" );
212 }
213
214 ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyBegin() const
215 { return _no_proxy.begin(); }
216
217 ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyEnd() const
218 { return _no_proxy.end(); }
219
220 } // namespace media
221} // namespace zypp
AutoDispose.h
Env.h
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
Logger.h
MIL
#define MIL
Definition Logger.h:100
ERR
#define ERR
Definition Logger.h:102
L_DBG
#define L_DBG(GROUP)
Definition Logger.h:108
Pathname.h
String.h
zypp::AutoDispose
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
zypp::AutoDispose::value
reference value() const
Reference to the Tp object.
Definition AutoDispose.h:138
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::Url::asString
std::string asString() const
Returns a default string representation of the Url object.
Definition Url.cc:524
zypp::WatchFile
Remember a files attributes to detect content changes.
Definition watchfile.h:50
zypp::WatchFile::hasChanged
bool hasChanged()
Definition watchfile.h:80
zypp::WatchFile::NO_INIT
@ NO_INIT
Definition watchfile.h:52
zypp::media::ProxyInfoLibproxy::_enabled
DefaultIntegral< bool, false > _enabled
Definition proxyinfolibproxy.h:61
zypp::media::ProxyInfoLibproxy::_factory
pxProxyFactoryType * _factory
Definition proxyinfolibproxy.h:63
zypp::media::ProxyInfoLibproxy::noProxyBegin
ProxyInfo::NoProxyIterator noProxyBegin() const override
Definition proxyinfolibproxy.cc:214
zypp::media::ProxyInfoLibproxy::~ProxyInfoLibproxy
~ProxyInfoLibproxy() override
Definition proxyinfolibproxy.cc:160
zypp::media::ProxyInfoLibproxy::ProxyInfoLibproxy
ProxyInfoLibproxy()
Definition proxyinfolibproxy.cc:153
zypp::media::ProxyInfoLibproxy::proxy
std::string proxy(const Url &url_r) const override
Definition proxyinfolibproxy.cc:168
zypp::media::ProxyInfoLibproxy::noProxyEnd
ProxyInfo::NoProxyIterator noProxyEnd() const override
Definition proxyinfolibproxy.cc:217
zypp::media::ProxyInfoLibproxy::_no_proxy
ProxyInfo::NoProxyList _no_proxy
Definition proxyinfolibproxy.h:62
zypp::media::ProxyInfoLibproxy::isAvailabe
static bool isAvailabe()
Definition proxyinfolibproxy.cc:163
zypp::media::ProxyInfo
Definition proxyinfo.h:30
zypp::media::ProxyInfo::NoProxyIterator
std::list< std::string >::const_iterator NoProxyIterator
Definition proxyinfo.h:35
zypp::base
Definition Random.cc:7
zypp::env
Namespace intended to collect all environment variables we use.
Definition RepoVariables.cc:34
zypp::env::PX_DEBUG
bool PX_DEBUG()
Definition proxyinfolibproxy.cc:40
zypp::env::getenvBool
TriBool getenvBool(const C_Str &var_r)
If the environment variable var_r is set to a legal true or false string return bool,...
Definition Env.h:32
zypp::env::inYAST
bool inYAST()
Definition proxyinfolibproxy.cc:34
zypp::media
Definition MediaNetworkRequestExecutor.h:22
zypp::media::GetProxiesSig
char **(*)(ProxyFactoryType *self, const char *url) GetProxiesSig
Definition proxyinfolibproxy.h:35
zypp::media::DelFactorySig
void(*)(ProxyFactoryType *self) DelFactorySig
Definition proxyinfolibproxy.h:32
zypp::media::FreeProxiesCb
void(*)(char **proxies) FreeProxiesCb
Definition proxyinfolibproxy.h:37
zypp::media::CreateFactorySig
ProxyFactoryType *(*)(void) CreateFactorySig
Definition proxyinfolibproxy.h:29
zypp::media::getProxyFactory
static pxProxyFactoryType * getProxyFactory()
Definition proxyinfolibproxy.cc:128
zypp::str::asString
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
Definition String.h:140
zypp::str::hasPrefix
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition String.h:1097
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
pxProxyFactoryType
struct _pxProxyFactory pxProxyFactoryType
Definition proxyinfolibproxy.h:22
zypp::env::ScopedSet
Temporarily set/unset an environment variable.
Definition Env.h:45
zypp::env::ScopedSet::ScopedSet
ScopedSet(const ScopedSet &)=delete
zypp::media::ProxyInfo::Impl::Impl
Impl()
Ctor.
Definition proxyinfoimpl.h:28
zypp::media::TmpUnsetEnv
Definition proxyinfolibproxy.cc:122
zypp::media::TmpUnsetEnv::TmpUnsetEnv
TmpUnsetEnv(const char *var_r)
Definition proxyinfolibproxy.cc:123
zypp::url::ViewOption
Url::asString() view options.
Definition UrlBase.h:41