📄 url.c
字号:
test_scheme(pres); break; case 'r': case 'R': test_scheme(rtsp); test_scheme(rtspu); break; case 's': case 'S': test_scheme(sip); test_scheme(sips); break; case 't': case 'T': test_scheme(tel); break; case 'w': case 'W': test_scheme(wv); break; default: break; }#undef test_scheme if (len != span_unreserved(scheme)) return url_invalid; else return url_unknown;}/** * Decode a URL. * * This function decodes a (SIP) URL string to a url_t structure. * * @param url structure to store the parsing result * @param s NUL-terminated string to be parsed * * @note The parsed string @a s will be modified when parsing it. * * @retval 0 if successful, * @retval -1 otherwise. */staticint _url_d(url_t *url, char *s){ int n; char *s0, rest_c, *host; int net_path = 1; memset(url, 0, sizeof(*url)); if (strcmp(s, "*") == 0) { url->url_type = url_any; url->url_scheme = "*"; return 0; } s0 = s; n = strcspn(s, ":/?#"); if (n && s[n] == ':') { char *scheme; url->url_scheme = scheme = s; s[n] = '\0'; s = s + n + 1; if (!(scheme = url_canonize(scheme, scheme, -1, "+"))) return -1; n = scheme - url->url_scheme; url->url_type = url_get_type(url->url_scheme, n); net_path = !url_type_is_opaque(url->url_type); } else { url->url_type = url_unknown; } host = s; if (url->url_type == url_sip || url->url_type == url_sips) { /* SIP URL may have /; in user part */ n = strcspn(s, "@#"); /* Opaque part */ if (s[n] != '@') n = 0; n += strcspn(s + n, "/;?#"); } else if (url->url_type == url_wv) { /* WV URL may have / in user part */ n = strcspn(s, "@#?;"); if (s[n] == '@') n += strcspn(s + n, ";?#"); } else if (url->url_type == url_invalid) { n = strcspn(s, "#"); } else if (net_path && host[0] == '/') { url->url_root = host[0]; /* Absolute path */ if (host[1] == '/') { /* We have host-part */ host += 2; s += 2; } else host = NULL; n = strcspn(s, "/;?#"); /* Find path, query and/or fragment */ } else { n = strcspn(s, "/;?#"); /* Find params, query and/or fragment */ } rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL; if (host) { char *atsign, *port; if (!net_path) { url->url_user = host; host = NULL; } else if ((atsign = strchr(host, '@'))) { char *user; url->url_user = user = host; if (atsign) *atsign++ = '\0'; host = atsign; if (url->url_type != url_unknown) { char *colon = strchr(user, ':'); if (colon) *colon++ = '\0'; url->url_password = colon; } } if ((url->url_host = host)) { /* IPv6 (and in some cases, IPv4) addresses are quoted with [] */ if (host[0] == '[') { port = strchr(host, ']'); if (!port) return -1; port = strchr(port + 1, ':'); } else port = strchr(host, ':'); if (port) { *port++ = '\0'; url->url_port = port; switch (url->url_type) { case url_any: case url_sip: case url_sips: case url_http: case url_https: case url_ftp: case url_file: case url_rtsp: case url_rtspu: if (!url_canonize2(port, port, -1, RESERVED_MASK)) return -1; /* Check that port is really numeric or wildcard */ /* Port can be *digit, empty string or "*" */ while (*port >= '0' && *port <= '9') port++; if (port != url->url_port ? port[0] != '\0' : port[0] != '\0' && (port[0] != '*' || port[1] != '\0')) return -1; } } } } if (rest_c == '/') { url->url_path = s; n = strcspn(s, "?#"); rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL; } if (rest_c == ';') { url->url_params = s; n = strcspn(s, "?#"); rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL; } if (rest_c == '?') { url->url_headers = s; n = strcspn(s, "#"); rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL; } if (rest_c == '#') { url->url_fragment = s; rest_c = '\0'; } if (rest_c) return -1; return 0;}/* Unreserved things *//** * Decode a URL. * * This function decodes a URL string to a url_t structure. * * @param url structure to store the parsing result * @param s NUL-terminated string to be parsed * * @note The parsed string @a s will be modified when parsing it. * * @retval 0 if successful, * @retval -1 otherwise. */int url_d(url_t *url, char *s){ if (url == NULL || _url_d(url, s) < 0) return -1; /* Canonize URL */ /* scheme is canonized by _url_d() */ if (url->url_type == url_sip || url->url_type == url_sips) {# define SIP_USER_UNRESERVED "&=+$,;?/" s = (char *)url->url_user; if (s && !url_canonize(s, s, -1, SIP_USER_UNRESERVED)) return -1;# define SIP_PASS_UNRESERVED "&=+$," s = (char *)url->url_password; if (s && !url_canonize(s, s, -1, SIP_PASS_UNRESERVED)) return -1; } else {# define USER_UNRESERVED "&=+$,;" s = (char *)url->url_user; if (s && !url_canonize(s, s, -1, USER_UNRESERVED)) return -1;# define PASS_UNRESERVED "&=+$,;:" s = (char *)url->url_password; if (s && !url_canonize(s, s, -1, PASS_UNRESERVED)) return -1; } s = (char *)url->url_host; if (s && !url_canonize2(s, s, -1, RESERVED_MASK)) return -1; /* port is canonized by _url_d() */ /* Allow all URI characters but ? and ; */# define PATH_UNRESERVED "/:@&=+$," s = (char *)url->url_path; if (s && !url_canonize(s, s, -1, PATH_UNRESERVED)) return -1; /* Allow all URI characters but ? */# define PARAMS_UNRESERVED ";" PATH_UNRESERVED s = (char *)url->url_params; if (s && !url_canonize(s, s, -1, PARAMS_UNRESERVED)) return -1; /* Unhex alphanumeric and unreserved URI characters */ s = (char *)url->url_headers; if (s && !url_canonize3(s, s, -1, RESERVED_MASK)) return -1; /* Allow all URI characters (including reserved ones) */ s = (char *)url->url_fragment; if (s && !url_canonize2(s, s, -1, URIC_MASK)) return -1; return 0;}/** Encode an URL. * * The function url_e() combines a URL from substrings in url_t structure * according the @ref url_syntax "URL syntax" presented above. The encoded * @a url is stored in a @a buffer of @a n bytes. * * @param buffer memory area to store the encoded @a url. * @param n size of @a buffer. * @param url URL to be encoded. * * @return * The function url_e() returns the number of bytes in the encoding. * * @note The function follows the convention set by C99 snprintf(). Even if * the result does not fit into the @a buffer and it is truncated, the * function returns the number of bytes in an untruncated encoding. */int url_e(char buffer[], int n, url_t const *url){ int i; char *b = buffer; int m = n; int do_copy = n > 0; if (url == NULL) return -1; if (URL_STRING_P(url)) { char const *u = (char *)url; i = strlen(u); if (!buffer) return i; if (i >= n) { memcpy(buffer, u, n - 2); buffer[n - 1] = '\0'; } else { memcpy(buffer, u, i + 1); } return i; } if (url->url_type == url_any) { if (b && m > 0) { if (m > 1) strcpy(b, "*"); else b[0] = '\0'; } return 1; } if (url->url_scheme && url->url_scheme[0]) { i = strlen(url->url_scheme) + 1; if (do_copy && (do_copy = i <= n)) { memcpy(b, url->url_scheme, i - 1); b[i - 1] = ':'; } b += i; n -= i; } if (url->url_root && (url->url_host || url->url_user)) { if (do_copy && (do_copy = 2 <= n)) memcpy(b, "//", 2); b += 2; n -= 2; } if (url->url_user) { i = strlen(url->url_user); if (do_copy && (do_copy = i <= n)) memcpy(b, url->url_user, i); b += i; n -= i; if (url->url_password) { if (do_copy && (do_copy = 1 <= n)) *b = ':'; b++; n--; i = strlen(url->url_password); if (do_copy && (do_copy = i <= n)) memcpy(b, url->url_password, i); b += i; n -= i; } if (url->url_host) { if (do_copy && (do_copy = 1 <= n)) *b = '@'; b++; n--; } } if (url->url_host) { i = strlen(url->url_host); if (do_copy && (do_copy = i <= n)) memcpy(b, url->url_host, i); b += i; n -= i; if (url->url_port) { i = strlen(url->url_port) + 1; if (do_copy && (do_copy = i <= n)) { b[0] = ':'; memcpy(b + 1, url->url_port, i - 1); } b += i; n -= i; } } if (url->url_path) { if (url->url_root) { if (do_copy && (do_copy = 1 <= n)) b[0] = '/'; b++, n--; } i = strlen(url->url_path); if (do_copy && (do_copy = i < n)) memcpy(b, url->url_path, i); b += i; n -= i; } { static char const sep[] = ";?#"; char const *pp[3]; int j; pp[0] = url->url_params; pp[1] = url->url_headers; pp[2] = url->url_fragment; for (j = 0; j < 3; j++) { char const *p = pp[j]; if (!p) continue; i = strlen(p) + 1; if (do_copy && (do_copy = i <= n)) { *b = sep[j]; memcpy(b + 1, p, i - 1); } b += i; n -= i; } } if (do_copy && (do_copy = 1 <= n)) *b = '\0'; else if (buffer && m > 0) buffer[m - 1] = '\0'; assert(b - buffer == m - n); /* This follows the snprintf(C99) return value, * Number of characters written (excluding NUL) */ return b - buffer;}/** Calculate the lengh of URL when encoded. * */int url_len(url_t const * url){ int rv = 0; if (url->url_scheme) rv += strlen(url->url_scheme) + 1; /* plus ':' */ if (url->url_user) { rv += strlen(url->url_user); if (url->url_password) rv += strlen(url->url_password) + 1; /* plus ':' */ rv += url->url_host != NULL; /* plus '@' */ } if (url->url_host) rv += strlen(url->url_host); if (url->url_port) rv += strlen(url->url_port) + 1; /* plus ':' */ if (url->url_path) rv += strlen(url->url_path) + 1; /* plus initial / */ if (url->url_params) rv += strlen(url->url_params) + 1; /* plus initial ; */ if (url->url_headers) rv += strlen(url->url_headers) + 1; /* plus '?' */ if (url->url_fragment) rv += strlen(url->url_fragment) + 1; /* plus '#' */ return rv;}/**@def URL_E(buf, end, url) * Encode an URL: use @a buf up to @a end. * @hideinitializer *//** * Calculate the size of strings associated with a #url_t sructure. * * @param url pointer to a #url_t structure or string * @return Number of bytes for URL */int url_xtra(url_t const *url){ if (URL_STRING_P(url)) { return strlen((char const *)url) + 1; } else { unsigned len_scheme, len_user, len_password, len_host, len_port, len_path, len_params, len_headers, len_fragment; len_scheme = (url->url_type <= url_unknown && url->url_scheme) ? strlen(url->url_scheme) + 1 : 0; len_user = url->url_user ? strlen(url->url_user) + 1 : 0; len_password = url->url_password ? strlen(url->url_password) + 1 : 0; len_host = url->url_host ? strlen(url->url_host) + 1 : 0; len_port = url->url_port ? strlen(url->url_port) + 1 : 0; len_path = url->url_path ? strlen(url->url_path) + 1 : 0; len_params = url->url_params ? strlen(url->url_params) + 1 : 0; len_headers = url->url_headers ? strlen(url->url_headers) + 1 : 0; len_fragment = url->url_fragment ? strlen(url->url_fragment) + 1 : 0; return len_scheme + len_user + len_password + len_host + len_port +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -