libzypp  17.14.0
UrlUtils.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include "zypp/base/Gettext.h"
13 #include "zypp/base/String.h"
14 #include "zypp/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, 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 */
Interface to gettext.
std::vector< std::string > ParamVec
A parameter vector container.
Definition: UrlUtils.h:40
std::map< std::string, std::string > ParamMap
A parameter map container.
Definition: UrlUtils.h:47
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:392
Thrown if the encoded string contains a NUL byte (%00).
Definition: UrlException.h:49
Flag to request encoded string(s).
Definition: UrlUtils.h:53
int decode_octet(const char *hex)
Decode one character.
Definition: UrlUtils.cc:149
String related utilities and Regular expression matching.
std::string encode(const std::string &str, const std::string &safe, EEncoding eflag)
Encodes a string using URL percent encoding.
Definition: UrlUtils.cc:32
Url url
Definition: MediaCurl.cc:180
Thrown if a feature e.g.
Definition: UrlException.h:124
void split(ParamVec &pvec, const std::string &pstr, const std::string &psep)
Split into a parameter vector.
Definition: UrlUtils.cc:165
#define URL_SAFE_CHARS
Characters that are safe for URL without percent-encoding.
Definition: UrlUtils.h:22
std::string join(const ParamVec &pvec, const std::string &psep)
Join parameter vector to a string.
Definition: UrlUtils.cc:254
#define _(MSG)
Definition: Gettext.h:37
SolvableIdType size_type
Definition: PoolMember.h:126
EEncoding
Encoding flags.
Definition: UrlUtils.h:52
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
std::string decode(const std::string &str, bool allowNUL)
Decodes a URL percent encoded string.
Definition: UrlUtils.cc:87
std::string encode_octet(const unsigned char c)
Encode one character.
Definition: UrlUtils.cc:132
Flag to request decoded string(s).
Definition: UrlUtils.h:54