00001 #ifndef hpp_CPP_URLHandler_CPP_hpp
00002 #define hpp_CPP_URLHandler_CPP_hpp
00003
00004
00005 #include "../Strings/Strings.hpp"
00006
00008 namespace Network
00009 {
00014 class URL
00015 {
00016
00017 public:
00019 typedef Strings::FastString String;
00020
00021
00022 protected:
00024 String scheme;
00026 String authority;
00028 String path;
00030 String query;
00032 String fragment;
00033
00034
00035 private:
00037 bool splitURI(const String & inputURL);
00039 void normalizePath(String & pathToNormalize) const;
00040
00041
00042 public:
00044 inline bool isValid() { return authority.getLength() > 0; }
00047 inline String asURI(const String & defaultScheme = "") const
00048 {
00049 String schemeTmp = scheme.getLength() ? scheme : defaultScheme;
00050 schemeTmp += "://" + authority + ((path.getLength() && path[0] != '/') ? "/" : "") + path;
00051 if (query.getLength()) schemeTmp += "?" + query;
00052 if (fragment.getLength()) schemeTmp += "#" + fragment;
00053 return schemeTmp;
00054 }
00056 inline URL appendRelativePath(String newPath) const
00057 {
00058 URL ret(scheme, authority, "");
00059
00060 int fragmentPos = newPath.reverseFind("#", newPath.getLength());
00061 if (fragmentPos != -1)
00062 {
00063 ret.fragment = newPath.midString(fragmentPos+1, newPath.getLength());
00064 newPath = newPath.midString(0, fragmentPos);
00065 }
00066 int queryPos = newPath.reverseFind("?", newPath.getLength());
00067 if (queryPos != -1)
00068 {
00069 ret.query = newPath.midString(queryPos+1, newPath.getLength());
00070 newPath = newPath.midString(0, queryPos);
00071 }
00072
00073
00074 newPath.findAndReplace("/./", "/", 0);
00075
00076 if (newPath[0] == '/') { ret.path = newPath; normalizePath(ret.path); return ret; }
00077
00078
00079 int lastSlashInNewPath = newPath.reverseFind('/', newPath.getLength()) + 1;
00080 bool isFile = isFile = newPath.Find('.', lastSlashInNewPath) != -1;
00081
00082
00083 String curPath = path;
00084 int lastSlash = curPath.reverseFind('/', curPath.getLength());
00085 if (lastSlash != -1) curPath = curPath.midString(0, lastSlash);
00086
00087
00088
00089 int upPos = newPath.Find("../");
00090 while (upPos != -1)
00091 {
00092
00093 lastSlash = curPath.reverseFind('/', curPath.getLength());
00094 if (lastSlash != -1) curPath = curPath.midString(0, lastSlash);
00095 newPath = newPath.midString(upPos + 3, newPath.getLength());
00096 upPos = newPath.Find("../");
00097 }
00098
00099
00100 ret.path = curPath + (curPath.getLength() ? "/" : "") + newPath;
00101 ret.path += (!isFile && ret.path[ret.path.getLength() - 1] != '/') ? "/" : "";
00102 if (ret.path[0] != '/') ret.path = "/" + ret.path;
00103
00104 normalizePath(ret.path);
00105 return ret;
00106 }
00108 static String escapedURI(const String & inputURL);
00109
00111 inline uint16 stripPortFromAuthority(uint16 defaultPortValue)
00112 {
00113 int portPos = authority.reverseFind(':', authority.getLength());
00114 if (portPos != -1)
00115 {
00116 String portValue = authority.midString(portPos+1, authority.getLength());
00117 authority = authority.midString(0, portPos);
00118 portPos = defaultPortValue;
00119 portValue.Scan("%d", &portPos);
00120 if (portPos < 0) portPos = 0;
00121 if (portPos > 65535) portPos = 65535;
00122 return (uint16)portPos;
00123 }
00124 return defaultPortValue;
00125 }
00126
00127
00128
00129 public:
00131 inline const String & getAuthority() const { return authority; }
00133 inline const String & getScheme() const { return scheme; }
00135 inline const String & getPath() const { return path; }
00137 inline const String & getQuery() const { return query; }
00139 inline const String & getFragment() const { return fragment; }
00140
00141
00142
00143 public:
00145 URL() {}
00147 URL(const String & inputURL, const String & defaultScheme = "")
00148 {
00149 splitURI(inputURL);
00150 if (!scheme.getLength()) scheme = defaultScheme;
00151 }
00153 URL(const String & _scheme, const String & _authority, const String & _path, const String & _query = "", const String & _fragment = "")
00154 : scheme(_scheme), authority(_authority), path(_path), query(_query), fragment(_fragment) { }
00155 };
00156 }
00157
00158 #endif