MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add proper url parsing for hashables

+97 -1
+97 -1
src/modules/url.c
··· 182 182 return strndup(r->first, (size_t)(r->afterLast - r->first)); 183 183 } 184 184 185 + static char *url_escape_brackets_in_query_or_fragment(const char *url_str, bool *changed_out) { 186 + size_t len = strlen(url_str); 187 + size_t extra = 0; 188 + bool in_query = false; 189 + bool in_fragment = false; 190 + 191 + for (size_t i = 0; i < len; i++) { 192 + char c = url_str[i]; 193 + if (c == '#' && !in_fragment) { 194 + in_query = false; 195 + in_fragment = true; 196 + continue; 197 + } 198 + if (c == '?' && !in_query && !in_fragment) { 199 + in_query = true; 200 + continue; 201 + } 202 + if ((in_query || in_fragment) && (c == '[' || c == ']')) extra += 2; 203 + } 204 + 205 + if (changed_out) *changed_out = (extra != 0); 206 + if (extra == 0) return NULL; 207 + 208 + char *escaped = malloc(len + extra + 1); 209 + size_t pos = 0; 210 + in_query = false; 211 + in_fragment = false; 212 + 213 + if (!escaped) return NULL; 214 + 215 + for (size_t i = 0; i < len; i++) { 216 + char c = url_str[i]; 217 + if (c == '#' && !in_fragment) { 218 + in_query = false; 219 + in_fragment = true; 220 + escaped[pos++] = c; 221 + continue; 222 + } 223 + if (c == '?' && !in_query && !in_fragment) { 224 + in_query = true; 225 + escaped[pos++] = c; 226 + continue; 227 + } 228 + if ((in_query || in_fragment) && c == '[') { 229 + memcpy(escaped + pos, "%5B", 3); 230 + pos += 3; 231 + continue; 232 + } 233 + if ((in_query || in_fragment) && c == ']') { 234 + memcpy(escaped + pos, "%5D", 3); 235 + pos += 3; 236 + continue; 237 + } 238 + escaped[pos++] = c; 239 + } 240 + 241 + escaped[pos] = '\0'; 242 + return escaped; 243 + } 244 + 245 + static void url_override_search_hash_from_input(url_state_t *s, const char *url_str) { 246 + const char *hash = strchr(url_str, '#'); 247 + const char *query = strchr(url_str, '?'); 248 + size_t search_len = 0; 249 + size_t hash_len = 0; 250 + 251 + if (query && hash && hash < query) query = NULL; 252 + 253 + if (query) { 254 + const char *search_end = hash && hash > query ? hash : url_str + strlen(url_str); 255 + search_len = (size_t)(search_end - query); 256 + } 257 + if (hash) hash_len = strlen(hash); 258 + 259 + free(s->search); 260 + s->search = search_len > 0 ? strndup(query, search_len) : strdup(""); 261 + 262 + free(s->hash); 263 + s->hash = hash_len > 0 ? strndup(hash, hash_len) : strdup(""); 264 + } 265 + 185 266 static void uri_to_state(const UriUriA *uri, url_state_t *s) { 186 267 char *scheme = uri_range_dup(&uri->scheme); 187 268 size_t slen = strlen(scheme); ··· 307 388 } 308 389 309 390 UriUriA uri; 310 - if (uriParseSingleUriA(&uri, url_str, &errpos) != URI_SUCCESS) return -1; 391 + char *escaped_url = NULL; 392 + bool used_relaxed_query_parse = false; 393 + 394 + if (uriParseSingleUriA(&uri, url_str, &errpos) != URI_SUCCESS) { 395 + escaped_url = url_escape_brackets_in_query_or_fragment(url_str, &used_relaxed_query_parse); 396 + if (!escaped_url) return -1; 397 + if (uriParseSingleUriA(&uri, escaped_url, &errpos) != URI_SUCCESS) { 398 + free(escaped_url); 399 + return -1; 400 + } 401 + } 402 + 311 403 if (!uri.scheme.first || uri.scheme.first == uri.scheme.afterLast) { 312 404 uriFreeUriMembersA(&uri); 405 + free(escaped_url); 313 406 return -1; 314 407 } 315 408 316 409 uriNormalizeSyntaxA(&uri); 317 410 uri_to_state(&uri, s); 411 + if (used_relaxed_query_parse) url_override_search_hash_from_input(s, url_str); 412 + 318 413 uriFreeUriMembersA(&uri); 414 + free(escaped_url); 319 415 320 416 return 0; 321 417 }