CTRACE(tfp, "LYHandleMETA: HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n",
CTRACE((tfp, "LYHandleMETA: HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n",
PUBLIC void LYHandleMETA ARGS4(	HTStructured *, 	me,	CONST BOOL*,		present,	CONST char **,		value,	char **,		include GCC_UNUSED){    char *http_equiv = NULL, *name = NULL, *content = NULL;    char *href = NULL, *id_string = NULL, *temp = NULL;    char *cp, *cp0, *cp1 = NULL;    int url_type = 0;    if (!me || !present)	return;    /*     *	Load the attributes for possible use by Lynx. - FM     */    if (present[HTML_META_HTTP_EQUIV] &&	value[HTML_META_HTTP_EQUIV] && *value[HTML_META_HTTP_EQUIV]) {	StrAllocCopy(http_equiv, value[HTML_META_HTTP_EQUIV]);	convert_to_spaces(http_equiv, TRUE);	LYUCFullyTranslateString(&http_equiv, me->tag_charset, me->tag_charset,				 NO, NO, YES, st_other);	LYTrimHead(http_equiv);	LYTrimTail(http_equiv);	if (*http_equiv == '\0') {	    FREE(http_equiv);	}    }    if (present[HTML_META_NAME] &&	value[HTML_META_NAME] && *value[HTML_META_NAME]) {	StrAllocCopy(name, value[HTML_META_NAME]);	convert_to_spaces(name, TRUE);	LYUCFullyTranslateString(&name, me->tag_charset, me->tag_charset,				 NO, NO, YES, st_other);	LYTrimHead(name);	LYTrimTail(name);	if (*name == '\0') {	    FREE(name);	}    }    if (present[HTML_META_CONTENT] &&	value[HTML_META_CONTENT] && *value[HTML_META_CONTENT]) {	/*	 *  Technically, we should be creating a comma-separated	 *  list, but META tags come one at a time, and we'll	 *  handle (or ignore) them as each is received.  Also,	 *  at this point, we only trim leading and trailing	 *  blanks from the CONTENT value, without translating	 *  any named entities or numeric character references,	 *  because how we should do that depends on what type	 *  of information it contains, and whether or not any	 *  of it might be sent to the screen. - FM	 */	StrAllocCopy(content, value[HTML_META_CONTENT]);	convert_to_spaces(content, FALSE);	LYTrimHead(content);	LYTrimTail(content);	if (*content == '\0') {	    FREE(content);	}    }    CTRACE(tfp, "LYHandleMETA: HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n",		(http_equiv ? http_equiv : "NULL"),		(name ? name : "NULL"),		(content ? content : "NULL"));    /*     *	Make sure we have META name/value pairs to handle. - FM     */    if (!(http_equiv || name) || !content)	goto free_META_copies;    /*     * Check for a no-cache Pragma     * or Cache-Control directive. - FM     */    if (!strcasecomp((http_equiv ? http_equiv : ""), "Pragma") ||	!strcasecomp((http_equiv ? http_equiv : ""), "Cache-Control")) {	LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,				 NO, NO, YES, st_other);	LYTrimHead(content);	LYTrimTail(content);	if (!strcasecomp(content, "no-cache")) {	    me->node_anchor->no_cache = TRUE;	    HText_setNoCache(me->text);	}	/*	 *  If we didn't get a Cache-Control MIME header,	 *  and the META has one, convert to lowercase,	 *  store it in the anchor element, and if we	 *  haven't yet set no_cache, check whether we	 *  should. - FM	 */	if ((!me->node_anchor->cache_control) &&	    !strcasecomp((http_equiv ? http_equiv : ""), "Cache-Control")) {	    LYLowerCase(content);	    StrAllocCopy(me->node_anchor->cache_control, content);	    if (me->node_anchor->no_cache == FALSE) {		cp0 = content;		while ((cp = strstr(cp0, "no-cache")) != NULL) {		    cp += 8;		    while (*cp != '\0' && WHITE(*cp))			cp++;		    if (*cp == '\0' || *cp == ';') {			me->node_anchor->no_cache = TRUE;			HText_setNoCache(me->text);			break;		    }		    cp0 = cp;		}		if (me->node_anchor->no_cache == TRUE)		    goto free_META_copies;		cp0 = content;		while ((cp = strstr(cp0, "max-age")) != NULL) {		    cp += 7;		    while (*cp != '\0' && WHITE(*cp))			cp++;		    if (*cp == '=') {			cp++;			while (*cp != '\0' && WHITE(*cp))			    cp++;			if (isdigit((unsigned char)*cp)) {			    cp0 = cp;			    while (isdigit((unsigned char)*cp))				cp++;			    if (*cp0 == '0' && cp == (cp0 + 1)) {				me->node_anchor->no_cache = TRUE;				HText_setNoCache(me->text);				break;			    }			}		    }		    cp0 = cp;		}	    }	}    /*     * Check for an Expires directive. - FM     */    } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Expires")) {	/*	 *  If we didn't get an Expires MIME header,	 *  store it in the anchor element, and if we	 *  haven't yet set no_cache, check whether we	 *  should.  Note that we don't accept a Date	 *  header via META tags, because it's likely	 *  to be untrustworthy, but do check for a	 *  Date header from a server when making the	 *  comparison. - FM	 */	LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,				 NO, NO, YES, st_other);	LYTrimHead(content);	LYTrimTail(content);	StrAllocCopy(me->node_anchor->expires, content);	if (me->node_anchor->no_cache == FALSE) {	    if (!strcmp(content, "0")) {		/*		 *  The value is zero, which we treat as		 *  an absolute no-cache directive. - FM		 */		me->node_anchor->no_cache = TRUE;		HText_setNoCache(me->text);	    } else if (me->node_anchor->date != NULL) {		/*		 *  We have a Date header, so check if		 *  the value is less than or equal to		 *  that. - FM		 */		if (LYmktime(content, TRUE) <=		    LYmktime(me->node_anchor->date, TRUE)) {		    me->node_anchor->no_cache = TRUE;		    HText_setNoCache(me->text);		}	    } else if (LYmktime(content, FALSE) <= 0) {		/*		 *  We don't have a Date header, and		 *  the value is in past for us. - FM		 */		me->node_anchor->no_cache = TRUE;		HText_setNoCache(me->text);	    }	}    /*     *	Check for a text/html Content-Type with a     *	charset directive, if we didn't already set     *	the charset via a server's header. - AAC & FM     */    } else if (!(me->node_anchor->charset && *me->node_anchor->charset) &&	       !strcasecomp((http_equiv ? http_equiv : ""), "Content-Type")) {	LYUCcharset * p_in = NULL;	LYUCcharset * p_out = NULL;	LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,				 NO, NO, YES, st_other);	LYTrimHead(content);	LYTrimTail(content);	LYLowerCase(content);	if ((cp = strstr(content, "text/html;")) != NULL &&	    (cp1 = strstr(content, "charset")) != NULL &&	    cp1 > cp) {	    BOOL chartrans_ok = NO;	    char *cp3 = NULL, *cp4;	    int chndl;	    cp1 += 7;	    while (*cp1 == ' ' || *cp1 == '=' || *cp1 == '"')		cp1++;	    StrAllocCopy(cp3, cp1); /* copy to mutilate more */	    for (cp4 = cp3; (*cp4 != '\0' && *cp4 != '"' &&			     *cp4 != ';'  && *cp4 != ':' &&			     !WHITE(*cp4)); cp4++) {		; /* do nothing */	    }	    *cp4 = '\0';	    cp4 = cp3;	    chndl = UCGetLYhndl_byMIME(cp3);	    if (UCCanTranslateFromTo(chndl, current_char_set)) {		chartrans_ok = YES;		StrAllocCopy(me->node_anchor->charset, cp4);		HTAnchor_setUCInfoStage(me->node_anchor, chndl,					UCT_STAGE_PARSER,					UCT_SETBY_STRUCTURED);	    } else if (chndl < 0) {		/*		 *  Got something but we don't recognize it.		 */		chndl = UCLYhndl_for_unrec;		if (chndl < 0) /* UCLYhndl_for_unrec not defined :-( */		     chndl = UCLYhndl_for_unspec; /* always >= 0 */		if (UCCanTranslateFromTo(chndl, current_char_set)) {		    chartrans_ok = YES;		    HTAnchor_setUCInfoStage(me->node_anchor, chndl,					    UCT_STAGE_PARSER,					    UCT_SETBY_STRUCTURED);		}	    }	    if (chartrans_ok) {		p_in = HTAnchor_getUCInfoStage(me->node_anchor,					       UCT_STAGE_PARSER);		p_out = HTAnchor_setUCInfoStage(me->node_anchor,						current_char_set,						UCT_STAGE_HTEXT,						UCT_SETBY_DEFAULT);		if (!p_out) {		    /*		     *	Try again.		     */		    p_out = HTAnchor_getUCInfoStage(me->node_anchor,						    UCT_STAGE_HTEXT);		}		if (!strcmp(p_in->MIMEname, "x-transparent")) {		    HTPassEightBitRaw = TRUE;		    HTAnchor_setUCInfoStage(me->node_anchor,				HTAnchor_getUCLYhndl(me->node_anchor,						     UCT_STAGE_HTEXT),						     UCT_STAGE_PARSER,						     UCT_SETBY_DEFAULT);		}		if (!strcmp(p_out->MIMEname, "x-transparent")) {		    HTPassEightBitRaw = TRUE;		    HTAnchor_setUCInfoStage(me->node_anchor,				HTAnchor_getUCLYhndl(me->node_anchor,						     UCT_STAGE_PARSER),					    UCT_STAGE_HTEXT,					    UCT_SETBY_DEFAULT);		}		if (p_in->enc != UCT_ENC_CJK) {		    HTCJK = NOCJK;		    if (!(p_in->codepoints &			  UCT_CP_SUBSETOF_LAT1) &&			chndl == current_char_set) {			HTPassEightBitRaw = TRUE;		    }		} else if (p_out->enc == UCT_ENC_CJK) {		    Set_HTCJK(p_in->MIMEname, p_out->MIMEname);		}		LYGetChartransInfo(me);		/*		**  Update the chartrans info homologously to		**  a Content-Type MIME header with a charset		**  parameter. - FM		*/		if (me->UCLYhndl != chndl) {		    HTAnchor_setUCInfoStage(me->node_anchor, chndl,					    UCT_STAGE_MIME,					    UCT_SETBY_STRUCTURED);		    HTAnchor_setUCInfoStage(me->node_anchor, chndl,					    UCT_STAGE_PARSER,					    UCT_SETBY_STRUCTURED);		    me->inUCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,							  UCT_STAGE_PARSER);		    me->inUCI = HTAnchor_getUCInfoStage(me->node_anchor,							UCT_STAGE_PARSER);		}		UCSetTransParams(&me->T,				 me->inUCLYhndl, me->inUCI,				 me->outUCLYhndl, me->outUCI);	    } else {		/*		 *  Cannot translate.		 *  If according to some heuristic the given		 *  charset and the current display character		 *  both are likely to be like ISO-8859 in		 *  structure, pretend we have some kind		 *  of match.		 */		BOOL given_is_8859		    = (!strncmp(cp4, "iso-8859-", 9) &&		       isdigit((unsigned char)cp4[9]));		BOOL given_is_8859like		    = (given_is_8859 || !strncmp(cp4, "windows-", 8) ||			!strncmp(cp4, "cp12", 4) ||			!strncmp(cp4, "cp-12", 5));		BOOL given_and_display_8859like		    = (given_is_8859like &&		       (strstr(LYchar_set_names[current_char_set],			       "ISO-8859") ||			strstr(LYchar_set_names[current_char_set],			       "windows-")));		if (given_is_8859) {		    cp1 = &cp4[10];		    while (*cp1 &&			   isdigit((unsigned char)(*cp1)))			cp1++;		    *cp1 = '\0';		}		if (given_and_display_8859like) {		    StrAllocCopy(me->node_anchor->charset, cp4);		    HTPassEightBitRaw = TRUE;		}		HTAlert(*cp4 ? cp4 : me->node_anchor->charset);	    }	    FREE(cp3);	    if (me->node_anchor->charset) {		CTRACE(tfp,			"LYHandleMETA: New charset: %s\n",			me->node_anchor->charset);	    }	}	/*	 *  Set the kcode element based on the charset. - FM	 */	HText_setKcode(me->text, me->node_anchor->charset, p_in);    /*     *	Check for a Refresh directive. - FM     */    } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Refresh")) {	char *Seconds = NULL;	/*	 *  Look for the Seconds field. - FM	 */	cp = LYSkipBlanks(content);	if (*cp && isdigit(*cp)) {	    cp1 = cp;	    while (*cp1 && isdigit(*cp1))		cp1++;	    if (*cp1)		*cp1++ = '\0';	    StrAllocCopy(Seconds, cp);	}	if (Seconds) {	    /*	     *	We have the seconds field.	     *	Now look for a URL field - FM	     */	    while (*cp1) {		if (!strncasecomp(cp1, "URL", 3)) {		    cp = (cp1 + 3);		    while (*cp && (*cp == '=' || isspace((unsigned char)*cp)))			cp++;		    cp1 = cp;		    while (*cp1 && !isspace((unsigned char)*cp1))			cp1++;		    *cp1 = '\0';		    if (*cp)			StrAllocCopy(href, cp);		    break;		}		cp1++;	    }	    if (href) {		/*		 *  We found a URL field, so check it out. - FM		 */		if (!(url_type = LYLegitimizeHREF(me, (char**)&href,						  TRUE, FALSE))) {		    /*		     *	The specs require a complete URL,		     *	but this is a Netscapism, so don't		     *	expect the author to know that. - FM		     */		    HTUserMsg(REFRESH_URL_NOT_ABSOLUTE);		    /*		     *	Use the document's address		     *	as the base. - FM		     */		    if (*href != '\0') {			temp = HTParse(href,				       me->node_anchor->address, PARSE_ALL);			StrAllocCopy(href, temp);			FREE(temp);		    } else {			StrAllocCopy(href, me->node_anchor->address);			HText_setNoCache(me->text);		    }		}		/*		 *  Check whether to fill in localhost. - FM		 */		LYFillLocalFileURL((char **)&href,				   (me->inBASE ?				 me->base_href : me->node_anchor->address));		/*		 *  Set the no_cache flag if the Refresh URL		 *  is the same as the document's address. - FM		 */		if (!strcmp(href, me->node_anchor->address)) {		    HText_setNoCache(me->text);		}	    } else {		/*		 *  We didn't find a URL field, so use		 *  the document's own address and set		 *  the no_cache flag. - FM		 */		StrAllocCopy(href, me->node_anchor->address);		HText_setNoCache(me->text);	    }	    /*	     *	Check for an anchor in http or https URLs. - FM	     */	    if ((strncmp(href, "http", 4) == 0) &&		(cp = strrchr(href, '#')) != NULL) {		StrAllocCopy(id_string, cp);		*cp = '\0';	    }	    if (me->inA) {		/*		 *  Ugh!  The META tag, which is a HEAD element,		 *  is in an Anchor, which is BODY element.  All		 *  we can do is close the Anchor and cross our		 *  fingers. - FM		 */		if (me->inBoldA == TRUE && me->inBoldH == FALSE)		    HText_appendCharacter(me->text, LY_BOLD_END_CHAR);		me->inBoldA = FALSE;		HText_endAnchor(me->text, me->CurrentANum);		me->inA = FALSE;		me->CurrentANum = 0;	    }	    me->CurrentA = HTAnchor_findChildAndLink(				me->node_anchor,	/* Parent */				id_string,		/* Tag */				href,			/* Addresss */				(void *)0);		/* Type */	    if (id_string)		*cp = '#';	    FREE(id_string);	    LYEnsureSingleSpace(me);	    if (me->inUnderline == FALSE)		HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);	    HTML_put_string(me, "REFRESH(");	    HTML_put_string(me, Seconds);	    HTML_put_string(me, " sec):");	    FREE(Seconds);	    if (me->inUnderline == FALSE)		HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);	    HTML_put_character(me, ' ');	    me->in_word = NO;	    HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);	    if (me->inBoldH == FALSE)		HText_appendCharacter(me->text, LY_BOLD_START_CHAR);	    HTML_put_string(me, href);	    FREE(href);	    if (me->inBoldH == FALSE)		HText_appendCharacter(me->text, LY_BOLD_END_CHAR);	    HText_endAnchor(me->text, 0);	    LYEnsureSingleSpace(me);	}    /*     *	Check for a suggested filename via a Content-Disposition with     *	a filename=name.suffix in it, if we don't already have it     *	via a server header. - FM     */    } else if (!(me->node_anchor->SugFname && *me->node_anchor->SugFname) &&	       !strcasecomp((http_equiv ?			     http_equiv : ""), "Content-Disposition")) {	cp = content;	while (*cp != '\0' && strncasecomp(cp, "filename", 8))	    cp++;	if (*cp != '\0') {	    cp += 8;	    while ((*cp != '\0') && (WHITE(*cp) || *cp == '='))		cp++;	    while (*cp != '\0' && WHITE(*cp))		cp++;	    if (*cp != '\0') {		StrAllocCopy(me->node_anchor->SugFname, cp);		if (*me->node_anchor->SugFname == '\"') {		    if ((cp = strchr((me->node_anchor->SugFname + 1),				     '\"')) != NULL) {			*(cp + 1) = '\0';			HTMIME_TrimDoubleQuotes(me->node_anchor->SugFname);		    } else {			FREE(me->node_anchor->SugFname);		    }		    if (me->node_anchor->SugFname != NULL &&			*me->node_anchor->SugFname == '\0') {			FREE(me->node_anchor->SugFname);		    }		}		if ((cp = me->node_anchor->SugFname) != NULL) {		    while (*cp != '\0' && !WHITE(*cp))			cp++;		    *cp = '\0';		    if (*me->node_anchor->SugFname == '\0')			FREE(me->node_anchor->SugFname);		}	    }	}    /*     *	Check for a Set-Cookie directive. - AK     */    } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Set-Cookie")) {	/*	 *  This will need to be updated when Set-Cookie/Set-Cookie2	 *  handling is finalized.  For now, we'll still assume	 *  "historical" cookies in META directives. - FM	 */	url_type = is_url(me->inBASE ?		       me->base_href : me->node_anchor->address);	if (url_type == HTTP_URL_TYPE || url_type == HTTPS_URL_TYPE) {	    LYSetCookie(content,			NULL,			(me->inBASE ?		      me->base_href : me->node_anchor->address));	}    }    /*     *	Free the copies. - FM     */free_META_copies:    FREE(http_equiv);    FREE(name);    FREE(content);}