Yet Another HTTP Library
yahttp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
url.hpp
Go to the documentation of this file.
1 #ifndef _YAHTTP_URL_HPP
2 #define _YAHTTP_URL_HPP 1
3 #include <sstream>
4 #include <string>
5 
6 #include "utility.hpp"
7 
8 #ifndef YAHTTP_MAX_URL_LENGTH
9 #define YAHTTP_MAX_URL_LENGTH 2048
10 #endif
11 
12 namespace YaHTTP {
14  class URL {
15  private:
16  bool parseSchema(const std::string& url, size_t &pos) {
17  size_t pos1;
18  if (pos >= url.size()) return false; // no data
19  if ( (pos1 = url.find_first_of(":",pos)) == std::string::npos ) return false; // schema is mandatory
20  protocol = url.substr(pos, pos1-pos);
21  if (protocol == "http") port = 80;
22  if (protocol == "https") port = 443;
23  pos = pos1+1; // after :
24  if (url.compare(pos, 2, "//") == 0) {
25  pathless = false; // if this is true we put rest into parameters
26  pos += 2;
27  }
28  return true;
29  }; //<! parse schema/protocol part
30 
31  bool parseHost(const std::string& url, size_t &pos) {
32  size_t pos1;
33  if (pos >= url.size()) return true; // no data
34  if ( (pos1 = url.find_first_of("/", pos)) == std::string::npos ) {
35  host = url.substr(pos);
36  path = "/";
37  pos = url.size();
38  } else {
39  host = url.substr(pos, pos1-pos);
40  pos = pos1;
41  }
42  if ( (pos1 = host.find_first_of(":")) != std::string::npos ) {
43  std::istringstream tmp(host.substr(pos1+1));
44  tmp >> port;
45  host = host.substr(0, pos1);
46  }
47  return true;
48  }; //<! parse host and port
49 
50  bool parseUserPass(const std::string& url, size_t &pos) {
51  size_t pos1,pos2;
52  if (pos >= url.size()) return true; // no data
53 
54  if ( (pos1 = url.find_first_of("@",pos)) == std::string::npos ) return true; // no userinfo
55  pos2 = url.find_first_of(":",pos);
56 
57  if (pos2 != std::string::npos) { // comes with password
58  username = url.substr(pos, pos2 - pos);
59  password = url.substr(pos2+1, pos1 - pos2 - 1);
61  } else {
62  username = url.substr(pos+1, pos1 - pos);
63  }
64  pos = pos1+1;
66  return true;
67  }; //<! parse possible username and password
68 
69  bool parsePath(const std::string& url, size_t &pos) {
70  size_t pos1;
71  if (pos >= url.size()) return true; // no data
72  if (url[pos] != '/') return false; // not an url
73  if ( (pos1 = url.find_first_of("?", pos)) == std::string::npos ) {
74  path = url.substr(pos);
75  pos = url.size();
76  } else {
77  path = url.substr(pos, pos1-pos);
78  pos = pos1;
79  }
80  return true;
81  }; //<! parse path component
82 
83  bool parseParameters(const std::string& url, size_t &pos) {
84  size_t pos1;
85  if (pos >= url.size()) return true; // no data
86  if (url[pos] == '#') return true; // anchor starts here
87  if (url[pos] != '?') return false; // not a parameter
88  if ( (pos1 = url.find_first_of("#", pos)) == std::string::npos ) {
89  parameters = url.substr(pos+1);;
90  pos = url.size();
91  } else {
92  parameters = url.substr(pos+1, pos1-pos-1);
93  pos = pos1;
94  }
95  if (parameters.size()>0 && *(parameters.end()-1) == '&') parameters.resize(parameters.size()-1);
96  return true;
97  }; //<! parse url parameters
98 
99  bool parseAnchor(const std::string& url, size_t &pos) {
100  if (pos >= url.size()) return true; // no data
101  if (url[pos] != '#') return false; // not anchor
102  anchor = url.substr(pos+1);
103  return true;
104  }; //<! parse anchor
105 
106  void initialize() {
107  protocol = ""; host = ""; port = 0; username = ""; password = ""; path = ""; parameters = ""; anchor =""; pathless = true;
108  }; //<! initialize to empty URL
109 
110  public:
111  std::string to_string() const {
112  std::string tmp;
113  std::ostringstream oss;
114 
115  if (protocol.empty() == false) {
116  oss << protocol << ":";
117  if (host.empty() == false) {
118  oss << "//";
119  }
120  }
121 
122  if (username.empty() == false) {
123  if (password.empty() == false)
124  oss << Utility::encodeURL(username) << ":" << Utility::encodeURL(password) << "@";
125  else
126  oss << Utility::encodeURL(username) << "@";
127  }
128  if (host.empty() == false)
129  oss << host;
130  if (!(protocol == "http" && port == 80) &&
131  !(protocol == "https" && port == 443) &&
132  port > 0)
133  oss << ":" << port;
134 
135  oss << path;
136  if (parameters.empty() == false) {
137  if (!pathless)
138  oss << "?";
139  oss << parameters;
140  }
141  if (anchor.empty() == false)
142  oss << "#" << anchor;
143  return oss.str();
144  }; //<! convert this URL to string
145 
146  std::string protocol; //<! schema/protocol
147  std::string host; //<! host
148  int port; //<! port
149  std::string username; //<! username
150  std::string password; //<! password
151  std::string path; //<! path
152  std::string parameters; //<! url parameters
153  std::string anchor; //<! anchor
154  bool pathless; //<! whether this url has no path
155 
156  URL() { initialize(); }; //<! construct empty url
157  URL(const std::string& url) {
158  parse(url);
159  }; //<! calls parse with url
160 
161  URL(const char *url) {
162  parse(std::string(url));
163  }; //<! calls parse with url
164 
165  bool parse(const std::string& url) {
166  // setup
167  initialize();
168 
169  if (url.size() > YAHTTP_MAX_URL_LENGTH) return false;
170  size_t pos = 0;
171  if (*(url.begin()) != '/') { // full url?
172  if (parseSchema(url, pos) == false) return false;
173  if (pathless) {
174  parameters = url.substr(pos);
175  return true;
176  }
177  if (parseUserPass(url, pos) == false) return false;
178  if (parseHost(url, pos) == false) return false;
179  }
180  if (parsePath(url, pos) == false) return false;
181  if (parseParameters(url, pos) == false) return false;
182  return parseAnchor(url, pos);
183  }; //<! parse various formats of urls ranging from http://example.com/foo?bar=baz into data:base64:d089swt64wt...
184 
185  friend std::ostream & operator<<(std::ostream& os, const URL& url) {
186  os<<url.to_string();
187  return os;
188  };
189  };
190 };
191 #endif
std::string password
Definition: url.hpp:150
static std::string encodeURL(const std::string &component, bool asUrl=true)
Definition: utility.hpp:233
bool parse(const std::string &url)
Definition: url.hpp:165
std::string host
Definition: url.hpp:147
bool pathless
Definition: url.hpp:154
static std::string decodeURL(const std::string &component)
Definition: utility.hpp:204
bool parsePath(const std::string &url, size_t &pos)
Definition: url.hpp:69
bool parseSchema(const std::string &url, size_t &pos)
Definition: url.hpp:16
bool parseAnchor(const std::string &url, size_t &pos)
Definition: url.hpp:99
int port
Definition: url.hpp:148
URL(const char *url)
Definition: url.hpp:161
friend std::ostream & operator<<(std::ostream &os, const URL &url)
Definition: url.hpp:185
std::string parameters
Definition: url.hpp:152
bool parseParameters(const std::string &url, size_t &pos)
Definition: url.hpp:83
bool parseUserPass(const std::string &url, size_t &pos)
Definition: url.hpp:50
std::string protocol
Definition: url.hpp:144
#define YAHTTP_MAX_URL_LENGTH
Definition: url.hpp:9
URL()
Definition: url.hpp:156
std::string anchor
Definition: url.hpp:153
std::string path
Definition: url.hpp:151
bool parseHost(const std::string &url, size_t &pos)
Definition: url.hpp:31
URL(const std::string &url)
Definition: url.hpp:157
std::string username
Definition: url.hpp:149
std::string to_string() const
Definition: url.hpp:111
Definition: url.hpp:14
void initialize()
Definition: url.hpp:106