libzypp 17.31.7
UrlUtils.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <zypp-core/base/Gettext.h>
13#include <zypp-core/base/String.h>
14#include <zypp-core/url/UrlUtils.h>
15
16#include <stdlib.h> // strtol
17#include <cctype> // isxdigit
18#include <stdexcept>
19
20
22namespace zypp
23{
24
26 namespace url
27 {
28
29
30 // ---------------------------------------------------------------
31 std::string
32 encode(const std::string &str, const std::string &safe,
33 EEncoding eflag)
34 {
35 std::string skip("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
36 "abcdefghijklmnopqrstuvwxyz"
37 "0123456789.~_-");
38 static const std::string more(URL_SAFE_CHARS); // ":/?#[]@!$&'()*+,;="
39 size_t beg, pos, len;
40 std::string out;
41
42 for(size_t i=0; i<safe.size(); i++)
43 {
44 if( more.find(safe.at(i)) != std::string::npos)
45 skip.append(1, safe.at(i));
46 }
47
48 len = str.length();
49 beg = 0;
50 while( beg < len)
51 {
52 pos = str.find_first_not_of(skip, beg);
53 if(pos != std::string::npos)
54 {
55 if( pos > beg)
56 {
57 out.append(str, beg, pos - beg);
58 }
59
60 if( eflag == E_ENCODED &&
61 pos + 2 < len &&
62 str.at(pos) == '%' &&
63 std::isxdigit(str.at(pos + 1)) &&
64 std::isxdigit(str.at(pos + 2)))
65 {
66 out.append(str, pos, 3);
67 beg = pos + 3;
68 }
69 else
70 {
71 out.append( encode_octet( str.at(pos)));
72 beg = pos + 1;
73 }
74 }
75 else
76 {
77 out.append(str, beg, len - beg);
78 beg = len;
79 }
80 }
81 return out;
82 }
83
84
85 // ---------------------------------------------------------------
86 std::string
87 decode(const std::string &str, bool allowNUL)
88 {
89 size_t pos, end, len;
90 std::string out(str);
91
92 len = out.length();
93 pos = end = 0;
94 while(pos < len)
95 {
96 out[end] = out[pos];
97 if( pos + 2 < len && out.at(pos) == '%')
98 {
99 int c = decode_octet(out.c_str() + pos + 1);
100 switch(c)
101 {
102 case -1:
103 // not a hex noted octet...
104 break;
105
106 case 0:
107 // is a %00 octet allowed ?
108 if( !allowNUL)
109 {
111 _("Encoded string contains a NUL byte")
112 ));
113 }
114 default:
115 // other octets are fine...
116 out[end] = c;
117 pos += 2;
118 break;
119 }
120 }
121 pos++;
122 end++;
123 }
124 if( end < pos)
125 out.erase(end);
126 return out;
127 }
128
129
130 // ---------------------------------------------------------------
131 std::string
132 encode_octet(const unsigned char c)
133 {
134 static const unsigned char tab[] = "0123456789ABCDEF";
135 unsigned char out[4];
136
137 out[0] = '%';
138 out[1] = tab[0x0f & (c >> 4)];
139 out[2] = tab[0x0f & c];
140 out[3] = '\0';
141
142 //snprintf(out, sizeof(out), "%%%02X", c);
143 return std::string((char *)out);
144 }
145
146
147 // ---------------------------------------------------------------
148 int
149 decode_octet(const char *hex)
150 {
151 if(hex && std::isxdigit(hex[0]) && std::isxdigit(hex[1]))
152 {
153 char x[3] = { hex[0], hex[1], '\0'};
154 return 0xff & ::strtol(x, NULL, 16);
155 }
156 else
157 {
158 return -1;
159 }
160 }
161
162
163 // ---------------------------------------------------------------
164 void
166 const std::string &pstr,
167 const std::string &psep)
168 {
169 size_t beg, pos, len;
170 if( psep.empty())
171 {
173 _("Invalid parameter array split separator character")
174 ));
175 }
176
177 len = pstr.length();
178 beg = 0;
179
180 while( beg < len)
181 {
182 pos = pstr.find(psep, beg);
183 if(pos != std::string::npos)
184 {
185 pvec.push_back( pstr.substr(beg, pos - beg));
186 beg = pos + 1;
187 }
188 else
189 {
190 pvec.push_back( pstr.substr(beg, len - beg));
191 beg = len;
192 }
193 }
194 }
195
196
197 // ---------------------------------------------------------------
198 void
200 const std::string &str,
201 const std::string &psep,
202 const std::string &vsep,
203 EEncoding eflag)
204 {
205 ParamVec pvec;
206 ParamVec::const_iterator pitr;
207 std::string k, v;
208 size_t pos;
209
210 if( psep.empty() || vsep.empty())
211 {
213 _("Invalid parameter map split separator character")
214 ));
215 }
216
217 split(pvec, str, psep);
218
219 for( pitr = pvec.begin(); pitr != pvec.end(); ++pitr)
220 {
221 pos = pitr->find(vsep);
222 if(pos != std::string::npos)
223 {
224 if( eflag == E_DECODED)
225 {
226 k = url::decode(pitr->substr(0, pos));
227 v = url::decode(pitr->substr(pos + 1));
228 pmap[ k ] = v;
229 }
230 else
231 {
232 k = pitr->substr(0, pos);
233 v = pitr->substr(pos + 1);
234 pmap[ k ] = v;
235 }
236 }
237 else
238 {
239 if( eflag == E_DECODED)
240 {
241 pmap[ url::decode(*pitr) ] = "";
242 }
243 else
244 {
245 pmap[ *pitr ] = "";
246 }
247 }
248 }
249 }
250
251
252 // ---------------------------------------------------------------
253 std::string
254 join(const ParamVec &pvec,
255 const std::string &psep)
256 {
257 std::string str;
258 ParamVec::const_iterator i( pvec.begin());
259
260 if( i != pvec.end())
261 {
262 str = *i;
263 while( ++i != pvec.end())
264 {
265 str += psep + *i;
266 }
267 }
268
269 return str;
270 }
271
272
273 // ---------------------------------------------------------------
274 std::string
275 join(const ParamMap &pmap,
276 const std::string &psep,
277 const std::string &vsep,
278 const std::string &safe)
279 {
280 if( psep.empty() || vsep.empty())
281 {
283 _("Invalid parameter array join separator character")
284 ));
285 }
286
287 std::string join_safe;
288 for(std::string::size_type i=0; i<safe.size(); i++)
289 {
290 if( psep.find(safe[i]) == std::string::npos &&
291 vsep.find(safe[i]) == std::string::npos)
292 {
293 join_safe.append(1, safe[i]);
294 }
295 }
296 std::string str;
297 ParamMap::const_iterator i( pmap.begin());
298
299 if( i != pmap.end())
300 {
301 str = encode(i->first, join_safe);
302 if( !i->second.empty())
303 str += vsep + encode(i->second, join_safe);
304
305 while( ++i != pmap.end())
306 {
307 str += psep + encode(i->first, join_safe);
308 if( !i->second.empty())
309 str += vsep + encode(i->second, join_safe);
310 }
311 }
312
313 return str;
314 }
315
316
318 } // namespace url
320
322} // namespace zypp
324/*
325** vim: set ts=2 sts=2 sw=2 ai et:
326*/
Thrown if the encoded string contains a NUL byte (%00).
Definition: UrlException.h:50
Thrown if a feature e.g.
Definition: UrlException.h:125
String related utilities and Regular expression matching.
SolvableIdType size_type
Definition: PoolMember.h:126
int decode_octet(const char *hex)
Decode one character.
Definition: UrlUtils.cc:149
std::string encode_octet(const unsigned char c)
Encode one character.
Definition: UrlUtils.cc:132
std::string encode(const std::string &str, const std::string &safe, EEncoding eflag)
Encodes a string using URL percent encoding.
Definition: UrlUtils.cc:32
std::map< std::string, std::string > ParamMap
A parameter map container.
Definition: UrlUtils.h:47
std::vector< std::string > ParamVec
A parameter vector container.
Definition: UrlUtils.h:40
void split(ParamVec &pvec, const std::string &pstr, const std::string &psep)
Split into a parameter vector.
Definition: UrlUtils.cc:165
std::string join(const ParamVec &pvec, const std::string &psep)
Join parameter vector to a string.
Definition: UrlUtils.cc:254
EEncoding
Encoding flags.
Definition: UrlUtils.h:52
@ E_DECODED
Flag to request decoded string(s).
Definition: UrlUtils.h:54
@ E_ENCODED
Flag to request encoded string(s).
Definition: UrlUtils.h:53
std::string decode(const std::string &str, bool allowNUL)
Decodes a URL percent encoded string.
Definition: UrlUtils.cc:87
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define _(MSG)
Definition: Gettext.h:37
#define URL_SAFE_CHARS
Characters that are safe for URL without percent-encoding.
Definition: UrlUtils.h:22