- implemented get/setPathParam and get/setQueryParam(param,value)
[platform/upstream/libzypp.git] / zypp / Url.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /**
10  * \file zypp/Url.cc
11  */
12 #include <zypp/Url.h>
13 #include <zypp/base/String.h>
14
15 #include <stdexcept>
16 // FIXME:
17 #if defined(WITH_URL_PARSE_DEBUG)
18 #include <iostream>
19 #endif
20
21 //////////////////////////////////////////////////////////////////////
22 namespace zypp
23 { ////////////////////////////////////////////////////////////////////
24
25
26   using namespace zypp::url;
27
28
29   // -----------------------------------------------------------------
30   /**
31    * url       = [scheme:] [//authority] /path [?query] [#fragment]
32    */
33   #define RX_SPLIT_URL                       "^(([^:/?#]+):)?" \
34                                              "(//([^/?#]*))?"  \
35                                              "([^?#]*)"        \
36                                              "([?]([^#]*))?"   \
37                                              "(#(.*))?"
38
39
40   // -----------------------------------------------------------------
41   // FIXME:
42   class LDAPUrl: public UrlBase
43   {
44   public:
45     LDAPUrl(): UrlBase()
46     {
47       configure();
48     }
49
50     LDAPUrl(const LDAPUrl &url): UrlBase(url)
51    {}
52
53     virtual UrlBase *
54     clone() const
55     {
56       return new LDAPUrl(*this);
57     }
58
59     virtual UrlBase::Schemes
60     getKnownSchemes() const
61     {
62       UrlBase::Schemes schemes(2);
63       schemes[0] = "ldap";
64       schemes[1] = "ldaps";
65       return schemes;
66     }
67
68     virtual void
69     configure()
70     {
71       // => put base-dn to path params :-)
72       // ahm... will this work propelly?
73       //config("sep_pathparams", "/");
74
75       config("psep_querystr",  "?");
76       config("vsep_querystr",  "");
77
78       config("safe_pathname",  "/=,");
79       config("safe_querystr",  "(),=");
80
81       // not allowed here
82       config("rx_username",     "");
83       config("rx_password",     "");
84       config("rx_fragment",     "");
85     }
86   };
87
88
89   // -----------------------------------------------------------------
90   // FIXME:
91   class UrlByScheme
92   {
93   private:
94     typedef std::map<std::string,UrlRef> UrlBySchemeMap;
95     UrlBySchemeMap urlByScheme;
96
97   public:
98     UrlByScheme()
99     {
100       UrlRef ref;
101
102       ref.reset( new LDAPUrl());
103       addUrlByScheme("ldap", ref);
104       addUrlByScheme("ldaps", ref);
105
106       ref.reset( new UrlBase());
107       // don't show empty authority
108       ref->setViewOptions( ref->getViewOptions() -
109                            zypp::url::ViewOption::EMPTY_AUTHORITY);
110       ref->config("rx_username",      "");  // disallow username
111       ref->config("rx_password",      "");  // disallow password
112       // FIXME: hmm... also host+port?
113       addUrlByScheme("nfs",    ref);
114
115       ref->config("safe_pathname",    "@"); // don't encode @ in path
116       ref->config("rx_hostname",      "");  // disallow hostname
117       ref->config("rx_port",          "");  // disallow port
118       addUrlByScheme("mailto", ref);
119     }
120
121     bool
122     addUrlByScheme(const std::string &scheme,
123                    UrlRef            urlImpl)
124     {
125       if( !scheme.empty() && urlImpl &&
126           urlImpl->isValidScheme(scheme))
127       {
128         UrlRef ref(urlImpl);
129         ref->clear();
130         urlByScheme[scheme] = ref;
131         return true;
132       }
133       return false;
134     }
135
136     UrlRef
137     getUrlByScheme(const std::string &scheme) const
138     {
139       UrlBySchemeMap::const_iterator i(urlByScheme.find(scheme));
140       if( i != urlByScheme.end())
141       {
142         return i->second;
143       }
144       return UrlRef();
145     }
146
147     UrlBase::Schemes
148     getKnownSchemes() const
149     {
150       UrlBySchemeMap::const_iterator i(urlByScheme.begin());
151       UrlBase::Schemes               schemes;
152
153       schemes.reserve(urlByScheme.size());
154       for( ; i != urlByScheme.begin(); ++i)
155       {
156         schemes.push_back(i->first);
157       }
158       return schemes;
159     }
160   };
161
162
163   // -----------------------------------------------------------------
164   UrlByScheme g_urlSchemeRepository;
165
166
167   // -----------------------------------------------------------------
168   Url::~Url()
169   {
170   }
171
172
173   // -----------------------------------------------------------------
174   Url::Url()
175     : m_impl( new UrlBase())
176   {
177   }
178
179
180   // -----------------------------------------------------------------
181   Url::Url(const Url &url)
182     : m_impl( url.m_impl)
183   {
184     if( !m_impl)
185     {
186       throw std::invalid_argument(
187         "Unable to clone Url object"
188       );
189     }
190   }
191
192
193   // -----------------------------------------------------------------
194   Url::Url(const std::string &encodedUrl)
195     : m_impl( parseUrl(encodedUrl))
196   {
197     if( !m_impl)
198     {
199       throw std::invalid_argument(
200         "Unable to parse Url components"
201       );
202     }
203   }
204
205
206   // -----------------------------------------------------------------
207   // static
208   bool
209   Url::registerScheme(const std::string &scheme,
210                       UrlRef            urlImpl)
211   {
212     return g_urlSchemeRepository.addUrlByScheme(scheme, urlImpl);
213   }
214
215
216   // -----------------------------------------------------------------
217   // static
218   UrlRef
219   Url::parseUrl(const std::string &encodedUrl)
220   {
221     UrlRef      url;
222     str::regex  rex(RX_SPLIT_URL);
223     str::smatch out;
224     bool        ret = str::regex_match(encodedUrl, out, rex);
225
226     // FIXME:
227     #if defined(WITH_URL_PARSE_DEBUG)
228     std::cerr << "Regex parsed URL components("
229               << out.size() << "):" << std::endl;
230     std::cerr << "URL " << encodedUrl << std::endl;
231     for(size_t n=0; n < out.size(); n++)
232     {
233       std::cerr << "[" << n << "] " << out[n].str() << std::endl;
234     }
235     #endif
236
237     if(ret && out.size() == 10)
238     {
239       url = g_urlSchemeRepository.getUrlByScheme(out[2].str());
240       if( !url)
241       {
242         url.reset( new UrlBase());
243       }
244       url->init(out[2].str(),
245                 out[4].str(),
246                 out[5].str(),
247                 out[7].str(),
248                 out[9].str());
249     }
250     return url;
251   }
252
253
254   // -----------------------------------------------------------------
255   // static
256   UrlBase::Schemes
257   Url::getAllKnownSchemes()
258   {
259     return g_urlSchemeRepository.getKnownSchemes();
260   }
261
262
263   // -----------------------------------------------------------------
264   UrlBase::Schemes
265   Url::getKnownSchemes() const
266   {
267     return m_impl->getKnownSchemes();
268   }
269
270
271   // -----------------------------------------------------------------
272   bool
273   Url::isValidScheme(const std::string &scheme) const
274   {
275     return m_impl->isValidScheme(scheme);
276   }
277
278
279   // -----------------------------------------------------------------
280   std::string
281   Url::toString() const
282   {
283     return m_impl->toString();
284   }
285
286
287   // -----------------------------------------------------------------
288   std::string
289   Url::toString(const ViewOptions &opts) const
290   {
291     return m_impl->toString(opts);
292   }
293
294
295   // -----------------------------------------------------------------
296   std::string
297   Url::getScheme() const
298   {
299     return m_impl->getScheme();
300   }
301
302
303   // -----------------------------------------------------------------
304   std::string
305   Url::getAuthority() const
306   {
307     return m_impl->getAuthority();
308   }
309
310   // -----------------------------------------------------------------
311   std::string
312   Url::getPathData() const
313   {
314     return m_impl->getPathData();
315   }
316
317
318   // -----------------------------------------------------------------
319   std::string
320   Url::getQueryString() const
321   {
322     return m_impl->getQueryString();
323   }
324
325
326   // -----------------------------------------------------------------
327   std::string
328   Url::getFragment(zypp::url::EEncoding eflag) const
329   {
330     return m_impl->getFragment(eflag);
331   }
332
333
334   // -----------------------------------------------------------------
335   std::string
336   Url::getUsername(EEncoding eflag) const
337   {
338     return m_impl->getUsername(eflag);
339   }
340
341
342   // -----------------------------------------------------------------
343   std::string
344   Url::getPassword(EEncoding eflag) const
345   {
346     return m_impl->getPassword(eflag);
347   }
348
349
350   // -----------------------------------------------------------------
351   std::string
352   Url::getHost(EEncoding eflag) const
353   {
354     return m_impl->getHost(eflag);
355   }
356
357
358   // -----------------------------------------------------------------
359   std::string
360   Url::getPort() const
361   {
362     return m_impl->getPort();
363   }
364
365
366   // -----------------------------------------------------------------
367   std::string
368   Url::getPathName(EEncoding eflag) const
369   {
370     return m_impl->getPathName(eflag);
371   }
372
373
374   // -----------------------------------------------------------------
375   std::string
376   Url::getPathParams() const
377   {
378     return m_impl->getPathParams();
379   }
380
381
382   // -----------------------------------------------------------------
383   zypp::url::ParamVec
384   Url::getPathParamsVec() const
385   {
386     return m_impl->getPathParamsVec();
387   }
388
389
390   // -----------------------------------------------------------------
391   zypp::url::ParamMap
392   Url::getPathParamsMap(EEncoding eflag) const
393   {
394     return m_impl->getPathParamsMap(eflag);
395   }
396
397
398   // -----------------------------------------------------------------
399   std::string
400   Url::getPathParam(const std::string &param, EEncoding eflag) const
401   {
402     return m_impl->getPathParam(param, eflag);
403   }
404
405
406   // -----------------------------------------------------------------
407   zypp::url::ParamVec
408   Url::getQueryStringVec() const
409   {
410     return m_impl->getQueryStringVec();
411   }
412
413
414   // -----------------------------------------------------------------
415   zypp::url::ParamMap
416   Url::getQueryStringMap(EEncoding eflag) const
417   {
418     return m_impl->getQueryStringMap(eflag);
419   }
420
421
422   // -----------------------------------------------------------------
423   std::string
424   Url::getQueryParam(const std::string &param, EEncoding eflag) const
425   {
426     return m_impl->getQueryParam(param, eflag);
427   }
428
429
430   // -----------------------------------------------------------------
431   void
432   Url::setScheme(const std::string &scheme)
433   {
434     if(scheme == m_impl->getScheme())
435     {
436       return;
437     }
438     if( m_impl->isKnownScheme(scheme))
439     {
440       m_impl->setScheme(scheme);
441       return;
442     }
443
444     UrlRef url = g_urlSchemeRepository.getUrlByScheme(scheme);
445     if( !url)
446     {
447       url.reset( new UrlBase());
448     }
449     url->init(
450       scheme,
451       m_impl->getAuthority(),
452       m_impl->getPathData(),
453       m_impl->getQueryString(),
454       m_impl->getFragment(zypp::url::E_ENCODED)
455     );
456     m_impl = url;
457   }
458
459
460   // -----------------------------------------------------------------
461   void
462   Url::setAuthority(const std::string &authority)
463   {
464     m_impl->setAuthority(authority);
465   }
466
467
468   // -----------------------------------------------------------------
469   void
470   Url::setPathData(const std::string &pathdata)
471   {
472     m_impl->setPathData(pathdata);
473   }
474
475
476   // -----------------------------------------------------------------
477   void
478   Url::setQueryString(const std::string &querystr)
479   {
480     m_impl->setQueryString(querystr);
481   }
482
483
484   // -----------------------------------------------------------------
485   void
486   Url::setFragment(const std::string &fragment)
487   {
488     m_impl->setFragment(fragment);
489   }
490
491
492   // -----------------------------------------------------------------
493   void
494   Url::setUsername(const std::string &user)
495   {
496     m_impl->setUsername(user);
497   }
498
499
500   // -----------------------------------------------------------------
501   void
502   Url::setPassword(const std::string &pass)
503   {
504     m_impl->setPassword(pass);
505   }
506
507
508   // -----------------------------------------------------------------
509   void
510   Url::setHost(const std::string &host)
511   {
512     m_impl->setHost(host);
513   }
514
515
516   // -----------------------------------------------------------------
517   void
518   Url::setPort(const std::string &port)
519   {
520     m_impl->setPort(port);
521   }
522
523
524   // -----------------------------------------------------------------
525   void
526   Url::setPathName(const std::string &path)
527   {
528     m_impl->setPathName(path);
529   }
530
531
532   // -----------------------------------------------------------------
533   void
534   Url::setPathParams(const std::string &params)
535   {
536     m_impl->setPathParams(params);
537   }
538
539
540   // -----------------------------------------------------------------
541   void
542   Url::setPathParamsVec(const zypp::url::ParamVec &pvec)
543   {
544     m_impl->setPathParamsVec(pvec);
545   }
546
547
548   // -----------------------------------------------------------------
549   void
550   Url::setPathParamsMap(const zypp::url::ParamMap &pmap)
551   {
552     m_impl->setPathParamsMap(pmap);
553   }
554
555
556   // -----------------------------------------------------------------
557   void
558   Url::setPathParam(const std::string &param, const std::string &value)
559   {
560     m_impl->setPathParam(param, value);
561   }
562
563
564   // -----------------------------------------------------------------
565   void
566   Url::setQueryStringVec(const zypp::url::ParamVec &pvec)
567   {
568     m_impl->setQueryStringVec(pvec);
569   }
570
571
572   // -----------------------------------------------------------------
573   void
574   Url::setQueryStringMap(const zypp::url::ParamMap &pmap)
575   {
576     m_impl->setQueryStringMap(pmap);
577   }
578
579   // -----------------------------------------------------------------
580   void
581   Url::setQueryParam(const std::string &param, const std::string &value)
582   {
583     m_impl->setQueryParam(param, value);
584   }
585
586
587   // -----------------------------------------------------------------
588   std::ostream & operator<<( std::ostream & str, const Url & url )
589   {
590     return str << url.toString();
591   }
592
593
594   ////////////////////////////////////////////////////////////////////
595 } // namespace zypp
596 //////////////////////////////////////////////////////////////////////
597 /*
598 ** vim: set ts=2 sts=2 sw=2 ai et:
599 */