libzypp  17.35.16
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 
22 namespace 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 = 0, len = 0;
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  size_t 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 = 0, end = 0, len = 0;
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 char tab[] = "0123456789ABCDEF";
135  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  return std::string(out);
143  }
144 
145 
146  // ---------------------------------------------------------------
147  int
148  decode_octet(const char *hex)
149  {
150  if(hex && std::isxdigit(hex[0]) && std::isxdigit(hex[1]))
151  {
152  char x[3] = { hex[0], hex[1], '\0'};
153  return 0xff & ::strtol(x, NULL, 16);
154  }
155  else
156  {
157  return -1;
158  }
159  }
160 
161 
162  // ---------------------------------------------------------------
163  void
165  const std::string &pstr,
166  const std::string &psep)
167  {
168  size_t beg = 0, len = 0;
169  if( psep.empty())
170  {
172  _("Invalid parameter array split separator character")
173  ));
174  }
175 
176  len = pstr.length();
177  beg = 0;
178 
179  while( beg < len)
180  {
181  size_t pos = pstr.find(psep, beg);
182  if(pos != std::string::npos)
183  {
184  pvec.push_back( pstr.substr(beg, pos - beg));
185  beg = pos + 1;
186  }
187  else
188  {
189  pvec.push_back( pstr.substr(beg, len - beg));
190  beg = len;
191  }
192  }
193  }
194 
195 
196  // ---------------------------------------------------------------
197  void
199  const std::string &str,
200  const std::string &psep,
201  const std::string &vsep,
202  EEncoding eflag)
203  {
204  ParamVec pvec;
205  ParamVec::const_iterator pitr;
206  std::string k, v;
207 
208  if( psep.empty() || vsep.empty())
209  {
211  _("Invalid parameter map split separator character")
212  ));
213  }
214 
215  split(pvec, str, psep);
216 
217  for( pitr = pvec.begin(); pitr != pvec.end(); ++pitr)
218  {
219  size_t pos = pitr->find(vsep);
220  if(pos != std::string::npos)
221  {
222  if( eflag == E_DECODED)
223  {
224  k = url::decode(pitr->substr(0, pos));
225  v = url::decode(pitr->substr(pos + 1));
226  pmap[ k ] = v;
227  }
228  else
229  {
230  k = pitr->substr(0, pos);
231  v = pitr->substr(pos + 1);
232  pmap[ k ] = v;
233  }
234  }
235  else
236  {
237  if( eflag == E_DECODED)
238  {
239  pmap[ url::decode(*pitr) ] = "";
240  }
241  else
242  {
243  pmap[ *pitr ] = "";
244  }
245  }
246  }
247  }
248 
249 
250  // ---------------------------------------------------------------
251  std::string
252  join(const ParamVec &pvec,
253  const std::string &psep)
254  {
255  std::string str;
256  ParamVec::const_iterator i( pvec.begin());
257 
258  if( i != pvec.end())
259  {
260  str = *i;
261  while( ++i != pvec.end())
262  {
263  str += psep + *i;
264  }
265  }
266 
267  return str;
268  }
269 
270 
271  // ---------------------------------------------------------------
272  std::string
273  join(const ParamMap &pmap,
274  const std::string &psep,
275  const std::string &vsep,
276  const std::string &safe,
277  EEncoding eflag)
278  {
279  if( psep.empty() || vsep.empty())
280  {
282  _("Invalid parameter array join separator character")
283  ));
284  }
285 
286  std::string str;
287 
288  if ( eflag == E_DECODED )
289  {
290  std::string safeKey;
291  std::string safeVal;
292 
293  for(std::string::size_type i=0; i<safe.size(); i++)
294  {
295  if( psep.find(safe[i]) == std::string::npos ) {
296  if ( vsep.find(safe[i]) == std::string::npos ) {
297  safeKey.append(1, safe[i]);
298  safeVal.append(1, safe[i]);
299  } else {
300  safeVal.append(1, safe[i]);
301  }
302  }
303  }
304 
305  ParamMap::const_iterator i( pmap.begin());
306 
307  if( i != pmap.end())
308  {
309  str = encode(i->first, safeKey);
310  if( !i->second.empty())
311  str += vsep + encode(i->second, safeVal);
312 
313  while( ++i != pmap.end())
314  {
315  str += psep + encode(i->first, safeKey);
316  if( !i->second.empty())
317  str += vsep + encode(i->second, safeVal);
318  }
319  }
320  }
321  else
322  {
323  for ( const auto & [k,v] : pmap ) {
324  if ( not str.empty() )
325  str += psep;
326  str += k;
327  if ( not v.empty() ) {
328  str += vsep;
329  str += v;
330  }
331  }
332  }
333 
334  return str;
335  }
336 
337 
339  } // namespace url
341 
343 } // namespace zypp
345 /*
346 ** vim: set ts=2 sts=2 sw=2 ai et:
347 */
#define _(MSG)
Definition: Gettext.h:39
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:424
Thrown if the encoded string contains a NUL byte (%00).
Definition: UrlException.h:49
Flag to request encoded string(s).
Definition: UrlUtils.h:53
std::map< std::string, std::string > ParamMap
A parameter map container.
Definition: UrlUtils.h:47
String related utilities and Regular expression matching.
std::vector< std::string > ParamVec
A parameter vector container.
Definition: UrlUtils.h:40
Thrown if a feature e.g.
Definition: UrlException.h:124
int decode_octet(const char *hex)
Decode one character.
Definition: UrlUtils.cc:148
void split(ParamVec &pvec, const std::string &pstr, const std::string &psep)
Split into a parameter vector.
Definition: UrlUtils.cc:164
std::string encode_octet(const unsigned char c)
Encode one character.
Definition: UrlUtils.cc:132
std::string join(const ParamVec &pvec, const std::string &psep)
Join parameter vector to a string.
Definition: UrlUtils.cc:252
std::string decode(const std::string &str, bool allowNUL)
Decodes a URL percent encoded string.
Definition: UrlUtils.cc:87
std::string encode(const std::string &str, const std::string &safe, EEncoding eflag)
Encodes a string using URL percent encoding.
Definition: UrlUtils.cc:32
#define URL_SAFE_CHARS
Characters that are safe for URL without percent-encoding.
Definition: UrlUtils.h:22
EEncoding
Encoding flags.
Definition: UrlUtils.h:52
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
SolvableIdType size_type
Definition: PoolMember.h:126
Flag to request decoded string(s).
Definition: UrlUtils.h:54