Url.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <zypp/Url.h>
00013 #include <zypp/base/Gettext.h>
00014 #include <zypp/base/String.h>
00015 #include <stdexcept>
00016 
00017 
00019 namespace zypp
00020 { 
00021 
00022 
00023   using namespace zypp::url;
00024 
00025 
00026   // -----------------------------------------------------------------
00027   /*
00028    * url       = [scheme:] [//authority] /path [?query] [#fragment]
00029    */
00030   #define RX_SPLIT_URL                       "^(([^:/?#]+):)?" \
00031                                              "(//([^/?#]*))?"  \
00032                                              "([^?#]*)"        \
00033                                              "([?]([^#]*))?"   \
00034                                              "(#(.*))?"
00035 
00036 
00038   namespace
00039   { 
00040 
00041 
00042     // ---------------------------------------------------------------
00043     class LDAPUrl: public UrlBase
00044     {
00045     public:
00046       LDAPUrl(): UrlBase()
00047       {
00048         configure();
00049       }
00050 
00051       LDAPUrl(const LDAPUrl &url): UrlBase(url)
00052       {}
00053 
00054       virtual UrlBase *
00055       clone() const
00056       {
00057         return new LDAPUrl(*this);
00058       }
00059 
00060       virtual UrlSchemes
00061       getKnownSchemes() const
00062       {
00063         UrlSchemes schemes(2);
00064         schemes[0] = "ldap";
00065         schemes[1] = "ldaps";
00066         return schemes;
00067       }
00068 
00069       virtual void
00070       configure()
00071       {
00072         config("sep_pathparams",  "");
00073 
00074         config("psep_querystr",   "?");
00075         config("vsep_querystr",   "");
00076 
00077         // host is required (isValid=>false)
00078         // but not mandatory (see RFC 2255),
00079         // that is, accept empty host.
00080         config("require_host",    "y");
00081 
00082         // not allowed here
00083         config("rx_username",     "");
00084         config("rx_password",     "");
00085         config("rx_fragment",     "");
00086         config("rx_pathparams",   "");
00087       }
00088 
00089       virtual zypp::url::ParamMap
00090       getQueryStringMap(zypp::url::EEncoding eflag) const
00091       {
00092         static const char * const keys[] = {
00093           "attrs", "scope", "filter", "exts", NULL
00094         };
00095         zypp::url::ParamMap pmap;
00096         zypp::url::ParamVec pvec( getQueryStringVec());
00097         if( pvec.size() <= 4)
00098         {
00099           for(size_t i=0; i<pvec.size(); i++)
00100           {
00101             if(eflag == zypp::url::E_ENCODED)
00102               pmap[keys[i]] = pvec[i];
00103             else
00104               pmap[keys[i]] = zypp::url::decode( pvec[i]);
00105           }
00106         }
00107         else
00108         {
00109           ZYPP_THROW(url::UrlNotSupportedException(
00110             _("Invalid LDAP URL query string")
00111           ));
00112         }
00113         return pmap;
00114       }
00115 
00116       virtual void
00117       setQueryStringMap(const zypp::url::ParamMap &pmap)
00118       {
00119         static const char * const keys[] = {
00120           "attrs", "scope", "filter", "exts", NULL
00121         };
00122 
00123         // remove psep ("?") from safe chars
00124         std::string join_safe;
00125         std::string safe(config("safe_querystr"));
00126         std::string psep(config("psep_querystr"));
00127         for(std::string::size_type i=0; i<safe.size(); i++)
00128         {
00129           if( psep.find(safe[i]) == std::string::npos)
00130             join_safe.append(1, safe[i]);
00131         }
00132 
00133         zypp::url::ParamVec pvec(4);
00134         zypp::url::ParamMap::const_iterator p;
00135         for(p=pmap.begin(); p!=pmap.end(); ++p)
00136         {
00137           bool found=false;
00138           for(size_t i=0; i<4; i++)
00139           {
00140             if(p->first == keys[i])
00141             {
00142               found=true;
00143               pvec[i] = zypp::url::encode(p->second, join_safe);
00144             }
00145           }
00146           if( !found)
00147           {
00148             ZYPP_THROW(url::UrlNotSupportedException(
00149               str::form(_("Invalid LDAP URL query parameter '%s'"),
00150                           p->first.c_str())
00151             ));
00152           }
00153         }
00154         setQueryStringVec(pvec);
00155       }
00156     };
00157 
00158 
00159     // ---------------------------------------------------------------
00160     // FIXME: hmm..
00161     class UrlByScheme
00162     {
00163     private:
00164       typedef std::map<std::string,UrlRef> UrlBySchemeMap;
00165       UrlBySchemeMap urlByScheme;
00166 
00167     public:
00168       UrlByScheme()
00169       {
00170         UrlRef ref;
00171 
00172         // =====================================
00173         ref.reset( new LDAPUrl());
00174         addUrlByScheme("ldap", ref);
00175         addUrlByScheme("ldaps", ref);
00176 
00177 
00178         // =====================================
00179         ref.reset( new UrlBase());
00180         ref->config("with_authority",   "n");   // disallow host,...
00181         ref->config("require_pathname", "m");   // path is mandatory
00182         addUrlByScheme("hd",     ref);
00183         addUrlByScheme("cd",     ref);
00184         addUrlByScheme("dvd",    ref);
00185         addUrlByScheme("dir",    ref);
00186         addUrlByScheme("iso",    ref);
00187 
00188         // don't show empty authority
00189         ref->setViewOptions( zypp::url::ViewOption::DEFAULTS -
00190                              zypp::url::ViewOption::EMPTY_AUTHORITY);
00191         addUrlByScheme("mailto", ref);
00192         addUrlByScheme("urn",    ref);
00193 
00194         // RFC1738, 3.10: may contain a host
00195         ref->config("with_authority",   "y");   // allow host,
00196         ref->config("with_port",        "n");   // but no port,
00197         ref->config("rx_username",      "");    // username or
00198         ref->config("rx_password",      "");    // password ...
00199         addUrlByScheme("file",   ref);
00200 
00201         // =====================================
00202         ref.reset( new UrlBase());
00203         ref->config("require_host",     "m");   // host is mandatory
00204         addUrlByScheme("nfs",    ref);
00205         addUrlByScheme("smb",    ref);
00206         addUrlByScheme("cifs",   ref);
00207         addUrlByScheme("http",   ref);
00208         addUrlByScheme("https",  ref);
00209         ref->config("path_encode_slash2", "y"); // always encode 2. slash
00210         addUrlByScheme("ftp",    ref);
00211         addUrlByScheme("sftp",   ref);
00212       }
00213 
00214       bool
00215       addUrlByScheme(const std::string &scheme,
00216                      UrlRef            urlImpl)
00217       {
00218         if( urlImpl && urlImpl->isValidScheme(scheme))
00219         {
00220           UrlRef ref(urlImpl);
00221           ref->clear();
00222           urlByScheme[str::toLower(scheme)] = ref;
00223           return true;
00224         }
00225         return false;
00226       }
00227 
00228       UrlRef
00229       getUrlByScheme(const std::string &scheme) const
00230       {
00231         UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme)));
00232         if( i != urlByScheme.end())
00233         {
00234           return i->second;
00235         }
00236         return UrlRef();
00237       }
00238 
00239       bool
00240       isRegisteredScheme(const std::string &scheme) const
00241       {
00242         return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end();
00243       }
00244 
00245       UrlSchemes
00246       getRegisteredSchemes() const
00247       {
00248         UrlBySchemeMap::const_iterator i(urlByScheme.begin());
00249         UrlSchemes                     schemes;
00250 
00251         schemes.reserve(urlByScheme.size());
00252         for( ; i != urlByScheme.end(); ++i)
00253         {
00254           schemes.push_back(i->first);
00255         }
00256         return schemes;
00257       }
00258     };
00259 
00260 
00261     // ---------------------------------------------------------------
00262     UrlByScheme g_urlSchemeRepository;
00263 
00264 
00266   } // anonymous namespace
00268 
00269 
00270   // -----------------------------------------------------------------
00271   Url::~Url()
00272   {
00273   }
00274 
00275 
00276   // -----------------------------------------------------------------
00277   Url::Url()
00278     : m_impl( new UrlBase())
00279   {
00280   }
00281 
00282 
00283   // -----------------------------------------------------------------
00284   Url::Url(const Url &url)
00285     : m_impl( url.m_impl)
00286   {
00287     if( !m_impl)
00288     {
00289       ZYPP_THROW(url::UrlException(
00290         _("Unable to clone Url object")
00291       ));
00292     }
00293   }
00294 
00295 
00296   // -----------------------------------------------------------------
00297   Url::Url(const zypp::url::UrlRef &url)
00298     : m_impl( url)
00299   {
00300     if( !m_impl)
00301     {
00302       ZYPP_THROW(url::UrlException(
00303         _("Invalid empty Url object reference")
00304       ));
00305     }
00306   }
00307 
00308 
00309   // -----------------------------------------------------------------
00310   Url::Url(const std::string &encodedUrl)
00311     : m_impl( parseUrl(encodedUrl))
00312   {
00313     if( !m_impl)
00314     {
00315       ZYPP_THROW(url::UrlParsingException(
00316         _("Unable to parse Url components")
00317       ));
00318     }
00319   }
00320 
00321 
00322   // -----------------------------------------------------------------
00323   Url&
00324   Url::operator = (const std::string &encodedUrl)
00325   {
00326     UrlRef url( parseUrl(encodedUrl));
00327     if( !url)
00328     {
00329       ZYPP_THROW(url::UrlParsingException(
00330         _("Unable to parse Url components")
00331       ));
00332     }
00333     m_impl = url;
00334     return *this;
00335   }
00336 
00337 
00338   // -----------------------------------------------------------------
00339   Url&
00340   Url::operator = (const Url &url)
00341   {
00342     m_impl = url.m_impl;
00343     return *this;
00344   }
00345 
00346 
00347   // -----------------------------------------------------------------
00348   // static
00349   bool
00350   Url::registerScheme(const std::string &scheme,
00351                       UrlRef            urlImpl)
00352   {
00353     return g_urlSchemeRepository.addUrlByScheme(scheme, urlImpl);
00354   }
00355 
00356 
00357   // -----------------------------------------------------------------
00358   // static
00359   UrlRef
00360   Url::parseUrl(const std::string &encodedUrl)
00361   {
00362     UrlRef      url;
00363     str::smatch out;
00364     bool        ret = false;
00365 
00366     try
00367     {
00368       str::regex  rex(RX_SPLIT_URL);
00369       ret = str::regex_match(encodedUrl, out, rex);
00370     }
00371     catch( ... )
00372     {}
00373 
00374     if(ret && out.size() == 10)
00375     {
00376       url = g_urlSchemeRepository.getUrlByScheme(out[2].str());
00377       if( !url)
00378       {
00379         url.reset( new UrlBase());
00380       }
00381       url->init(out[2].str(),
00382                 out[4].str(),
00383                 out[5].str(),
00384                 out[7].str(),
00385                 out[9].str());
00386     }
00387     return url;
00388   }
00389 
00390 
00391   // -----------------------------------------------------------------
00392   // static
00393   zypp::url::UrlSchemes
00394   Url::getRegisteredSchemes()
00395   {
00396     return g_urlSchemeRepository.getRegisteredSchemes();
00397   }
00398 
00399 
00400   // -----------------------------------------------------------------
00401   // static
00402   bool
00403   Url::isRegisteredScheme(const std::string &scheme)
00404   {
00405     return g_urlSchemeRepository.isRegisteredScheme(scheme);
00406   }
00407 
00408 
00409   // -----------------------------------------------------------------
00410   zypp::url::UrlSchemes
00411   Url::getKnownSchemes() const
00412   {
00413     return m_impl->getKnownSchemes();
00414   }
00415 
00416 
00417   // -----------------------------------------------------------------
00418   bool
00419   Url::isValidScheme(const std::string &scheme) const
00420   {
00421     return m_impl->isValidScheme(scheme);
00422   }
00423 
00424 
00425   // -----------------------------------------------------------------
00426   bool
00427   Url::isValid() const
00428   {
00429     return m_impl->isValid();
00430   }
00431 
00432 
00433   // -----------------------------------------------------------------
00434   std::string
00435   Url::asString() const
00436   {
00437     return m_impl->asString();
00438   }
00439 
00440 
00441   // -----------------------------------------------------------------
00442   std::string
00443   Url::asCompleteString() const
00444   {
00445     // make sure, all url components are included;
00446     // regardless of the current configuration...
00447     ViewOptions opts(getViewOptions() +
00448                      ViewOption::WITH_SCHEME +
00449                      ViewOption::WITH_USERNAME +
00450                      ViewOption::WITH_PASSWORD +
00451                      ViewOption::WITH_HOST +
00452                      ViewOption::WITH_PORT +
00453                      ViewOption::WITH_PATH_NAME +
00454                      ViewOption::WITH_PATH_PARAMS +
00455                      ViewOption::WITH_QUERY_STR +
00456                      ViewOption::WITH_FRAGMENT);
00457     return m_impl->asString(opts);
00458   }
00459 
00460 
00461   // -----------------------------------------------------------------
00462   std::string
00463   Url::asString(const ViewOptions &opts) const
00464   {
00465     return m_impl->asString(opts);
00466   }
00467 
00468 
00469   // -----------------------------------------------------------------
00470   std::string
00471   Url::getScheme() const
00472   {
00473     return m_impl->getScheme();
00474   }
00475 
00476 
00477   // -----------------------------------------------------------------
00478   std::string
00479   Url::getAuthority() const
00480   {
00481     return m_impl->getAuthority();
00482   }
00483 
00484   // -----------------------------------------------------------------
00485   std::string
00486   Url::getPathData() const
00487   {
00488     return m_impl->getPathData();
00489   }
00490 
00491 
00492   // -----------------------------------------------------------------
00493   std::string
00494   Url::getQueryString() const
00495   {
00496     return m_impl->getQueryString();
00497   }
00498 
00499 
00500   // -----------------------------------------------------------------
00501   std::string
00502   Url::getFragment(zypp::url::EEncoding eflag) const
00503   {
00504     return m_impl->getFragment(eflag);
00505   }
00506 
00507 
00508   // -----------------------------------------------------------------
00509   std::string
00510   Url::getUsername(EEncoding eflag) const
00511   {
00512     return m_impl->getUsername(eflag);
00513   }
00514 
00515 
00516   // -----------------------------------------------------------------
00517   std::string
00518   Url::getPassword(EEncoding eflag) const
00519   {
00520     return m_impl->getPassword(eflag);
00521   }
00522 
00523 
00524   // -----------------------------------------------------------------
00525   std::string
00526   Url::getHost(EEncoding eflag) const
00527   {
00528     return m_impl->getHost(eflag);
00529   }
00530 
00531 
00532   // -----------------------------------------------------------------
00533   std::string
00534   Url::getPort() const
00535   {
00536     return m_impl->getPort();
00537   }
00538 
00539 
00540   // -----------------------------------------------------------------
00541   std::string
00542   Url::getPathName(EEncoding eflag) const
00543   {
00544     return m_impl->getPathName(eflag);
00545   }
00546 
00547 
00548   // -----------------------------------------------------------------
00549   std::string
00550   Url::getPathParams() const
00551   {
00552     return m_impl->getPathParams();
00553   }
00554 
00555 
00556   // -----------------------------------------------------------------
00557   zypp::url::ParamVec
00558   Url::getPathParamsVec() const
00559   {
00560     return m_impl->getPathParamsVec();
00561   }
00562 
00563 
00564   // -----------------------------------------------------------------
00565   zypp::url::ParamMap
00566   Url::getPathParamsMap(EEncoding eflag) const
00567   {
00568     return m_impl->getPathParamsMap(eflag);
00569   }
00570 
00571 
00572   // -----------------------------------------------------------------
00573   std::string
00574   Url::getPathParam(const std::string &param, EEncoding eflag) const
00575   {
00576     return m_impl->getPathParam(param, eflag);
00577   }
00578 
00579 
00580   // -----------------------------------------------------------------
00581   zypp::url::ParamVec
00582   Url::getQueryStringVec() const
00583   {
00584     return m_impl->getQueryStringVec();
00585   }
00586 
00587 
00588   // -----------------------------------------------------------------
00589   zypp::url::ParamMap
00590   Url::getQueryStringMap(EEncoding eflag) const
00591   {
00592     return m_impl->getQueryStringMap(eflag);
00593   }
00594 
00595 
00596   // -----------------------------------------------------------------
00597   std::string
00598   Url::getQueryParam(const std::string &param, EEncoding eflag) const
00599   {
00600     return m_impl->getQueryParam(param, eflag);
00601   }
00602 
00603 
00604   // -----------------------------------------------------------------
00605   void
00606   Url::setScheme(const std::string &scheme)
00607   {
00608     if(scheme == m_impl->getScheme())
00609     {
00610       return;
00611     }
00612     if( m_impl->isKnownScheme(scheme))
00613     {
00614       m_impl->setScheme(scheme);
00615       return;
00616     }
00617 
00618     UrlRef url = g_urlSchemeRepository.getUrlByScheme(scheme);
00619     if( !url)
00620     {
00621       url.reset( new UrlBase());
00622     }
00623     url->init(
00624       scheme,
00625       m_impl->getAuthority(),
00626       m_impl->getPathData(),
00627       m_impl->getQueryString(),
00628       m_impl->getFragment(zypp::url::E_ENCODED)
00629     );
00630     m_impl = url;
00631   }
00632 
00633 
00634   // -----------------------------------------------------------------
00635   void
00636   Url::setAuthority(const std::string &authority)
00637   {
00638     m_impl->setAuthority(authority);
00639   }
00640 
00641 
00642   // -----------------------------------------------------------------
00643   void
00644   Url::setPathData(const std::string &pathdata)
00645   {
00646     m_impl->setPathData(pathdata);
00647   }
00648 
00649 
00650   // -----------------------------------------------------------------
00651   void
00652   Url::setQueryString(const std::string &querystr)
00653   {
00654     m_impl->setQueryString(querystr);
00655   }
00656 
00657 
00658   // -----------------------------------------------------------------
00659   void
00660   Url::setFragment(const std::string &fragment, EEncoding eflag)
00661   {
00662     m_impl->setFragment(fragment, eflag);
00663   }
00664 
00665 
00666   // -----------------------------------------------------------------
00667   void
00668   Url::setUsername(const std::string &user,
00669                    EEncoding         eflag)
00670   {
00671     m_impl->setUsername(user, eflag);
00672   }
00673 
00674 
00675   // -----------------------------------------------------------------
00676   void
00677   Url::setPassword(const std::string &pass,
00678                    EEncoding         eflag)
00679   {
00680     m_impl->setPassword(pass, eflag);
00681   }
00682 
00683 
00684   // -----------------------------------------------------------------
00685   void
00686   Url::setHost(const std::string &host)
00687   {
00688     m_impl->setHost(host);
00689   }
00690 
00691 
00692   // -----------------------------------------------------------------
00693   void
00694   Url::setPort(const std::string &port)
00695   {
00696     m_impl->setPort(port);
00697   }
00698 
00699 
00700   // -----------------------------------------------------------------
00701   void
00702   Url::setPathName(const std::string &path,
00703                    EEncoding         eflag)
00704   {
00705     m_impl->setPathName(path, eflag);
00706   }
00707 
00708 
00709   // -----------------------------------------------------------------
00710   void
00711   Url::setPathParams(const std::string &params)
00712   {
00713     m_impl->setPathParams(params);
00714   }
00715 
00716 
00717   // -----------------------------------------------------------------
00718   void
00719   Url::setPathParamsVec(const zypp::url::ParamVec &pvec)
00720   {
00721     m_impl->setPathParamsVec(pvec);
00722   }
00723 
00724 
00725   // -----------------------------------------------------------------
00726   void
00727   Url::setPathParamsMap(const zypp::url::ParamMap &pmap)
00728   {
00729     m_impl->setPathParamsMap(pmap);
00730   }
00731 
00732 
00733   // -----------------------------------------------------------------
00734   void
00735   Url::setPathParam(const std::string &param, const std::string &value)
00736   {
00737     m_impl->setPathParam(param, value);
00738   }
00739 
00740 
00741   // -----------------------------------------------------------------
00742   void
00743   Url::setQueryStringVec(const zypp::url::ParamVec &pvec)
00744   {
00745     m_impl->setQueryStringVec(pvec);
00746   }
00747 
00748 
00749   // -----------------------------------------------------------------
00750   void
00751   Url::setQueryStringMap(const zypp::url::ParamMap &pmap)
00752   {
00753     m_impl->setQueryStringMap(pmap);
00754   }
00755 
00756   // -----------------------------------------------------------------
00757   void
00758   Url::setQueryParam(const std::string &param, const std::string &value)
00759   {
00760     m_impl->setQueryParam(param, value);
00761   }
00762 
00763   // -----------------------------------------------------------------
00764   ViewOptions
00765   Url::getViewOptions() const
00766   {
00767     return m_impl->getViewOptions();
00768   }
00769 
00770   // -----------------------------------------------------------------
00771   void
00772   Url::setViewOptions(const ViewOptions &vopts)
00773   {
00774     m_impl->setViewOptions(vopts);
00775   }
00776 
00777   // -----------------------------------------------------------------
00778   std::ostream & operator<<( std::ostream & str, const Url & url )
00779   {
00780     return str << url.asString();
00781   }
00782 
00783 
00785 } // namespace zypp
00787 /*
00788 ** vim: set ts=2 sts=2 sw=2 ai et:
00789 */

Generated on Tue Nov 28 16:49:34 2006 for zypp by  doxygen 1.5.0