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

Generated on Thu Jul 6 00:07:28 2006 for zypp by  doxygen 1.4.6