revert isLocal metod and use downloads instead to decide when cache packages.
[platform/upstream/libzypp.git] / zypp / Url.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /**
10  * \file zypp/Url.cc
11  */
12
13 #include <zypp/Url.h>
14 #include <zypp/base/Gettext.h>
15 #include <zypp/base/String.h>
16 #include <zypp/base/Regex.h>
17 #include <stdexcept>
18 #include <iostream>
19
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   namespace
42   { //////////////////////////////////////////////////////////////////
43
44
45     // ---------------------------------------------------------------
46     class LDAPUrl: public UrlBase
47     {
48     public:
49       LDAPUrl(): UrlBase()
50       {
51         configure();
52       }
53
54       LDAPUrl(const LDAPUrl &url): UrlBase(url)
55       {}
56
57       virtual UrlBase *
58       clone() const
59       {
60         return new LDAPUrl(*this);
61       }
62
63       virtual UrlSchemes
64       getKnownSchemes() const
65       {
66         UrlSchemes schemes(2);
67         schemes[0] = "ldap";
68         schemes[1] = "ldaps";
69         return schemes;
70       }
71
72       virtual void
73       configure()
74       {
75         config("sep_pathparams",  "");
76
77         config("psep_querystr",   "?");
78         config("vsep_querystr",   "");
79
80         // host is required (isValid=>false)
81         // but not mandatory (see RFC 2255),
82         // that is, accept empty host.
83         config("require_host",    "y");
84
85         // not allowed here
86         config("rx_username",     "");
87         config("rx_password",     "");
88         config("rx_fragment",     "");
89         config("rx_pathparams",   "");
90       }
91
92       virtual zypp::url::ParamMap
93       getQueryStringMap(zypp::url::EEncoding eflag) const
94       {
95         static const char * const keys[] = {
96           "attrs", "scope", "filter", "exts", NULL
97         };
98         zypp::url::ParamMap pmap;
99         zypp::url::ParamVec pvec( getQueryStringVec());
100         if( pvec.size() <= 4)
101         {
102           for(size_t i=0; i<pvec.size(); i++)
103           {
104             if(eflag == zypp::url::E_ENCODED)
105               pmap[keys[i]] = pvec[i];
106             else
107               pmap[keys[i]] = zypp::url::decode( pvec[i]);
108           }
109         }
110         else
111         {
112           ZYPP_THROW(url::UrlNotSupportedException(
113             _("Invalid LDAP URL query string")
114           ));
115         }
116         return pmap;
117       }
118
119       virtual void
120       setQueryStringMap(const zypp::url::ParamMap &pmap)
121       {
122         static const char * const keys[] = {
123           "attrs", "scope", "filter", "exts", NULL
124         };
125
126         // remove psep ("?") from safe chars
127         std::string join_safe;
128         std::string safe(config("safe_querystr"));
129         std::string psep(config("psep_querystr"));
130         for(std::string::size_type i=0; i<safe.size(); i++)
131         {
132           if( psep.find(safe[i]) == std::string::npos)
133             join_safe.append(1, safe[i]);
134         }
135
136         zypp::url::ParamVec pvec(4);
137         zypp::url::ParamMap::const_iterator p;
138         for(p=pmap.begin(); p!=pmap.end(); ++p)
139         {
140           bool found=false;
141           for(size_t i=0; i<4; i++)
142           {
143             if(p->first == keys[i])
144             {
145               found=true;
146               pvec[i] = zypp::url::encode(p->second, join_safe);
147             }
148           }
149           if( !found)
150           {
151             ZYPP_THROW(url::UrlNotSupportedException(
152               str::form(_("Invalid LDAP URL query parameter '%s'"),
153                           p->first.c_str())
154             ));
155           }
156         }
157         setQueryStringVec(pvec);
158       }
159     };
160
161
162     // ---------------------------------------------------------------
163     // FIXME: hmm..
164     class UrlByScheme
165     {
166     private:
167       typedef std::map<std::string,UrlRef> UrlBySchemeMap;
168       UrlBySchemeMap urlByScheme;
169
170     public:
171       UrlByScheme()
172       {
173         UrlRef ref;
174
175         // =====================================
176         ref.reset( new LDAPUrl());
177         addUrlByScheme("ldap", ref);
178         addUrlByScheme("ldaps", ref);
179
180
181         // =====================================
182         ref.reset( new UrlBase());
183         ref->config("with_authority",   "n");   // disallow host,...
184         ref->config("require_pathname", "m");   // path is mandatory
185         addUrlByScheme("hd",     ref);
186         addUrlByScheme("cd",     ref);
187         addUrlByScheme("dvd",    ref);
188         addUrlByScheme("dir",    ref);
189         addUrlByScheme("iso",    ref);
190
191         // don't show empty authority
192         ref->setViewOptions( zypp::url::ViewOption::DEFAULTS -
193                              zypp::url::ViewOption::EMPTY_AUTHORITY);
194         addUrlByScheme("mailto", ref);
195         addUrlByScheme("urn",    ref);
196
197         // RFC1738, 3.10: may contain a host
198         ref->config("with_authority",   "y");   // allow host,
199         ref->config("with_port",        "n");   // but no port,
200         ref->config("rx_username",      "");    // username or
201         ref->config("rx_password",      "");    // password ...
202         addUrlByScheme("file",   ref);
203
204         // =====================================
205         ref.reset( new UrlBase());
206         ref->config("require_host",     "m");   // host is mandatory
207         addUrlByScheme("nfs",    ref);
208         addUrlByScheme("smb",    ref);
209         addUrlByScheme("cifs",   ref);
210         addUrlByScheme("http",   ref);
211         addUrlByScheme("https",  ref);
212         ref->config("path_encode_slash2", "y"); // always encode 2. slash
213         addUrlByScheme("ftp",    ref);
214         addUrlByScheme("sftp",   ref);
215       }
216
217       bool
218       addUrlByScheme(const std::string &scheme,
219                      UrlRef            urlImpl)
220       {
221         if( urlImpl && urlImpl->isValidScheme(scheme))
222         {
223           UrlRef ref(urlImpl);
224           ref->clear();
225           urlByScheme[str::toLower(scheme)] = ref;
226           return true;
227         }
228         return false;
229       }
230
231       UrlRef
232       getUrlByScheme(const std::string &scheme) const
233       {
234         UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme)));
235         if( i != urlByScheme.end())
236         {
237           return i->second;
238         }
239         return UrlRef();
240       }
241
242       bool
243       isRegisteredScheme(const std::string &scheme) const
244       {
245         return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end();
246       }
247
248       UrlSchemes
249       getRegisteredSchemes() const
250       {
251         UrlBySchemeMap::const_iterator i(urlByScheme.begin());
252         UrlSchemes                     schemes;
253
254         schemes.reserve(urlByScheme.size());
255         for( ; i != urlByScheme.end(); ++i)
256         {
257           schemes.push_back(i->first);
258         }
259         return schemes;
260       }
261     };
262
263
264     // ---------------------------------------------------------------
265     UrlByScheme & g_urlSchemeRepository()
266     {
267       static UrlByScheme _v;
268       return _v;
269     }
270
271     //////////////////////////////////////////////////////////////////
272   } // anonymous namespace
273   ////////////////////////////////////////////////////////////////////
274
275
276   // -----------------------------------------------------------------
277   Url::~Url()
278   {
279   }
280
281
282   // -----------------------------------------------------------------
283   Url::Url()
284     : m_impl( new UrlBase())
285   {
286   }
287
288
289   // -----------------------------------------------------------------
290   Url::Url(const Url &url)
291     : m_impl( url.m_impl)
292   {
293     if( !m_impl)
294     {
295       ZYPP_THROW(url::UrlException(
296         _("Unable to clone Url object")
297       ));
298     }
299   }
300
301
302   // -----------------------------------------------------------------
303   Url::Url(const zypp::url::UrlRef &url)
304     : m_impl( url)
305   {
306     if( !m_impl)
307     {
308       ZYPP_THROW(url::UrlException(
309         _("Invalid empty Url object reference")
310       ));
311     }
312   }
313
314
315   // -----------------------------------------------------------------
316   Url::Url(const std::string &encodedUrl)
317     : m_impl( parseUrl(encodedUrl))
318   {
319     if( !m_impl)
320     {
321       ZYPP_THROW(url::UrlParsingException(
322         _("Unable to parse Url components")
323       ));
324     }
325   }
326
327
328   // -----------------------------------------------------------------
329   Url&
330   Url::operator = (const std::string &encodedUrl)
331   {
332     UrlRef url( parseUrl(encodedUrl));
333     if( !url)
334     {
335       ZYPP_THROW(url::UrlParsingException(
336         _("Unable to parse Url components")
337       ));
338     }
339     m_impl = url;
340     return *this;
341   }
342
343
344   // -----------------------------------------------------------------
345   Url&
346   Url::operator = (const Url &url)
347   {
348     m_impl = url.m_impl;
349     return *this;
350   }
351
352
353   // -----------------------------------------------------------------
354   // static
355   bool
356   Url::registerScheme(const std::string &scheme,
357                       UrlRef            urlImpl)
358   {
359     return g_urlSchemeRepository().addUrlByScheme(scheme, urlImpl);
360   }
361
362
363   // -----------------------------------------------------------------
364   // static
365   UrlRef
366   Url::parseUrl(const std::string &encodedUrl)
367   {
368     UrlRef      url;
369     str::smatch out;
370     bool        ret = false;
371
372     try
373     {
374       str::regex  rex(RX_SPLIT_URL);
375       ret = str::regex_match(encodedUrl, out, rex);
376     }
377     catch( ... )
378     {}
379
380     if(ret && out.size() == 5)
381     {
382       std::string scheme = out[1];
383       if (scheme.size() > 1)
384         scheme = scheme.substr(0, scheme.size()-1);
385       std::string authority = out[2];
386       if (authority.size() >= 2)
387         authority = authority.substr(2);
388       std::string query = out[4];
389       if (query.size() > 1)
390         query = query.substr(1);
391       std::string fragment = out[5];
392       if (fragment.size() > 1)
393         fragment = fragment.substr(1);
394
395       url = g_urlSchemeRepository().getUrlByScheme(scheme);
396       if( !url)
397       {
398         url.reset( new UrlBase());
399       }
400       url->init(scheme, authority, out[3],
401                 query, fragment);
402     }
403     return url;
404   }
405
406
407   // -----------------------------------------------------------------
408   // static
409   zypp::url::UrlSchemes
410   Url::getRegisteredSchemes()
411   {
412     return g_urlSchemeRepository().getRegisteredSchemes();
413   }
414
415
416   // -----------------------------------------------------------------
417   // static
418   bool
419   Url::isRegisteredScheme(const std::string &scheme)
420   {
421     return g_urlSchemeRepository().isRegisteredScheme(scheme);
422   }
423
424
425   // -----------------------------------------------------------------
426   zypp::url::UrlSchemes
427   Url::getKnownSchemes() const
428   {
429     return m_impl->getKnownSchemes();
430   }
431
432
433   // -----------------------------------------------------------------
434   bool
435   Url::isValidScheme(const std::string &scheme) const
436   {
437     return m_impl->isValidScheme(scheme);
438   }
439
440
441   // -----------------------------------------------------------------
442   bool
443   Url::isValid() const
444   {
445     return m_impl->isValid();
446   }
447
448
449   // -----------------------------------------------------------------
450   std::string
451   Url::asString() const
452   {
453     return m_impl->asString();
454   }
455
456
457   // -----------------------------------------------------------------
458   std::string
459   Url::asCompleteString() const
460   {
461     // make sure, all url components are included;
462     // regardless of the current configuration...
463     ViewOptions opts(getViewOptions() +
464                      ViewOption::WITH_SCHEME +
465                      ViewOption::WITH_USERNAME +
466                      ViewOption::WITH_PASSWORD +
467                      ViewOption::WITH_HOST +
468                      ViewOption::WITH_PORT +
469                      ViewOption::WITH_PATH_NAME +
470                      ViewOption::WITH_PATH_PARAMS +
471                      ViewOption::WITH_QUERY_STR +
472                      ViewOption::WITH_FRAGMENT);
473     return m_impl->asString(opts);
474   }
475
476
477   // -----------------------------------------------------------------
478   std::string
479   Url::asString(const ViewOptions &opts) const
480   {
481     return m_impl->asString(opts);
482   }
483
484
485   // -----------------------------------------------------------------
486   std::string
487   Url::getScheme() const
488   {
489     return m_impl->getScheme();
490   }
491
492
493   // -----------------------------------------------------------------
494   std::string
495   Url::getAuthority() const
496   {
497     return m_impl->getAuthority();
498   }
499
500   // -----------------------------------------------------------------
501   std::string
502   Url::getPathData() const
503   {
504     return m_impl->getPathData();
505   }
506
507
508   // -----------------------------------------------------------------
509   std::string
510   Url::getQueryString() const
511   {
512     return m_impl->getQueryString();
513   }
514
515
516   // -----------------------------------------------------------------
517   std::string
518   Url::getFragment(zypp::url::EEncoding eflag) const
519   {
520     return m_impl->getFragment(eflag);
521   }
522
523
524   // -----------------------------------------------------------------
525   std::string
526   Url::getUsername(EEncoding eflag) const
527   {
528     return m_impl->getUsername(eflag);
529   }
530
531
532   // -----------------------------------------------------------------
533   std::string
534   Url::getPassword(EEncoding eflag) const
535   {
536     return m_impl->getPassword(eflag);
537   }
538
539
540   // -----------------------------------------------------------------
541   std::string
542   Url::getHost(EEncoding eflag) const
543   {
544     return m_impl->getHost(eflag);
545   }
546
547
548   // -----------------------------------------------------------------
549   std::string
550   Url::getPort() const
551   {
552     return m_impl->getPort();
553   }
554
555
556   // -----------------------------------------------------------------
557   std::string
558   Url::getPathName(EEncoding eflag) const
559   {
560     return m_impl->getPathName(eflag);
561   }
562
563
564   // -----------------------------------------------------------------
565   std::string
566   Url::getPathParams() const
567   {
568     return m_impl->getPathParams();
569   }
570
571
572   // -----------------------------------------------------------------
573   zypp::url::ParamVec
574   Url::getPathParamsVec() const
575   {
576     return m_impl->getPathParamsVec();
577   }
578
579
580   // -----------------------------------------------------------------
581   zypp::url::ParamMap
582   Url::getPathParamsMap(EEncoding eflag) const
583   {
584     return m_impl->getPathParamsMap(eflag);
585   }
586
587
588   // -----------------------------------------------------------------
589   std::string
590   Url::getPathParam(const std::string &param, EEncoding eflag) const
591   {
592     return m_impl->getPathParam(param, eflag);
593   }
594
595
596   // -----------------------------------------------------------------
597   zypp::url::ParamVec
598   Url::getQueryStringVec() const
599   {
600     return m_impl->getQueryStringVec();
601   }
602
603
604   // -----------------------------------------------------------------
605   zypp::url::ParamMap
606   Url::getQueryStringMap(EEncoding eflag) const
607   {
608     return m_impl->getQueryStringMap(eflag);
609   }
610
611
612   // -----------------------------------------------------------------
613   std::string
614   Url::getQueryParam(const std::string &param, EEncoding eflag) const
615   {
616     return m_impl->getQueryParam(param, eflag);
617   }
618
619
620   // -----------------------------------------------------------------
621   void
622   Url::setScheme(const std::string &scheme)
623   {
624     if(scheme == m_impl->getScheme())
625     {
626       return;
627     }
628     if( m_impl->isKnownScheme(scheme))
629     {
630       m_impl->setScheme(scheme);
631       return;
632     }
633
634     UrlRef url = g_urlSchemeRepository().getUrlByScheme(scheme);
635     if( !url)
636     {
637       url.reset( new UrlBase());
638     }
639     url->init(
640       scheme,
641       m_impl->getAuthority(),
642       m_impl->getPathData(),
643       m_impl->getQueryString(),
644       m_impl->getFragment(zypp::url::E_ENCODED)
645     );
646     m_impl = url;
647   }
648
649
650   // -----------------------------------------------------------------
651   void
652   Url::setAuthority(const std::string &authority)
653   {
654     m_impl->setAuthority(authority);
655   }
656
657
658   // -----------------------------------------------------------------
659   void
660   Url::setPathData(const std::string &pathdata)
661   {
662     m_impl->setPathData(pathdata);
663   }
664
665
666   // -----------------------------------------------------------------
667   void
668   Url::setQueryString(const std::string &querystr)
669   {
670     m_impl->setQueryString(querystr);
671   }
672
673
674   // -----------------------------------------------------------------
675   void
676   Url::setFragment(const std::string &fragment, EEncoding eflag)
677   {
678     m_impl->setFragment(fragment, eflag);
679   }
680
681
682   // -----------------------------------------------------------------
683   void
684   Url::setUsername(const std::string &user,
685                    EEncoding         eflag)
686   {
687     m_impl->setUsername(user, eflag);
688   }
689
690
691   // -----------------------------------------------------------------
692   void
693   Url::setPassword(const std::string &pass,
694                    EEncoding         eflag)
695   {
696     m_impl->setPassword(pass, eflag);
697   }
698
699
700   // -----------------------------------------------------------------
701   void
702   Url::setHost(const std::string &host)
703   {
704     m_impl->setHost(host);
705   }
706
707
708   // -----------------------------------------------------------------
709   void
710   Url::setPort(const std::string &port)
711   {
712     m_impl->setPort(port);
713   }
714
715
716   // -----------------------------------------------------------------
717   void
718   Url::setPathName(const std::string &path,
719                    EEncoding         eflag)
720   {
721     m_impl->setPathName(path, eflag);
722   }
723
724
725   // -----------------------------------------------------------------
726   void
727   Url::setPathParams(const std::string &params)
728   {
729     m_impl->setPathParams(params);
730   }
731
732
733   // -----------------------------------------------------------------
734   void
735   Url::setPathParamsVec(const zypp::url::ParamVec &pvec)
736   {
737     m_impl->setPathParamsVec(pvec);
738   }
739
740
741   // -----------------------------------------------------------------
742   void
743   Url::setPathParamsMap(const zypp::url::ParamMap &pmap)
744   {
745     m_impl->setPathParamsMap(pmap);
746   }
747
748
749   // -----------------------------------------------------------------
750   void
751   Url::setPathParam(const std::string &param, const std::string &value)
752   {
753     m_impl->setPathParam(param, value);
754   }
755
756
757   // -----------------------------------------------------------------
758   void
759   Url::setQueryStringVec(const zypp::url::ParamVec &pvec)
760   {
761     m_impl->setQueryStringVec(pvec);
762   }
763
764
765   // -----------------------------------------------------------------
766   void
767   Url::setQueryStringMap(const zypp::url::ParamMap &pmap)
768   {
769     m_impl->setQueryStringMap(pmap);
770   }
771
772   // -----------------------------------------------------------------
773   void
774   Url::setQueryParam(const std::string &param, const std::string &value)
775   {
776     m_impl->setQueryParam(param, value);
777   }
778
779   // -----------------------------------------------------------------
780   ViewOptions
781   Url::getViewOptions() const
782   {
783     return m_impl->getViewOptions();
784   }
785
786   // -----------------------------------------------------------------
787   void
788   Url::setViewOptions(const ViewOptions &vopts)
789   {
790     m_impl->setViewOptions(vopts);
791   }
792
793   // -----------------------------------------------------------------
794   std::ostream & operator<<( std::ostream & str, const Url & url )
795   {
796     return str << url.asString();
797   }
798
799   bool operator<( const Url &lhs, const Url &rhs )
800   {
801     return (lhs.asCompleteString() < rhs.asCompleteString());
802   }
803
804   bool operator==( const Url &lhs, const Url &rhs )
805   {
806     return (lhs.asCompleteString() == rhs.asCompleteString());
807   }
808
809   bool operator!=( const Url &lhs, const Url &rhs )
810   {
811     return (lhs.asCompleteString() != rhs.asCompleteString());
812   }
813
814   ////////////////////////////////////////////////////////////////////
815 } // namespace zypp
816 //////////////////////////////////////////////////////////////////////
817 /*
818 ** vim: set ts=2 sts=2 sw=2 ai et:
819 */