1 /*******************************************************************************
2  * libproxy sysconfig module
3  * Copyright (C) 2010 Novell Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
18  ******************************************************************************/
19 
20 #include <sys/stat.h>
21 #include <cstdlib>
22 #include <map>
23 #include <fstream>
24 #include <unistd.h>
25 #include <sys/types.h>
26 
27 
28 #include "../extension_config.hpp"
29 using namespace libproxy;
30 using std::map;
31 
32 enum Trim {
33     NO_TRIM = 0x00,
34     L_TRIM  = 0x01,
35     R_TRIM  = 0x02,
36     TRIM    = (L_TRIM|R_TRIM)
37 };
38 
trim(const std::string & s,const Trim trim_r=TRIM)39 static std::string trim( const std::string & s, const Trim trim_r = TRIM ) {
40 
41 	if (s.empty() || trim_r == NO_TRIM)
42 		return s;
43 
44 	std::string ret(s);
45 
46 	if (trim_r & L_TRIM) {
47  		std::string::size_type p = ret.find_first_not_of(" \t\n");
48 		if (p == std::string::npos)
49 			return std::string();
50 
51 		ret = ret.substr(p);
52 	}
53 
54 	if (trim_r & R_TRIM) {
55 		std::string::size_type p = ret.find_last_not_of(" \t\n");
56 		if (p == std::string::npos)
57 			return std::string();
58 
59 		ret = ret.substr(0, p+1);
60 	}
61 
62 	return ret;
63 }
64 
sysconfig_read(const string & _path)65 static map<string,string> sysconfig_read(const string &_path)	{
66 
67 	map<string,string> ret;
68 	string line;
69 
70 	ifstream in(_path.c_str());
71 	if (in.fail()) {
72 		return ret;
73 	}
74 
75 	while(getline( in, line)) {
76 
77 		if (*line.begin() != '#') {
78 
79 			string::size_type pos = line.find('=', 0);
80 
81 			if (pos != string::npos) {
82 
83  				string key = trim(line.substr(0, pos));
84  				string value = trim(line.substr(pos + 1, line.length() - pos - 1));
85 
86 				if (value.length() >= 2
87 				    && *(value.begin()) == '"'
88 				    && *(value.rbegin()) == '"') {
89 					value = value.substr( 1, value.length() - 2 );
90 				}
91 
92 				if (value.length() >= 2
93 				    && *(value.begin()) == '\''
94  				    && *(value.rbegin()) == '\'' ) {
95 					value = value.substr( 1, value.length() - 2 );
96 				}
97 				ret[key] = value;
98 			} // '=' found
99 
100 		} // not comment
101 
102 	} // while getline
103 	return ret;
104 }
105 
should_use_sysconfig()106 static bool should_use_sysconfig()
107 {
108 	struct stat st;
109 	if (stat("/etc/sysconfig", &st) == 0)
110 		return (getuid() == 0);
111 	return false;
112 }
113 
114 class sysconfig_config_extension : public config_extension {
115 
116 	map<string,string> _data;
117 
118 public:
sysconfig_config_extension()119 	sysconfig_config_extension()
120 		: _data(sysconfig_read("/etc/sysconfig/proxy")) {
121 
122 	}
123 
~sysconfig_config_extension()124 	~sysconfig_config_extension() {
125 	}
126 
get_config(const url & dst)127 	vector<url> get_config(const url &dst) {
128 		map<string,string>::const_iterator it = _data.find("PROXY_ENABLED");
129 		vector<url> response;
130 
131 		if (it != _data.end() && it->second == "no") {
132 			response.push_back(url("direct://"));
133 			return response;
134 		}
135 
136 		string key;
137 		string proxy;
138 
139 		// If the URL is an ftp url, try to read the ftp proxy
140 		if (dst.get_scheme() == "ftp")
141 			key = "FTP_PROXY";
142 		else if (dst.get_scheme() == "http")
143 			key = "HTTP_PROXY";
144 		else if (dst.get_scheme() == "https")
145 			key = "HTTPS_PROXY";
146 
147 		it = _data.find(key);
148 		if (it != _data.end())
149 			proxy = it->second;
150 
151 		if (proxy.empty())
152 			throw runtime_error("Unable to read configuration");
153 
154 		response.push_back(url(proxy));
155 		return response;
156 	}
157 
get_ignore(const url &)158 	string get_ignore(const url&) {
159 		map<string,string>::const_iterator it = _data.find("NO_PROXY");
160 		if (it != _data.end())
161 			return it->second;
162 		return "";
163         }
164 
165 	// if we are running as root, and the module is used, then
166 	// make sure this is the first method tried
operator <(const base_extension &) const167 	virtual bool operator<(const base_extension&) const {
168 		return true;
169 	}
170 };
171 
172 MM_MODULE_INIT_EZ(sysconfig_config_extension, should_use_sysconfig(), NULL, NULL);
173 
174