parm_len = PL_strlen(parm_name);
parm_len = nsCRT::strlen(parm_name);
MimeHeaders_get_parameter (const char *header_value, const char *parm_name, 						   char **charset, char **language){  const char *str;  char *s = NULL; /* parm value to be returned */  PRInt32 parm_len;  if (!header_value || !parm_name || !*header_value || !*parm_name)	return 0;  /* The format of these header lines is	 <token> [ ';' <token> '=' <token-or-quoted-string> ]*   */  if (charset) *charset = NULL;  if (language) *language = NULL;  str = header_value;  parm_len = PL_strlen(parm_name);  /* Skip forward to first ';' */  for (; *str && *str != ';' && *str != ','; str++)	;  if (*str)	str++;  /* Skip over following whitespace */  for (; *str && IS_SPACE(*str); str++)	;  if (!*str)	return 0;  while (*str)	{	  const char *token_start = str;	  const char *token_end = 0;	  const char *value_start = str;	  const char *value_end = 0;	  PR_ASSERT(!IS_SPACE(*str)); /* should be after whitespace already */	  /* Skip forward to the end of this token. */	  for (; *str && !IS_SPACE(*str) && *str != '=' && *str != ';'; str++)		;	  token_end = str;	  /* Skip over whitespace, '=', and whitespace */	  while (IS_SPACE (*str)) str++;	  if (*str == '=') str++;	  while (IS_SPACE (*str)) str++;	  if (*str != '"')		{		  /* The value is a token, not a quoted string. */		  value_start = str;		  for (value_end = str;			   *value_end && !IS_SPACE (*value_end) && *value_end != ';';			   value_end++)			;		  str = value_end;		}	  else		{		  /* The value is a quoted string. */		  str++;		  value_start = str;		  for (value_end = str; *value_end; value_end++)			{			  if (*value_end == '\\')				value_end++;			  else if (*value_end == '"')				break;			}		  str = value_end+1;		}	  /* See if this is the parameter we're looking for.		 If so, copy it and return.	   */	  if (token_end - token_start == parm_len &&		  !PL_strncasecmp(token_start, parm_name, parm_len))		{		  s = (char *) PR_MALLOC ((value_end - value_start) + 1);		  if (! s) return 0;  /* MIME_OUT_OF_MEMORY */		  nsCRT::memcpy (s, value_start, value_end - value_start);		  s [value_end - value_start] = 0;		  /* if the parameter spans across multiple lines we have to strip out the			 line continuatio -- jht 4/29/98 */		  MIME_StripContinuations(s);		  return s;		}	  else if (token_end - token_start > parm_len &&			   !PL_strncasecmp(token_start, parm_name, parm_len) &&			   *(token_start+parm_len) == '*')	  {		  /* RFC2231 - The legitimate parm format can be:			 title*=us-ascii'en-us'This%20is%20weired.			    or			 title*0*=us-ascii'en'This%20is%20weired.%20We			 title*1*=have%20to%20support%20this.			 title*3="Else..."			    or			 title*0="Hey, what you think you are doing?"			 title*1="There is no charset and language info."		   */		  const char *cp = token_start+parm_len+1; /* 1st char pass '*' */		  PRBool needUnescape = *(token_end-1) == '*';		  if ((*cp == '0' && needUnescape) || (token_end-token_start == parm_len+1))		  {			  const char *s_quote1 = PL_strchr(value_start, 0x27);			  const char *s_quote2 = (char *) (s_quote1 ? PL_strchr(s_quote1+1, 0x27) : NULL);			  PR_ASSERT(s_quote1 && s_quote2);			  if (charset && s_quote1 > value_start && s_quote1 < value_end)			  {				  *charset = (char *) PR_MALLOC(s_quote1-value_start+1);				  if (*charset)				  {					  nsCRT::memcpy(*charset, value_start, s_quote1-value_start);					  *(*charset+(s_quote1-value_start)) = 0;				  }			  }			  if (language && s_quote1 && s_quote2 && s_quote2 > s_quote1+1 &&				  s_quote2 < value_end)			  {				  *language = (char *) PR_MALLOC(s_quote2-(s_quote1+1)+1);				  if (*language)				  {					  nsCRT::memcpy(*language, s_quote1+1, s_quote2-(s_quote1+1));					  *(*language+(s_quote2-(s_quote1+1))) = 0;				  }			  }			  if (s_quote2 && s_quote2+1 < value_end)			  {				  PR_ASSERT(!s);				  s = (char *) PR_MALLOC(value_end-(s_quote2+1)+1);				  if (s)				  {					  nsCRT::memcpy(s, s_quote2+1, value_end-(s_quote2+1));					  *(s+(value_end-(s_quote2+1))) = 0;					  if (needUnescape)					  {						  nsUnescape(s);						  if (token_end-token_start == parm_len+1)							  return s; /* we done; this is the simple case of										   encoding charset and language info										 */					  }				  }			  }		  }		  else if (XP_IS_DIGIT(*cp))		  {			  PRInt32 len = 0;			  char *ns = NULL;			  if (s)			  {				  len = PL_strlen(s);				  ns = (char *) PR_Realloc(s, len+(value_end-value_start)+1);				  if (!ns)                    {					  PR_FREEIF(s);                    }				  else if (ns != s)					  s = ns;			  }			  else if (*cp == '0') /* must be; otherwise something is wrong */			  {				  s = (char *) PR_MALLOC(value_end-value_start+1);			  }			  /* else {} something is really wrong; out of memory */			  if (s)			  {				  nsCRT::memcpy(s+len, value_start, value_end-value_start);				  *(s+len+(value_end-value_start)) = 0;				  if (needUnescape)					  nsUnescape(s+len);			  }		  }	  }	  /* str now points after the end of the value.		 skip over whitespace, ';', whitespace. */	  while (IS_SPACE (*str)) str++;	  if (*str == ';') str++;	  while (IS_SPACE (*str)) str++;	}  return s;}