| 1171 return 0; |
1171 return 0; |
| 1172 ++t; |
1172 ++t; |
| 1173 } |
1173 } |
| 1174 return 0; |
1174 return 0; |
| 1175 } |
1175 } |
| |
1176 |
| |
1177 /* -------------------------- util_parse_http_uri -------------------------- */ |
| |
1178 |
| |
1179 NSAPI_PUBLIC int util_parse_uri(const char *uri, WSUri *result) { |
| |
1180 if(!uri) { |
| |
1181 return 0; |
| |
1182 } |
| |
1183 return util_parse_uri_len(uri, strlen(uri), result); |
| |
1184 } |
| |
1185 |
| |
1186 NSAPI_PUBLIC int util_parse_uri_len(const char *uri, size_t length, WSUri *result) { |
| |
1187 if(length == 0) { |
| |
1188 return 0; |
| |
1189 } |
| |
1190 |
| |
1191 memset(result, 0, sizeof(WSUri)); |
| |
1192 |
| |
1193 // get uri scheme |
| |
1194 int scheme = -1; |
| |
1195 const char *scheme_str = uri; |
| |
1196 size_t scheme_len = length; |
| |
1197 short port = 0; |
| |
1198 size_t i = 0; |
| |
1199 for(;i<length;i++) { |
| |
1200 if(uri[i] == ':') { |
| |
1201 if(i+3 < length && uri[i+1] == '/' && uri[i+2] == '/') { |
| |
1202 cxstring scheme_s = cx_strn(uri, i); |
| |
1203 scheme_len = i; |
| |
1204 if(!cx_strcmp(scheme_s, "http")) { |
| |
1205 scheme = WS_URI_HTTP; |
| |
1206 port = 80; |
| |
1207 } else if(!cx_strcmp(scheme_s, "https")) { |
| |
1208 scheme = WS_URI_HTTPS; |
| |
1209 port = 443; |
| |
1210 } else { |
| |
1211 scheme = WS_URI_OTHER; |
| |
1212 } |
| |
1213 i += 3; |
| |
1214 break; |
| |
1215 } else { |
| |
1216 return 0; // invalid uri |
| |
1217 } |
| |
1218 } |
| |
1219 } |
| |
1220 result->scheme_num = scheme; |
| |
1221 result->scheme = scheme_str; |
| |
1222 result->schemelen = scheme_len; |
| |
1223 |
| |
1224 if(i == length) { |
| |
1225 return 0; // invlid uri |
| |
1226 } |
| |
1227 |
| |
1228 // get host |
| |
1229 size_t hostlen = 0; |
| |
1230 const char *port_str = NULL; |
| |
1231 const char *path = NULL; |
| |
1232 int is_ipv6_addr = 0; |
| |
1233 size_t host_start = i; |
| |
1234 if(uri[i] == '[') { |
| |
1235 host_start++; |
| |
1236 is_ipv6_addr = 1; |
| |
1237 i++; |
| |
1238 } |
| |
1239 for(;i<length;i++) { |
| |
1240 char c = uri[i]; |
| |
1241 if(is_ipv6_addr) { |
| |
1242 if(c == ']') { |
| |
1243 // end of ipv6 address |
| |
1244 result->host = uri + host_start; |
| |
1245 result->hostlen = i - host_start; |
| |
1246 is_ipv6_addr = 0; |
| |
1247 |
| |
1248 // the next character must be a port or path separator |
| |
1249 if(i+1 < length) { |
| |
1250 c = uri[i+1]; |
| |
1251 if(c != '/' && c != ':') { |
| |
1252 return 0; // invalid uri |
| |
1253 } |
| |
1254 } |
| |
1255 } else if(c != ':' && c != '.' && c != '%' && !isalnum(c)) { |
| |
1256 return 0; // invalid ipv6 address |
| |
1257 } |
| |
1258 } else if(c == ':') { |
| |
1259 if(port_str) { |
| |
1260 return 0; // error: port was already specified |
| |
1261 } |
| |
1262 if(!result->host) { |
| |
1263 result->host = uri + host_start; |
| |
1264 result->hostlen = i - host_start; |
| |
1265 } |
| |
1266 // get port |
| |
1267 port_str = uri + i + 1; |
| |
1268 } else if(c == '/') { |
| |
1269 path = uri + i; |
| |
1270 break; |
| |
1271 } else if(c == '[' || c == ']') { |
| |
1272 return 0; // invalid hostname |
| |
1273 } |
| |
1274 } |
| |
1275 if(is_ipv6_addr) { |
| |
1276 return 0; // ipv6 address was not terminated |
| |
1277 } |
| |
1278 |
| |
1279 if(port_str) { |
| |
1280 size_t port_len = uri + i - port_str; |
| |
1281 cxstring port_s = cx_strn(port_str, port_len); |
| |
1282 if(cx_strtos(port_s, &port, 10)) { |
| |
1283 return 0; // invalid port |
| |
1284 } |
| |
1285 } |
| |
1286 if(!result->host) { |
| |
1287 result->host = uri + host_start; |
| |
1288 result->hostlen = i - host_start; |
| |
1289 } |
| |
1290 if(result->hostlen == 0) { |
| |
1291 return 0; |
| |
1292 } |
| |
1293 |
| |
1294 size_t pathlen = 0; |
| |
1295 if(path) { |
| |
1296 pathlen = uri + length - path; |
| |
1297 } |
| |
1298 |
| |
1299 result->path = path; |
| |
1300 result->pathlen = pathlen; |
| |
1301 result->port = port; |
| |
1302 |
| |
1303 return 1; |
| |
1304 } |