📄 url.c
字号:
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 + len_path + len_params + len_headers + len_fragment; }}static inlinechar *copy(char *buf, char *end, char const *src){#if HAVE_MEMCCPY char *b = memccpy(buf, src, '\0', end - buf); if (b) return b; else return end + strlen(src + (end - buf)) + 1;#else for (; buf < end && (*buf = *src); buf++, src++) ; if (buf >= end) while (*src++) buf++; return buf + 1;#endif}/** * Duplicate the url. * * The function url_dup() copies the url structure @a src and the strings * attached to it to @a url. The non-constant strings in @a src are copied * to @a buf. If the size of duplicated strings exceed @a bufsize, the * corresponding string fields in @a url are set to NULL. * * The calling function can calculate the size of buffer required by calling * url_dup() with zero as @a bufsize and NULL as @a dst. * @param buf Buffer for non-constant strings copied from @a src. * @param bufsize Size of @a buf. * @param dst Destination URL structure. *燖param src Source URL structure. * * @return The function url_dup() returns number of characters required for * duplicating the strings in @a str, or -1 if an error * occurred. */int url_dup(char *buf, int bufsize, url_t *dst, url_t const *src){ if (!src && !dst) return -1; else if (URL_STRING_P(src)) { int n = strlen((char *)src) + 1; if (n > bufsize || dst == NULL) return n; strcpy(buf, (char *)src); memset(dst, 0, sizeof(*dst)); if (url_d(dst, buf) < 0) return -1; return n; } else { char *b = buf; char *end = b + bufsize; char const **dstp; char const * const *srcp; url_t dst0[1]; if (dst == NULL) dst = dst0; memset(dst, 0, sizeof(*dst)); if (!src) return 0; memset(dst->url_pad, 0, sizeof dst->url_pad); dst->url_type = src->url_type; dst->url_root = src->url_root; dstp = &dst->url_scheme; srcp = &src->url_scheme; if (dst->url_type > url_unknown) *dstp = url_scheme(dst->url_type); if (*dstp != NULL) dstp++, srcp++; /* Skip scheme if it is constant */ if (dst != dst0 && buf != NULL && bufsize != 0) for (; srcp <= &src->url_fragment; srcp++, dstp++) if (*srcp) { char *next = copy(b, end, *srcp); if (next > end) break; *dstp = b, b = next; } for (; srcp <= &src->url_fragment; srcp++) if (*srcp) { b += strlen(*srcp) + 1; } return b - buf; }}/**@def URL_DUP(buf, end, dst, src) * Duplicate the url: use @a buf up to @a end. @HI * * The macro URL_DUP() duplicates the url. The non-constant strings in @a * src are copied to @a buf. However, no strings are copied past @a end. * In other words, the size of buffer is @a end - @a buf. * * The macro updates the buffer pointer @a buf, so that it points to the * first unused byte in the buffer. The buffer pointer @a buf is updated, * even if the buffer is too small for the duplicated strings. * * @param buf Buffer for non-constant strings copied from @a src. * @param end End of @a buf. * @param dst Destination URL structure. *燖param src Source URL structure. * * @return * The macro URL_DUP() returns pointer to first unused byte in the * buffer @a buf. *//** Duplicate the url to memory allocated via home. * * The function url_hdup() duplicates (deep copies) an #url_t structure. * Alternatively, it can be passed a string; string is then copied and * parsed to the #url_t structure. * * The function url_hdup() allocates the destination structure from @a home * as a single memory block. It is possible to free the copied url structure * and all the associated strings using a single call to su_free(). * * @param home memory home used to allocate new url object * @param src pointer to URL (or string) * * @return * The function url_hdup() returns a pointer to the newly allocated #url_t * structure, or NULL upon an error. */ url_t *url_hdup(su_home_t *home, url_t const *src){ if (src) { int len = sizeof(*src) + url_xtra(src), actual; url_t *dst = su_alloc(home, len); if (dst) { actual = url_dup((char *)(dst + 1), len - sizeof(*src), dst, src); if (actual < 0) su_free(home, dst), dst = NULL; else assert(len == sizeof(*src) + actual); } return dst; } else return NULL;}/** Convert an string to an url */ url_t *url_make(su_home_t *h, char const *str){ return url_hdup(h, URL_STRING_MAKE(str)->us_url);}/** Print an URL */ url_t *url_format(su_home_t *h, char const *fmt, ...){ url_t *url; char *us; va_list ap; va_start(ap, fmt); us = su_vsprintf(h, fmt, ap); va_end(ap); if (us == NULL) return NULL; url = url_hdup(h, URL_STRING_MAKE(us)->us_url); su_free(h, us); return url;}/** Convert @a url to a string allocated from @a home */char *url_as_string(su_home_t *home, url_t const *url){ if (url) { int len = url_e(NULL, 0, url); char *b = su_alloc(home, len + 1); url_e(b, len + 1, url); return b; } else { return NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -