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

📄 url.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 4 页
字号:
      break;    default:      rv = strcmp(a->url_user, b->url_user);      break;    }    if (rv)      return rv;  }#if 0  if (a->url_path != b->url_path) {    if (a->url_path == NULL) return -1;    if (b->url_path == NULL) return +1;    if ((rv = strcmp(a->url_path, b->url_path)))      return rv;  }#endif  return 0;}staticint url_tel_cmp_numbers(char const *A, char const *B){  short a, b;  int rv;  while (*A && *B) {    #define UNHEX(a) (a - (a >= 'a' ? 'a' - 10 : (a >= 'A' ? 'A' - 10 : '0')))    /* Skip visual-separators */    do {      a = *A++;      if (a == '%' && IS_HEX(A[0]) && IS_HEX(A[1])) 	a = (UNHEX(A[0]) << 4) | UNHEX(A[1]), A +=2;    } while (a == ' ' || a == '-' || a == '.' || a == '(' || a == ')');    if (isupper(a))      a = tolower(a);    do {      b = *B++;      if (b == '%' && IS_HEX(B[0]) && IS_HEX(B[1])) 	b = (UNHEX(B[0]) << 4) | UNHEX(B[1]), B +=2;    } while (b == ' ' || b == '-' || b == '.' || b == '(' || b == ')');    if (isupper(b))      b = tolower(b);    if ((rv = a - b))      return rv;  }  return (int)*A - (int)*B;}/**Conservative comparison of urls. * * Compare all parts of URLs. * * @note * The @a a and @a b must be pointers to URL structures. * */int url_cmp_all(url_t const *a, url_t const *b){  int rv, url_type;  if (!a || !b)    return (a != NULL) - (b != NULL);  if ((rv = a->url_type - b->url_type))    return rv;  url_type = a->url_type;	/* Or b->url_type, they are equal! */  if (url_type <= url_unknown &&       ((rv = !a->url_scheme - !b->url_scheme) ||       (a->url_scheme && b->url_scheme &&	(rv = strcasecmp(a->url_scheme, b->url_scheme)))))    return rv;  if ((rv = a->url_root - b->url_root))    return rv;  if ((rv = host_cmp(a->url_host, b->url_host)))    return rv;  if (a->url_port != b->url_port) {    char const *a_port;    char const *b_port;    if (url_type != url_sip && url_type != url_sips)      a_port = b_port = url_port_default(url_type);    else if (host_is_ip_address(a->url_host))      a_port = b_port = url_port_default(url_type);    else      a_port = b_port = "";        if (a->url_port) a_port = a->url_port;    if (b->url_port) b_port = b->url_port;    if ((rv = strcmp(a_port, b_port)))      return rv;  }  if (a->url_user != b->url_user) {    if (a->url_user == NULL) return -1;    if (b->url_user == NULL) return +1;    switch (url_type) {    case url_tel: case url_modem: case url_fax:      rv = url_tel_cmp_numbers(a->url_user, b->url_user);      break;    default:      rv = strcmp(a->url_user, b->url_user);      break;    }    if (rv)      return rv;  }  if (a->url_path != b->url_path) {    if (a->url_path == NULL) return -1;    if (b->url_path == NULL) return +1;    if ((rv = strcmp(a->url_path, b->url_path)))      return rv;  }  if (a->url_params != b->url_params) {    if (a->url_params == NULL) return -1;    if (b->url_params == NULL) return +1;    if ((rv = strcmp(a->url_params, b->url_params)))      return rv;  }  if (a->url_headers != b->url_headers) {    if (a->url_headers == NULL) return -1;    if (b->url_headers == NULL) return +1;    if ((rv = strcmp(a->url_headers, b->url_headers)))      return rv;  }  if (a->url_headers != b->url_headers) {    if (a->url_headers == NULL) return -1;    if (b->url_headers == NULL) return +1;    if ((rv = strcmp(a->url_headers, b->url_headers)))      return rv;  }  if (a->url_fragment != b->url_fragment) {    if (a->url_fragment == NULL) return -1;    if (b->url_fragment == NULL) return +1;    if ((rv = strcmp(a->url_fragment, b->url_fragment)))      return rv;  }  return 0;}/** Return default port number corresponding to the url type */char const *url_port_default(enum url_type_e url_type){  switch (url_type) {  case url_sip:			/* "sip:" */    return "5060";  case url_sips:		/* "sips:" */    return "5061";  case url_http:		/* "http:" */    return "80";  case url_https:		/* "https:" */    return "443";  case url_ftp:			/* "ftp:" */  case url_file:		/* "file:" */    return "21";  case url_rtsp:		/* "rtsp:" */  case url_rtspu:		/* "rtspu:" */    return "554";  case url_mailto:		/* "mailto:" */    return "25";  case url_any:			/* "*" */    return "*";  case url_msrp:  case url_msrps:    return "9999";		/* XXXX */  case url_tel:	  case url_fax:	  case url_modem:  case url_im:	  case url_pres:  case url_cid:  case url_wv:  default:			/* Unknown scheme */    return "";  }}/** Return default transport name corresponding to the url type */char const *url_tport_default(enum url_type_e url_type){  switch (url_type) {  case url_sip:    return "*";  case url_sips:    return "tls";  case url_http:    return "tcp";  case url_https:    return "tls";  case url_ftp:  case url_file:    return "tcp";  case url_rtsp:    return "tcp";  case url_rtspu:    return "udp";  case url_mailto:    return "tcp";  case url_msrp:    return "tcp";  case url_msrps:    return "tls";  case url_any:			/* "*" */  case url_tel:  case url_fax:  case url_modem:  case url_im:  case url_pres:  case url_cid:  case url_wv:  default:			/* Unknown scheme */    return "*";  }}/** Return the URL port string */char const *url_port(url_t const *u){  if (!u)    return "";  else if (u->url_port && u->url_port[0])    return u->url_port;  if (u->url_type == url_sips || u->url_type == url_sip)    if (!host_is_ip_address(u->url_host))      return "";  return url_port_default(u->url_type);}/** Sanitize URL. * * The function url_sanitize() adds a scheme to an incomplete URL.  It * modifies its parameter structure @a url.  Currently, the function follows * simple heuristics: * * - URL with host name starting with @c ftp. is an FTP URL * - URL with host name starting with @c www. is an HTTP URL * - URL with host and path, e.g., @c host/foo;bar, is an HTTP URL * - URL with host name, no path is a SIP URL. * * @param url pointer to URL struct to be sanitized (IN/OUT) * * @return * The function url_sanitize() returns 0 if it considers URL to be * sane, and -1 otherwise. */int url_sanitize(url_t *url){  if (!url)    return -1;  else if (url->url_scheme != NULL)    /* xyzzy */;  else if (url->url_host == NULL)    return -1;  else if (strncasecmp(url->url_host, "ftp.", strlen("ftp.")) == 0)    url->url_type = url_ftp, url->url_scheme = "ftp", url->url_root = '/';  else if (strncasecmp(url->url_host, "www.", strlen("www.")) == 0	   || url->url_path)    url->url_type = url_http, url->url_scheme = "http", url->url_root = '/';  else    url->url_type = url_sip, url->url_scheme = "sip";  return 0;}#include <sofia-sip/su_md5.h>staticvoid canon_update(su_md5_t *md5, char const *s, size_t n, char const *allow){  size_t i, j;  for (i = 0, j = 0; i < n && s[i]; i++) {    char c;    if (s[i] == '%' && i + 2 < n && IS_HEX(s[i+1]) && IS_HEX(s[i+2])) {#define   UNHEX(a) (a - (a >= 'a' ? 'a' - 10 : (a >= 'A' ? 'A' - 10 : '0')))      c = (UNHEX(s[i+1]) << 4) | UNHEX(s[i+2]);#undef    UNHEX      if (c != '%' && c > ' ' && c < '\177' && 	  (!strchr(EXCLUDED, c) || strchr(allow, c))) {	if (i != j)	  su_md5_iupdate(md5, s + j, i - j);	su_md5_iupdate(md5, &c, 1);	j = i + 3;      }      i += 2;    }  }  if (i != j)    su_md5_iupdate(md5, s + j, i - j);}/** Update MD5 sum with url-string contents */staticvoid url_string_update(su_md5_t *md5, char const *s){  size_t n, p;  int have_authority = 1;  enum url_type_e type = url_any;  char const *at, *colon;  char schema[48];  if (s == NULL || strlen(s) == 0 || strcmp(s, "*") == 0) {    su_md5_update(md5, "*\0\0*", 4);    return;  }  n = strcspn(s, ":/?#");  if (n >= sizeof schema) {    su_md5_update(md5, ":", 1);  }  else if (n && s[n] == ':' ) {    at = url_canonize(schema, s, n, 0, "+");    type = url_get_type(schema, at - schema);    su_md5_iupdate(md5, schema, at - schema);    have_authority = !url_type_is_opaque(type);    s += n + 1;  }  else {    su_md5_update(md5, "", 1);  }    if (type == url_sip || 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;      /* Ignore password in hash */      colon = memchr(s, ':', n);      p = colon ? (size_t)(colon - s) : n;      canon_update(md5, s, p, SIP_USER_UNRESERVED);      s += n + 1; n = 0;    }    else      su_md5_iupdate(md5, "", 1);	/* user */    n += strcspn(s + n, "/;?#");  }  else if (have_authority) {    if (type == url_wv) {    /* WV URL may have / in user part */      n = strcspn(s, "@;?#");    }    else if (type != url_wv && s[0] == '/' && s[1] != '/') {      /* foo:/bar */      su_md5_update(md5, "\0\0", 2); /* user, host */      su_md5_striupdate(md5, url_port_default(type));      return;    }    else if (s[0] == '/' && s[1] == '/') {      /* We have authority, / / foo or foo */      s += 2;      n = strcspn(s, "/?#@[]");    }    else       n = strcspn(s, "@;/?#");    if (s[n] == '@') {      /* Ignore password in hash */      colon = type != url_unknown ? memchr(s, ':', n) : NULL;      p = colon ? (size_t)(colon - s) : n;      canon_update(md5, s, p, SIP_USER_UNRESERVED);      s += n + 1;      n = strcspn(s, "/;?#");	/* Until path, query or fragment */    }    else {      su_md5_iupdate(md5, "", 1);	/* user */      n += strcspn(s + n, "/;?#");	/* Until path, query or fragment */    }  }  else /* if (!have_authority) */ {    n = strcspn(s, ":/;?#");	/* Until pass, path, query or fragment */        canon_update(md5, s, n, ""); /* user */    su_md5_update(md5, "\0", 1); /* host, no port */    su_md5_striupdate(md5, url_port_default(type));    return;  }  if (n > 0 && s[0] == '[') {	/* IPv6reference */    colon = memchr(s, ']', n);    if (colon == NULL || ++colon == s + n || *colon != ':')      colon = NULL;  }  else     colon = memchr(s, ':', n);  if (colon) {    canon_update(md5, s, colon - s, ""); /* host */    canon_update(md5, colon + 1, (s + n) - (colon + 1), "");  }  else {    canon_update(md5, s, n, ""); /* host */    su_md5_strupdate(md5, url_port_default(type));	/* port */  }  /* ignore parameters/path/headers.... */}/** Update md5 digest with contents of URL. * */void url_update(su_md5_t *md5, url_t const *url){  if (url_string_p((url_string_t *)url)) {    url_string_update(md5, (char const *)url);  }  else {    SU_MD5_STRI0UPDATE(md5, url->url_scheme);    SU_MD5_STRI0UPDATE(md5, url->url_user);    SU_MD5_STRI0UPDATE(md5, url->url_host);    su_md5_striupdate(md5, URL_PORT(url));    /* XXX - parameters/path.... */    /* SU_MD5_STRI0UPDATE(md5, url->url_path); */  }}/** Calculate a digest from URL contents. */void url_digest(void *hash, int hsize, url_t const *url, char const *key){  su_md5_t md5[1];  uint8_t digest[SU_MD5_DIGEST_SIZE];  su_md5_init(md5);  if (key) su_md5_strupdate(md5, key);  url_update(md5, url);  su_md5_digest(md5, digest);  if (hsize > SU_MD5_DIGEST_SIZE) {    memset((char *)hash + SU_MD5_DIGEST_SIZE, 0, hsize - SU_MD5_DIGEST_SIZE);    hsize = SU_MD5_DIGEST_SIZE;  }  memcpy(hash, digest, hsize);}/** Convert a URL query to a header string. * * URL query is converted by replacing each "=" in header name "=" value * pair with semicolon (":"), and the "&" separating header-name-value pairs * with line feed ("\n"). The "body" pseudoheader is moved last in the * string. The %-escaping is removed. Note that if the @a query contains %00, * the resulting string will be truncated. * * @param home memory home used to alloate string (if NULL, malloc() it) * @param query query part from SIP URL  *  * The result string is allocated from @a home, and it can be used as * argument to msg_header_parse_str(), msg_header_add_str() or * SIPTAG_HEADER_STR(). * * @sa msg_header_add_str(), SIPTAG_HEADER_STR(), * sip_headers_as_url_query(), sip_url_query_as_taglist(),  * @RFC3261 section 19.1.1 "Headers", #url_t, url_s#url_headers, * url_unescape(), url_unescape_to() * * @since New in @VERSION_1_12_4. */char *url_query_as_header_string(su_home_t *home, 				 char const *query){  size_t i, j, n, b_start = 0, b_len = 0;  char *s = su_strdup(home, query);  if (!s)     return NULL;  for (i = 0, j = 0; s[i];) {    n = strcspn(s + i, "=");    if (!s[i + n])      break;    if (n == 4 && strncasecmp(s + i, "body", 4) == 0) {      if (b_start)	break;      b_start = i + n + 1, b_len = strcspn(s + b_start, "&");      i = b_start + b_len + 1;      continue;    }    if (i != j)      memmove(s + j, s + i, n);    s[j + n] = ':';    i += n + 1, j += n + 1;    n = strcspn(s + i, "&");    j += url_unescape_to(s + j, s + i, n);    i += n;    if (s[i]) {      s[j++] = '\n', i++;    }  }  if (s[i])    return (void)su_free(home, s), NULL;  if (b_start) {    s[j++] = '\n', s[j++] = '\n';    j += url_unescape_to(s + j, query + b_start, b_len);  }  s[j] = '\0'; assert(j <= i);  return s;}

⌨️ 快捷键说明

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