00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #ifndef MISC_URI_H
00028 #define MISC_URI_H
00029
00030
00031
00032 #include <map>
00033 #include <string>
00034
00035
00036
00037 namespace misc
00038 {
00039
00040
00041
00043
00046 class URI
00047 {
00048 public:
00050 typedef std::map<std::string, std::string> parameters_t;
00051
00053 URI() : m_uri(), m_scheme(), m_contents(), m_authority(), m_path(),
00054 m_query(), m_hostname(), m_port(0), m_username(), m_password(),
00055 m_parameters() { }
00057 URI(std::string const &uri) : m_uri(), m_scheme(), m_contents(),
00058 m_authority(), m_path(), m_query(), m_hostname(), m_port(0),
00059 m_username(), m_password(), m_parameters() { assign(uri); }
00061 URI(char const *uri) : m_uri(), m_scheme(), m_contents(),
00062 m_authority(), m_path(), m_query(), m_hostname(), m_port(0),
00063 m_username(), m_password(), m_parameters() { assign(uri); }
00065 URI(URI const &uri) : m_uri(uri.m_uri), m_scheme(uri.m_scheme),
00066 m_contents(uri.m_contents), m_authority(uri.m_authority),
00067 m_path(uri.m_path), m_query(uri.m_query),
00068 m_hostname(uri.m_hostname), m_port(uri.m_port),
00069 m_username(uri.m_username), m_password(uri.m_password),
00070 m_parameters(uri.m_parameters) { }
00072 URI &operator=(URI const &right);
00074 bool operator==(URI const &right)
00075 { return (m_uri == right.m_uri); }
00077 bool operator!=(URI const &right)
00078 { return !(operator==(right)); }
00079
00081
00087 bool assign(std::string const &uri)
00088 { clear(); return parse_uri(uri.begin(), uri.end()); }
00090 bool assign(char const *uri)
00091 { clear(); return parse_uri(uri, uri + strlen(uri)); }
00092
00094 void clear();
00095
00097 std::string const &uri() const { return m_uri; }
00098
00100 std::string const &scheme() const { return m_scheme; }
00102 std::string const &contents() const { return m_contents; }
00103
00105 std::string const &authority() const { return m_authority; }
00107 std::string const &path() const { return m_path; }
00109 std::string const &query() const { return m_query; }
00110
00112 std::string const &hostname() const { return m_hostname; }
00114 uint16_t port() const { return m_port; }
00116 std::string const &username() const { return m_username; }
00118 std::string const &password() const { return m_password; }
00119
00121 parameters_t const ¶meters() const { return m_parameters; }
00122 private:
00123 std::string m_uri;
00124
00125 std::string m_scheme;
00126 std::string m_contents;
00127
00128 std::string m_authority;
00129 std::string m_path;
00130 std::string m_query;
00131
00132 std::string m_hostname;
00133 uint16_t m_port;
00134 std::string m_username;
00135 std::string m_password;
00136
00137 parameters_t m_parameters;
00138
00139 template <typename T> bool parse_uri(T beg, T end)
00140 {
00141 T send = end;
00142
00143 for (T it = beg; it != end; ++it)
00144 {
00145 if (*it == ':')
00146 {
00147 send = it;
00148
00149 if (++it == end)
00150 return false;
00151
00152 break;
00153 }
00154 }
00155
00156 if (send == end)
00157 return false;
00158
00159 if (!parse_contents(send + 1, end))
00160 return false;
00161
00162 m_scheme.assign(beg, send);
00163 m_contents.assign(send + 1, end);
00164 m_uri.assign(beg, end);
00165
00166 return true;
00167 }
00168
00169 template <typename T> bool parse_contents(T beg, T end)
00170 {
00171 if (*beg == '/' && (beg + 1) != end && *(beg + 1) == '/')
00172 beg += 2;
00173 else
00174 return true;
00175
00176 T aend = end, pend = end;
00177
00178 for (T it = beg; it != end; ++it)
00179 {
00180 if (*it == '/')
00181 {
00182 if (aend != end)
00183 return false;
00184
00185 aend = it;
00186 }
00187 else if (*it == '?')
00188 {
00189 if (aend == end)
00190 return false;
00191
00192 if (it + 1 == end)
00193 pend = end = it;
00194 else
00195 pend = it;
00196 break;
00197 }
00198 }
00199
00200 if (beg != aend && !parse_authority(beg, aend))
00201 return false;
00202
00203 if (pend != end && (pend + 1) != end &&
00204 !parse_query(pend + 1, end))
00205 return false;
00206
00207 if (beg != aend)
00208 m_authority.assign(beg, aend);
00209 if (aend != end)
00210 m_path.assign(aend, pend);
00211 if (pend != end)
00212 m_query.assign(pend + 1, end);
00213 return true;
00214 }
00215
00216 template <typename T> bool parse_authority(T beg, T end)
00217 {
00218 T cend = beg;
00219
00220 for (T it = beg; it != end; ++it)
00221 {
00222 if (*it == '@')
00223 {
00224 cend = it;
00225
00226 if (++it == end)
00227 return false;
00228
00229 break;
00230 }
00231 }
00232
00233 if (cend != beg)
00234 return parse_credentials(beg, cend, end);
00235 else
00236 return parse_host(cend, end);
00237 }
00238
00239 template <typename T> bool parse_credentials(T beg, T end,
00240 T hend)
00241 {
00242 T uend = end;
00243
00244 for (T it = beg; it != end; ++it)
00245 {
00246 if (*it == ':')
00247 {
00248 if (it == beg)
00249 return false;
00250
00251 if (it + 1 == end)
00252 uend = end = it;
00253 else
00254 uend = it;
00255 break;
00256 }
00257 }
00258
00259 if (!parse_host(end + 1, hend))
00260 return false;
00261
00262 m_username.assign(beg, uend);
00263 if (uend != end)
00264 m_password.assign(uend + 1, end);
00265
00266 return true;
00267 }
00268
00269 template <typename T> bool parse_host(T beg, T end)
00270 {
00271 T nend = end;
00272
00273 for (T it = beg; it != end; ++it)
00274 {
00275 if (*it == ':')
00276 {
00277 if (it == beg)
00278 return false;
00279
00280 if (it + 1 == end)
00281 nend = end = it;
00282 else
00283 nend = it;
00284 break;
00285 }
00286 }
00287
00288 m_hostname.assign(beg, nend);
00289 if (nend != end)
00290 {
00291 std::string port(nend + 1, end);
00292 m_port = atoi(port.c_str());
00293 }
00294
00295 return true;
00296 }
00297
00298 template <typename T> bool parse_query(T beg, T end)
00299 {
00300 while (beg != end && *beg == '&')
00301 ++beg;
00302
00303 T pbeg = beg;
00304
00305 for (T it = beg; it != end; ++it)
00306 {
00307 if (*it == '&')
00308 {
00309 if (!parse_parameter(pbeg, it))
00310 return false;
00311
00312 while (it != end && *it == '&')
00313 ++it;
00314
00315 pbeg = it;
00316
00317 if (it == end)
00318 break;
00319 }
00320 }
00321
00322 if (end - pbeg >= 1 && !parse_parameter(pbeg, end))
00323 return false;
00324
00325 return true;
00326 }
00327
00328 template <typename T> bool parse_parameter(T beg, T end)
00329 {
00330 T nend = end;
00331
00332 for (T it = beg; it != end; ++it)
00333 {
00334 if (*it == '=')
00335 {
00336 if (it == beg)
00337 return false;
00338
00339 if (it + 1 == end)
00340 nend = end = it;
00341 else
00342 nend = it;
00343 break;
00344 }
00345 }
00346
00347 if (nend != end)
00348 m_parameters[std::string(beg, nend)] =
00349 std::string(nend + 1, end);
00350 else
00351 m_parameters[std::string(beg, nend)] = "";
00352
00353 return true;
00354 }
00355 };
00356
00357
00358
00359 }
00360
00361
00362
00363 #endif