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

📄 url.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 4 页
字号:
/**  * 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 Number of characters required for * duplicating the strings in @a str, or -1 if an error * occurred. */issize_t url_dup(char *buf, isize_t bufsize, url_t *dst, url_t const *src){  if (!src && !dst)    return -1;  else if (URL_STRING_P(src)) {    size_t 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) {    size_t len = sizeof(*src) + url_xtra(src);    url_t *dst = su_alloc(home, len);    if (dst) {      ssize_t actual;      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. * * @param home memory home to allocate the new string * @param url  url to convert to string * * The @a url can be a string, too. * * @return Newly allocated conversion result, or NULL upon an error. */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;  }}/** 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. */isize_t url_param(char const *params, 		  char const *tag, 		  char value[], isize_t vlen){  size_t n, tlen, flen;  char *p;  if (!params)    return 0;  tlen = strlen(tag);  if (tlen && tag[tlen - 1] == '=')    tlen--;  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(). */isize_t 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 with same name? */  size_t n = url->url_params ? strlen(url->url_params) + 1: 0;  size_t 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;}/** Remove a named parameter from url_param string. * * Remove a named parameter and its possible value from the URL parameter * string (url_s##url_param). * * @return Pointer to modified string, or NULL if nothing is left in there. */char *url_strip_param_string(char *params, char const *name){  if (params && name) {    size_t i, n = strlen(name), remove, rest;        for (i = 0; params[i];) {      if (strncasecmp(params + i, name, n) ||	  (params[i + n] != '=' && params[i + n] != ';' && params[i + n])) {	i = i + strcspn(params + i, ";");	if (!params[i++])	  break;	continue;      }      remove = n + strcspn(params + i + n, ";");      if (params[i + remove] == ';')	remove++;      if (i == 0) {	params += remove;	continue;      }      rest = strlen(params + i + remove);      if (!rest) {	if (i == 0)	  return NULL;		/* removed everything */	params[i - 1] = '\0';	break;      }      memmove(params + i, params + i + remove, rest + 1);    }    if (!params[0])      return NULL;  }  return params;}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;	memmove(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. It is stripped in-place. * * @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);}/**Lazily compare two URLs. * * Compare essential parts of URLs: schema, host, port, and username. * * any_url compares 0 with any other URL. * * pres: and im: URIs compares 0 with SIP URIs. * * @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;  int url_type;  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)) {#if 0    /* 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)#endif      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 = 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);

⌨️ 快捷键说明

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