int
osip_message_set_multiple_header(osip_message_t * sip, char *hname, char *hvalue)
{
	int i;
	char *ptr;					/* current location of the search */
	char *comma;				/* This is the separator we are elooking for */
	char *beg;					/* beg of a header */
	char *end;					/* end of a header */
	char *quote1;				/* first quote of a pair of quotes   */
	char *quote2;				/* second quuote of a pair of quotes */
	size_t hname_len;

	/* Find header based upon lowercase comparison */
	osip_tolower(hname);

	if (hvalue == NULL) {
		i = osip_message_set__header(sip, hname, hvalue);
		if (i != 0)
			return i;
		return OSIP_SUCCESS;
	}

	ptr = hvalue;
	comma = strchr(ptr, ',');

	hname_len = strlen(hname);

	if (comma == NULL || (hname_len == 4 && strncmp(hname, "date", 4) == 0)
		|| (hname_len == 2 && strncmp(hname, "to", 2) == 0)
		|| (hname_len == 4 && strncmp(hname, "from", 4) == 0)
		|| (hname_len == 7 && strncmp(hname, "call-id", 7) == 0)
		|| (hname_len == 4 && strncmp(hname, "cseq", 4) == 0)
		|| (hname_len == 7 && strncmp(hname, "subject", 7) == 0)
		|| (hname_len == 7 && strncmp(hname, "expires", 7) == 0)
		|| (hname_len == 6 && strncmp(hname, "server", 6) == 0)
		|| (hname_len == 10 && strncmp(hname, "user-agent", 10) == 0)
		|| (hname_len == 16 && strncmp(hname, "www-authenticate", 16) == 0)
		|| (hname_len == 19 && strncmp(hname, "authentication-info", 19) == 0)
		|| (hname_len == 18 && strncmp(hname, "proxy-authenticate", 18) == 0)
		|| (hname_len == 19 && strncmp(hname, "proxy-authorization", 19) == 0)
		|| (hname_len == 25
			&& strncmp(hname, "proxy-authentication-info", 25) == 0)
		|| (hname_len == 12 && strncmp(hname, "organization", 12) == 0)
		|| (hname_len == 13 && strncmp(hname, "authorization", 13) == 0))
		/* there is no multiple header! likely      */
		/* to happen most of the time...            */
		/* or hname is a TEXT-UTF8-TRIM and may     */
		/* contain a comma. this is not a separator */
		/* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */
	{
		i = osip_message_set__header(sip, hname, hvalue);
		if (i != 0)
			return i;
		return OSIP_SUCCESS;
	}

	beg = hvalue;
	end = NULL;
	quote2 = NULL;
	while (comma != NULL) {
		quote1 = __osip_quote_find(ptr);
		if (quote1 != NULL) {
			quote2 = __osip_quote_find(quote1 + 1);
			if (quote2 == NULL)
				return OSIP_SYNTAXERROR;	/* quotes comes by pair */
			ptr = quote2 + 1;
		}

		if ((quote1 == NULL) || (quote1 > comma)) {
			/* We must search for the next comma which is not
			   within quotes! */
			end = comma;

			if (quote1 != NULL && quote1 > comma) {
				/* comma may be within the quotes */
				/* ,<sip:[email protected]>;methods=\"INVITE,BYE,OPTIONS,ACK,CANCEL\",<sip:[email protected]> */
				/* we want the next comma after the quotes */
				char *tmp_comma;
				char *tmp_quote1;
				char *tmp_quote2;

				tmp_quote1 = quote1;
				tmp_quote2 = quote2;
				tmp_comma = strchr(comma + 1, ',');
				while (1) {
					if (tmp_comma < tmp_quote1)
						break;	/* ok (before to quotes) */
					if (tmp_comma < tmp_quote2) {
						tmp_comma = strchr(tmp_quote2 + 1, ',');
					}
					tmp_quote1 = __osip_quote_find(tmp_quote2 + 1);
					if (tmp_quote1 == NULL)
						break;
					tmp_quote2 = __osip_quote_find(tmp_quote1 + 1);
					if (tmp_quote2 == NULL)
						break;	/* probably a malformed message? */
				}
				comma = tmp_comma;	/* this one is not enclosed within quotes */
			} else
				comma = strchr(comma + 1, ',');
			if (comma != NULL)
				ptr = comma + 1;

		} else if ((quote1 < comma) && (quote2 < comma)) {	/* quotes are located before the comma, */
			/* continue the search for next quotes  */
			ptr = quote2 + 1;
		} else if ((quote1 < comma) && (comma < quote2)) {	/* if comma is inside the quotes... */
			/* continue with the next comma.    */
			ptr = quote2 + 1;
			comma = strchr(ptr, ',');
			if (comma == NULL)
				/* this header last at the end of the line! */
			{					/* this one does not need an allocation... */
#if 0
				if (strlen(beg) < 2)
					return OSIP_SUCCESS;	/* empty header */
#else
				if (beg[0] == '\0' || beg[1] == '\0')
					return OSIP_SUCCESS;	/* empty header */
#endif
				osip_clrspace(beg);
				i = osip_message_set__header(sip, hname, beg);
				if (i != 0)
					return i;
				return OSIP_SUCCESS;
			}
		}

		if (end != NULL) {
			char *avalue;

			if (end - beg + 1 < 2)
				return OSIP_SYNTAXERROR;
			avalue = (char *) osip_malloc(end - beg + 1);
			if (avalue == NULL)
				return OSIP_NOMEM;
			osip_clrncpy(avalue, beg, end - beg);
			/* really store the header in the sip structure */
			i = osip_message_set__header(sip, hname, avalue);
			osip_free(avalue);
			if (i != 0)
				return i;
			beg = end + 1;
			end = NULL;
			if (comma == NULL)
				/* this header last at the end of the line! */
			{					/* this one does not need an allocation... */
#if 0
				if (strlen(beg) < 2)
					return OSIP_SUCCESS;	/* empty header */
#else
				if (beg[0] == '\0' || beg[1] == '\0')
					return OSIP_SUCCESS;	/* empty header */
#endif
				osip_clrspace(beg);
				i = osip_message_set__header(sip, hname, beg);
				if (i != 0)
					return i;
				return OSIP_SUCCESS;
			}
		}
	}
	return OSIP_SYNTAXERROR;	/* if comma is NULL, we should have already return 0 */
}
int
osip_message_set_multiple_header (osip_message_t * sip, char *hname, char *hvalue)
{
  int i;
  char *ptr, *p;                /* current location of the search */
  char *comma;                  /* This is the separator we are elooking for */
  char *beg;                    /* beg of a header */
  char *end;                    /* end of a header */
  int inquotes, inuri;          /* state for inside/outside of double-qoutes or URI */
  size_t hname_len;

  /* Find header based upon lowercase comparison */
  osip_tolower (hname);

  if (hvalue == NULL) {
    i = osip_message_set__header (sip, hname, hvalue);
    if (i != 0)
      return i;
    return OSIP_SUCCESS;
  }

  ptr = hvalue;
  comma = strchr (ptr, ',');

  hname_len = strlen (hname);

  if (comma == NULL || (hname_len == 4 && strncmp (hname, "date", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "t", 1) == 0)
      || (hname_len == 2 && strncmp (hname, "to", 2) == 0)
      || (hname_len == 1 && strncmp (hname, "f", 1) == 0)
      || (hname_len == 4 && strncmp (hname, "from", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "i", 1) == 0)
      || (hname_len == 7 && strncmp (hname, "call-id", 7) == 0)
      || (hname_len == 4 && strncmp (hname, "cseq", 4) == 0)
      || (hname_len == 1 && strncmp (hname, "s", 1) == 0)
      || (hname_len == 7 && strncmp (hname, "subject", 7) == 0)
      || (hname_len == 7 && strncmp (hname, "expires", 7) == 0)
      || (hname_len == 6 && strncmp (hname, "server", 6) == 0)
      || (hname_len == 10 && strncmp (hname, "user-agent", 10) == 0)
      || (hname_len == 16 && strncmp (hname, "www-authenticate", 16) == 0)
      || (hname_len == 19 && strncmp (hname, "authentication-info", 19) == 0)
      || (hname_len == 18 && strncmp (hname, "proxy-authenticate", 18) == 0)
      || (hname_len == 19 && strncmp (hname, "proxy-authorization", 19) == 0)
      || (hname_len == 25 && strncmp (hname, "proxy-authentication-info", 25) == 0)
      || (hname_len == 12 && strncmp (hname, "organization", 12) == 0)
      || (hname_len == 13 && strncmp (hname, "authorization", 13) == 0)
      || (hname_len == 1 && strncmp (hname, "r", 1) == 0) /* refer-to */
      || (hname_len == 8 && strncmp (hname, "refer-to", 8) == 0)
      || (hname_len == 1 && strncmp (hname, "b", 1) == 0) /* referred-by */
      || (hname_len == 11 && strncmp (hname, "referred-by", 11) == 0))
    /* there is no multiple header! likely      */
    /* to happen most of the time...            */
    /* or hname is a TEXT-UTF8-TRIM and may     */
    /* contain a comma. this is not a separator */
    /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */
  {
    i = osip_message_set__header (sip, hname, hvalue);
    if (i != 0)
      return i;
    return OSIP_SUCCESS;
  }

  beg = hvalue;
  inquotes = 0;
  inuri = 0;
  /* Seach for a comma that is not within quotes or a URI */
  for (;; ptr++)
  {
    switch (*ptr)
    {
    case '"':
      /* Check that the '"' is not escaped */
      for (i = 0, p = ptr; p >= beg && *p == '\\'; p--, i++);
      if (i % 2 == 0)
        inquotes = !inquotes; /* the '"' was not escaped */
      break;

    case '<':
      if (!inquotes)
      {
        if (!inuri)
        {
          if((osip_strncasecmp(ptr+1, "sip:", 4) == 0
              || osip_strncasecmp(ptr+1, "sips:", 5) == 0
              || osip_strncasecmp(ptr+1, "http:", 5) == 0
              || osip_strncasecmp(ptr+1, "https:", 6) == 0
              || osip_strncasecmp(ptr+1, "tel:", 4) == 0)
              && strchr(ptr, '>'))
            inuri = 1;
        }
	/*
	  else {
	  if we found such sequence: "<sip:" "<sip:" ">"
	  It might be a valid header containing data and not URIs.
	  Thus, we ignore inuri
	  }
	*/
      }
      break;

    case '>':
      if (!inquotes)
      {
        if (inuri)
          inuri = 0;
      }
      break;

    case '\0':
      /* we discard any validation we tried: no valid uri detected */
      inquotes=0;
      inuri=0;
    case ',':
      if (!inquotes && !inuri)
      {
        char *avalue;

        if (beg[0] == '\0')
          return OSIP_SUCCESS; /* empty header */

        end = ptr;
        if (end - beg + 1 < 2)
	  {
	    beg=end+1;
	    break; /* skip empty header */
	  }
        avalue = (char *) osip_malloc (end - beg + 1);
        if (avalue==NULL)
          return OSIP_NOMEM;
        osip_clrncpy (avalue, beg, end - beg);
        /* really store the header in the sip structure */
        i = osip_message_set__header (sip, hname, avalue);
        osip_free (avalue);
        if (i != 0)
          return i;
        beg = end + 1;
      }
      if (*ptr == '\0')
        return OSIP_SUCCESS;
      break;

    default:
      break;
    }
  }
}