1 #ifndef SRC_NODE_URL_H_ 2 #define SRC_NODE_URL_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "node.h" 7 8 #include <string> 9 10 namespace node { 11 namespace url { 12 13 #define PARSESTATES(XX) \ 14 XX(kSchemeStart) \ 15 XX(kScheme) \ 16 XX(kNoScheme) \ 17 XX(kSpecialRelativeOrAuthority) \ 18 XX(kPathOrAuthority) \ 19 XX(kRelative) \ 20 XX(kRelativeSlash) \ 21 XX(kSpecialAuthoritySlashes) \ 22 XX(kSpecialAuthorityIgnoreSlashes) \ 23 XX(kAuthority) \ 24 XX(kHost) \ 25 XX(kHostname) \ 26 XX(kPort) \ 27 XX(kFile) \ 28 XX(kFileSlash) \ 29 XX(kFileHost) \ 30 XX(kPathStart) \ 31 XX(kPath) \ 32 XX(kCannotBeBase) \ 33 XX(kQuery) \ 34 XX(kFragment) 35 36 #define FLAGS(XX) \ 37 XX(URL_FLAGS_NONE, 0) \ 38 XX(URL_FLAGS_FAILED, 0x01) \ 39 XX(URL_FLAGS_CANNOT_BE_BASE, 0x02) \ 40 XX(URL_FLAGS_INVALID_PARSE_STATE, 0x04) \ 41 XX(URL_FLAGS_TERMINATED, 0x08) \ 42 XX(URL_FLAGS_SPECIAL, 0x10) \ 43 XX(URL_FLAGS_HAS_USERNAME, 0x20) \ 44 XX(URL_FLAGS_HAS_PASSWORD, 0x40) \ 45 XX(URL_FLAGS_HAS_HOST, 0x80) \ 46 XX(URL_FLAGS_HAS_PATH, 0x100) \ 47 XX(URL_FLAGS_HAS_QUERY, 0x200) \ 48 XX(URL_FLAGS_HAS_FRAGMENT, 0x400) \ 49 XX(URL_FLAGS_IS_DEFAULT_SCHEME_PORT, 0x800) \ 50 51 enum url_parse_state { 52 kUnknownState = -1, 53 #define XX(name) name, 54 PARSESTATES(XX) 55 #undef XX 56 }; 57 58 enum url_flags { 59 #define XX(name, val) name = val, 60 FLAGS(XX) 61 #undef XX 62 }; 63 64 struct url_data { 65 int32_t flags = URL_FLAGS_NONE; 66 int port = -1; 67 std::string scheme; 68 std::string username; 69 std::string password; 70 std::string host; 71 std::string query; 72 std::string fragment; 73 std::vector<std::string> path; 74 }; 75 76 namespace table_data { 77 extern const char hex[1024]; 78 extern const uint8_t C0_CONTROL_ENCODE_SET[32]; 79 extern const uint8_t FRAGMENT_ENCODE_SET[32]; 80 extern const uint8_t PATH_ENCODE_SET[32]; 81 extern const uint8_t USERINFO_ENCODE_SET[32]; 82 extern const uint8_t QUERY_ENCODE_SET_NONSPECIAL[32]; 83 extern const uint8_t QUERY_ENCODE_SET_SPECIAL[32]; 84 } 85 86 class URL { 87 public: 88 static void Parse(const char* input, 89 size_t len, 90 enum url_parse_state state_override, 91 struct url_data* url, 92 bool has_url, 93 const struct url_data* base, 94 bool has_base); 95 URL(const char * input,const size_t len)96 URL(const char* input, const size_t len) { 97 Parse(input, len, kUnknownState, &context_, false, nullptr, false); 98 } 99 URL(const char * input,const size_t len,const URL * base)100 URL(const char* input, const size_t len, const URL* base) { 101 if (base != nullptr) 102 Parse(input, len, kUnknownState, 103 &context_, false, 104 &(base->context_), true); 105 else 106 Parse(input, len, kUnknownState, &context_, false, nullptr, false); 107 } 108 URL(const char * input,const size_t len,const char * base,const size_t baselen)109 URL(const char* input, const size_t len, 110 const char* base, const size_t baselen) { 111 if (base != nullptr && baselen > 0) { 112 URL _base(base, baselen); 113 Parse(input, len, kUnknownState, 114 &context_, false, 115 &(_base.context_), true); 116 } else { 117 Parse(input, len, kUnknownState, &context_, false, nullptr, false); 118 } 119 } 120 URL(const std::string & input)121 explicit URL(const std::string& input) : 122 URL(input.c_str(), input.length()) {} 123 URL(const std::string & input,const URL * base)124 URL(const std::string& input, const URL* base) : 125 URL(input.c_str(), input.length(), base) {} 126 URL(const std::string & input,const URL & base)127 URL(const std::string& input, const URL& base) : 128 URL(input.c_str(), input.length(), &base) {} 129 URL(const std::string & input,const std::string & base)130 URL(const std::string& input, const std::string& base) : 131 URL(input.c_str(), input.length(), base.c_str(), base.length()) {} 132 flags()133 int32_t flags() const { 134 return context_.flags; 135 } 136 port()137 int port() const { 138 return context_.port; 139 } 140 protocol()141 const std::string& protocol() const { 142 return context_.scheme; 143 } 144 username()145 const std::string& username() const { 146 return context_.username; 147 } 148 password()149 const std::string& password() const { 150 return context_.password; 151 } 152 host()153 const std::string& host() const { 154 return context_.host; 155 } 156 query()157 const std::string& query() const { 158 return context_.query; 159 } 160 fragment()161 const std::string& fragment() const { 162 return context_.fragment; 163 } 164 path()165 std::string path() const { 166 std::string ret; 167 for (const std::string& element : context_.path) { 168 ret += '/' + element; 169 } 170 return ret; 171 } 172 173 // Get the path of the file: URL in a format consumable by native file system 174 // APIs. Returns an empty string if something went wrong. 175 std::string ToFilePath() const; 176 // Get the file URL from native file system path. 177 static URL FromFilePath(const std::string& file_path); 178 179 v8::MaybeLocal<v8::Value> ToObject(Environment* env) const; 180 181 URL(const URL&) = default; 182 URL& operator=(const URL&) = default; 183 URL(URL&&) = default; 184 URL& operator=(URL&&) = default; 185 URL()186 URL() : URL("") {} 187 188 private: 189 struct url_data context_; 190 }; 191 192 } // namespace url 193 194 } // namespace node 195 196 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 197 198 #endif // SRC_NODE_URL_H_ 199