⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 url.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 4 页
字号:
  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){  size_t n, p;  char *s0, rest_c, *host, *user;  int have_authority = 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, SIZE_MAX, 0, "+")))      return -1;    n = scheme - url->url_scheme;    url->url_type = url_get_type(url->url_scheme, n);    have_authority = !url_type_is_opaque(url->url_type);  }  else {    url->url_type = url_unknown;  }  user = NULL, host = s;  if (url->url_type == url_sip || url->url_type == url_sips) {    /* SIP URL may have /;? in user part but no path */    /* user-unreserved  =  "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */    /* Some #*@#* phones include unescaped # there, too */    n = strcspn(s, "@/;?#");    p = strcspn(s + n, "@");    if (s[n + p] == '@') {      n += p;      user = s;      host = s + n + 1;    }    n += strcspn(s + n, "/;?#");  }  else if (have_authority) {    if (url->url_type == url_wv) {      /* WV URL may have / in user part */      n = strcspn(s, "@#?;");      if (s[n] == '@') {	user = s;	host = s + n + 1;	n += strcspn(s + n, ";?#");      }    }    else if (host[0] == '/' && host[1] != '/') {      /* foo:/bar or /bar - no authority, just path */      url->url_root = '/';	/* Absolute path */      host = NULL, n = 0;    }    else {      if (host[0] == '/' && host[1] == '/') {	/* We have authority, / / foo or foo */	host += 2; s += 2, url->url_root = '/';	n = strcspn(s, "/?#@[]");      }      else 	n = strcspn(s, "@;/?#");      if (s[n] == '@')	user = host, host = user + n + 1;      n += strcspn(s + n, ";/?#");	/* Find path, query and/or fragment */    }  }  else /* !have_authority */ {    user = host, host = NULL;    if (url->url_type != url_invalid)      n = strcspn(s, "/;?#");	/* Find params, query and/or fragment */    else      n = strcspn(s, "#");  }  rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL;  if (user) {    if (host) host[-1] = '\0';    url->url_user = user;    if (url->url_type != url_unknown) {      n = strcspn(user, ":");      if (user[n]) {	user[n] = '\0';	url->url_password = user + n + 1;      }    }  }  if (host) {    url->url_host = host;    /* IPv6 (and in some cases, IPv4) addresses are quoted with [] */    if (host[0] == '[') {      n = strcspn(host, "]");      if (host[n] && (host[n + 1] == '\0' || host[n + 1] == ':'))	n++;      else	n = 0;    }    else {      n = strcspn(host, ":");    }    /* We allow empty host by default */    if (n == 0) switch (url->url_type) {    case url_sip:    case url_sips:    case url_im:    case url_pres:      return -1;    default:      break;    }        if (host[n] == ':') {      char *port = host + n + 1;      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, SIZE_MAX, 0, 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] != '*' || port[1] != '\0'))	  return -1;      }      host[n] = 0;    }  }  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, SIZE_MAX, 0, SIP_USER_UNRESERVED))      return -1;    /* Having different charset in user and password does not make sense */    /* but that is how it is defined in RFC 3261 */#   define SIP_PASS_UNRESERVED "&=+$,"    s = (char *)url->url_password;    if (s && !url_canonize(s, s, SIZE_MAX, 0, SIP_PASS_UNRESERVED))      return -1;  }  else {#   define USER_UNRESERVED "&=+$,;"    s = (char *)url->url_user;    if (s && !url_canonize(s, s, SIZE_MAX, 0, USER_UNRESERVED))      return -1;#   define PASS_UNRESERVED "&=+$,;:"    s = (char *)url->url_password;    if (s && !url_canonize(s, s, SIZE_MAX, 0, PASS_UNRESERVED))      return -1;  }  s = (char *)url->url_host;  if (s && !url_canonize2(s, s, SIZE_MAX, 0, RESERVED_MASK))    return -1;  /* port is canonized by _url_d() */  s = (char *)url->url_path;  if (s && !url_canonize(s, s, SIZE_MAX, 			 /* Allow all URI characters but ? */			 /* Allow unescaped /;?@, - but do not convert */			 SYN33('/') | SYN33(';') | SYN33('=') | SYN33('@') |			 SYN33(','),			 /* Convert escaped :&+$ to unescaped */			 ":&+$"))    return -1;  s = (char *)url->url_params;  if (s && !url_canonize(s, s, SIZE_MAX,			 /* Allow all URI characters but ? */			 /* Allow unescaped ;=@, - but do not convert */			 SYN33(';') | SYN33('=') | SYN33('@') | SYN33(','),			 /* Convert escaped /:&+$ to unescaped */			 "/:&+$"))    return -1;    /* Unhex alphanumeric and unreserved URI characters */  s = (char *)url->url_headers;  if (s && !url_canonize3(s, s, SIZE_MAX, RESERVED_MASK))    return -1;  /* Allow all URI characters (including reserved ones) */  s = (char *)url->url_fragment;  if (s && !url_canonize2(s, s, SIZE_MAX, 0, 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  * Return 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. */issize_t url_e(char buffer[], isize_t n, url_t const *url){  size_t i;  char *b = buffer;  size_t 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];    size_t 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((size_t)(b - buffer) == (size_t)(m - n));    /* This follows the snprintf(C99) return value,    * Number of characters written (excluding NUL)   */  return b - buffer;}/** Calculate the length of URL when encoded.  * */isize_t url_len(url_t const * url){  size_t 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 */isize_t url_xtra(url_t const *url){  size_t xtra;  if (URL_STRING_P(url)) {    xtra = strlen((char const *)url) + 1;  }  else {    size_t 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;    xtra =      len_scheme + len_user + len_password + len_host + len_port +      len_path + len_params + len_headers + len_fragment;  }  return xtra;}su_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}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -