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

📄 url.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 3 页
字号:
/** Test if param @a tag matches to parameter string @a p.  */#define URL_PARAM_MATCH(p, tag) \ (strncasecmp(p, tag, strlen(tag)) == 0 && \  (p[strlen(tag)] == '\0' || p[strlen(tag)] == ';' || p[strlen(tag)] == '='))/** * Search for a parameter. * * This function searches for a parameter from a parameter list. * * If you want to test if there is parameter @b user=phone,  * call this function like  * @code if (url_param(url->url_param, "user=phone", NULL, 0)) * @endcode * * @param params URL parameter string (excluding first semicolon) * @param tag    parameter name * @param value  string to which the parameter value is copied * @param vlen   length of string reserved for value * * @retval positive length of parameter value (including final NUL) if found * @retval zero     if not found. */int url_param(char const *params, 	      char const *tag, 	      char value[], int vlen){  size_t n, tlen = strlen(tag), flen;  char *p;    if (!params)    return 0;  for (p = (char *)params; *p; p += n + 1) {    n = strcspn(p, ";");    if (n < tlen) {      if (p[n]) continue; else break;    }    if (strncasecmp(p, tag, tlen) == 0) {      if (n == tlen) {	if (vlen > 0)	  value[0] = '\0';		return 1;      }      if (p[tlen] != '=')	continue;      flen = n - tlen - 1;      if (flen >= (size_t)vlen)	return flen + 1;      memcpy(value, p + tlen + 1, flen);      value[flen] = '\0';      return flen + 1;    }    if (!p[n])      break;  }  return 0;}/** Check for a parameter.  * * @deprecated  * Bad grammar. Use url_has_param(). */int url_have_param(char const *params, char const *tag){  return url_param(params, tag, NULL, 0);}/** Check for a parameter. */int url_has_param(url_t const *url, char const *tag){  return url && url->url_params && url_param(url->url_params, tag, NULL, 0);}/** Add an parameter. */int url_param_add(su_home_t *h, url_t *url, char const *param){  /* XXX - should remove existing parameters? */  int n = url->url_params ? strlen(url->url_params) + 1: 0;  int nn = strlen(param) + 1;  char *s = su_alloc(h, n + nn);  if (!s)    return -1;    if (url->url_params)    strcpy(s, url->url_params)[n - 1] = ';';  strcpy(s + n, param);  url->url_params = s;  return 0;}int url_string_p(url_string_t const *url){  return URL_STRING_P(url);}int url_is_string(url_string_t const *url){  return URL_IS_STRING(url);}/** Strip transport-specific stuff. */staticint url_strip_transport2(url_t *url, int modify){  char *p, *d;  size_t n;  int semi;  if (url->url_type != url_sip && url->url_type != url_sips)    return 0;    if (url->url_port != NULL) {    if (!modify)      return 1;    url->url_port = NULL;  }  if (!url->url_params)    return 0;  for (d = p = (char *)url->url_params; *p; p += n + semi) {    n = strcspn(p, ";");    semi = (p[n] != '\0');    if (modify && n == 0)      continue;    if (URL_PARAM_MATCH(p, "method"))      continue;    if (URL_PARAM_MATCH(p, "maddr"))      continue;    if (URL_PARAM_MATCH(p, "ttl"))      continue;    if (URL_PARAM_MATCH(p, "transport"))      continue;    if (p != d) {      if (d != url->url_params)	d++;      if (p != d) {	if (!modify)	  return 1;	memcpy(d, p, n + 1);      }    }    d += n;  }  if (d == p)    return 0;  else if (d + 1 == p)		/* empty param */    return 0;  else if (!modify)    return 1;  if (d != url->url_params)    *d = '\0';  else     url->url_params = NULL;  return 1;}/** Strip transport-specific stuff.  * * The function url_strip_transport() removes transport-specific parameters * from a SIP or SIPS URI.  These parameters include: * - the port number * - "maddr=" parameter * - "transport=" parameter * - "ttl=" parameter * - "method=" parameter * * @note * The @a url must be a pointer to a URL structure. * * @note * If the parameter string contains empty parameters, they are stripped, too. * * @return  * The function url_strip_transport() returns @e true, if the URL was * modified, @e false otherwise. */int url_strip_transport(url_t *url){  return url_strip_transport2(url, 1);}/** Check for transport-specific stuff.  * * The function url_have_transport() tests if there are transport-specific * parameters in a SIP or SIPS URI. These parameters include: * - the port number * - "maddr=" parameters * - "transport=" parameters *  * @note * The @a url must be a pointer to a URL structure. * * @return The function url_have_transport() returns @e true, if the URL * contains transport parameters, @e false otherwise. */int url_have_transport(url_t const *url){  return url_strip_transport2((url_t *)url, 0);}/** Compare two URLs. * * @note * The @a a and @a b must be pointers to URL structures. * * @note Currently, the url parameters are not compared. This is because the * url_cmp() is used to sort URLs: taking parameters into account makes that * impossible. */int url_cmp(url_t const *a, url_t const *b){  int rv;  if ((a && a->url_type == url_any) || (b && b->url_type == url_any))    return 0;  if (!a || !b)    return (a != NULL) - (b != NULL);  if ((rv = a->url_type - b->url_type)) {    /* presence and instant messaging URLs match magically with SIP */    enum url_type_e a_type = a->url_type;    enum url_type_e b_type = b->url_type;        if (a_type == url_im || a_type == url_pres)      a_type = url_sip;    if (b_type == url_im || b_type == url_pres)      b_type = url_sip;    if (a_type != b_type)      return rv;  }  if (a->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 (a->url_host != b->url_host &&       ((rv = !a->url_host - !b->url_host) ||       (rv = strcasecmp(a->url_host, b->url_host))))    return rv;  if (a->url_port != b->url_port) {    char const *a_port;    char const *b_port;    if (a->url_type != url_sip && a->url_type != url_sips)      a_port = b_port = url_port_default(a->url_type);    else if (host_is_ip_address(a->url_host))      a_port = b_port = url_port_default(a->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;    if ((rv = strcmp(a->url_user, b->url_user)))      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;}/** 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:    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_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)    return u->url_port;  else    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, int n, char const *allow){  char const *s0 = s, *b = s;  for (;*s && s - s0 < n; s++) {    char c;    if (*s == '%' && IS_HEX(s[1]) && IS_HEX(s[2]) && s - s0 + 2 < n) {#define   UNHEX(a) (a - (a >= 'a' ? 'a' - 10 : (a >= 'A' ? 'A' - 10 : '0')))      c = (UNHEX(s[1]) << 4) | UNHEX(s[2]);#undef    UNHEX      if (c != '%' && c > ' ' && c < '\177' && 	  (!strchr(EXCLUDED, c) || strchr(allow, c))) {	if (b != s)	  su_md5_iupdate(md5, b, s - b);	su_md5_iupdate(md5, &c, 1);	b = s + 3;      }      s += 2;    }  }  if (b != s)    su_md5_iupdate(md5, b, s - b);}/** Update MD5 sum with url-string contents */staticvoid url_string_update(su_md5_t *md5, char const *s){  int n;  int hostpart = 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, "+");    type = url_get_type(schema, at - schema);    su_md5_iupdate(md5, schema, at - schema);    hostpart = !url_type_is_opaque(type);    s += n + 1;  }  else {    su_md5_update(md5, "", 1);  }    if (type == url_sip || type == url_sips) {    n = strcspn(s, "@#");	/* Opaque part */    if (s[n] != '@')      n = 0;    n += strcspn(s + n, "/;?#");  }  else if (!hostpart || s[0] != '/') {    n = strcspn(s, "/;?#");	/* Opaque part */  }  else if (s[1] == '/') {    s += 2;    n = strcspn(s, "/;?#");	/* Until path, query or fragment */  }  else {    /* foo:/bar */    su_md5_update(md5, "\0\0", 2); /* user, host */    su_md5_striupdate(md5, url_port_default(type));    return;  }    if (!hostpart) {    char const *colon = memchr(s, ':', n);        if (colon) n = colon - s;    canon_update(md5, s, n, ""); /* user */    su_md5_update(md5, "\0", 1); /* host, no port */    su_md5_striupdate(md5, url_port_default(type));    return;  }  at = memchr(s, '@', n);  if (at) {    char const *allow =       (type == url_sip || type == url_sips)       ? SIP_USER_UNRESERVED      : USER_UNRESERVED;    colon = memchr(s, ':', at - s);    /* Updated only user part */    if (colon)      canon_update(md5, s, colon - s, allow);    else      canon_update(md5, s, at - s, allow);    n = n - (at + 1 - s);    s = at + 1;  }  else    su_md5_iupdate(md5, "", 1);	/* user */  colon = memchr(s, ':', n);	/* XXX - IPv6! */  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);}

⌨️ 快捷键说明

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