gecko-dev/network/cnvts/cvpics.c

387 строки
9.0 KiB
C

/* this set of functions parses an incoming stream of HTML and tries to find
* any PICS label within it. It doesn't do anything accept parse the pics label
* and finish
*/
#include "xp.h"
#include "plstr.h"
#include "prmem.h"
#include "netutils.h"
#include "mkselect.h"
#include "mktcp.h"
#include "mkgeturl.h"
#include "mkstream.h"
#include "pa_parse.h"
#include "xpgetstr.h"
#include "layout.h"
#include "pics.h"
typedef enum StatesEnum {
IN_CONTENT,
IN_SCRIPT,
ABOUT_TO_BEGIN_TAG,
IN_BEGIN_TAG,
IN_TAG,
BEGIN_ATTRIBUTE_VALUE,
IN_QUOTED_ATTRIBUTE_VALUE,
IN_BROKEN_QUOTED_ATTRIBUTE_VALUE,
IN_UNQUOTED_ATTRIBUTE_VALUE,
IN_COMMENT,
IN_AMPERSAND_THINGY
} StatesEnum;
#define MAXTAGLEN 15
typedef struct _DataObject {
MWContext *context;
URL_Struct *URL_s;
StatesEnum state;
char tag[MAXTAGLEN+1];
uint tag_index;
int tag_type;
PRBool in_broken_html;
char *tag_data; /* the contents of the current tag */
} DataObject;
extern int MK_CVCOLOR_SOURCE_OF;
PRIVATE void net_BeginPICSLabelFinderTag (DataObject *obj)
{
if(obj->tag_data)
*obj->tag_data = '\0'; /* empty tag_data */
if (obj->tag_type == P_SCRIPT)
{
obj->tag_type = P_UNKNOWN;
}
obj->state = ABOUT_TO_BEGIN_TAG;
return ;
}
PRIVATE void net_EndPICSLabelFinderTag (DataObject *obj)
{
if(obj->in_broken_html)
{
obj->in_broken_html = PR_FALSE;
}
if (obj->tag_type == P_SCRIPT)
{
obj->state = IN_SCRIPT;
}
else
{
obj->state = IN_CONTENT;
}
/* check tag_data for a META tag */
if(obj->tag_data && !PL_strncasecmp(obj->tag_data, "META", 4))
{
PA_Tag tmp_tag;
char *name;
tmp_tag.type = P_META;
tmp_tag.data = (void*)obj->tag_data;
tmp_tag.data_len = PL_strlen((char*)tmp_tag.data);
name = (char *)lo_FetchParamValue(obj->context, &tmp_tag, PARAM_HTTP_EQUIV);
#define PICS_HEADER "PICS-Label"
if(name && !PL_strcasecmp(name, PICS_HEADER))
{
char *label = (char *)lo_FetchParamValue(obj->context, &tmp_tag, PARAM_CONTENT);
if(label)
{
PICS_RatingsStruct * rs = PICS_ParsePICSLable(label);
PR_Free(label);
PICS_CompareToUserSettings(rs, obj->URL_s->address);
PICS_FreeRatingsStruct(rs); /* handles NULL */
}
}
PR_FREEIF(name);
}
return;
}
PRIVATE int net_PICSLabelFinderWrite (NET_StreamClass *stream, CONST char *s, int32 l)
{
int32 i;
CONST char *cp;
DataObject *obj = (DataObject *)stream->data_object;
char tiny_buf[8];
for(i = 0, cp = s; i < l; i++, cp++)
{
switch(obj->state)
{
case IN_CONTENT:
/* do nothing until you find a '<' "<!--" or '&' */
if(*cp == '<')
{
/* XXX we can miss a comment spanning a block boundary */
if(i+4 <= l && !PL_strncmp(cp, "<!--", 4))
{
obj->state = IN_COMMENT;
}
else
{
net_BeginPICSLabelFinderTag(obj);
}
}
else if(*cp == '&')
{
obj->state = IN_AMPERSAND_THINGY;
}
break;
case IN_SCRIPT:
/* do nothing until you find '</SCRIPT>' */
if(*cp == '<')
{
/* XXX we can miss a </SCRIPT> spanning a block boundary */
if(i+8 <= l && !PL_strncasecmp(cp, "</SCRIPT", 8))
{
net_BeginPICSLabelFinderTag(obj);
}
}
break;
case ABOUT_TO_BEGIN_TAG:
/* we have seen the first '<'
* once we see a non-whitespace character
* we will be in the tag identifier
*/
if(*cp == '>')
{
net_EndPICSLabelFinderTag(obj);
}
else if(!NET_IS_SPACE(*cp))
{
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
obj->state = IN_BEGIN_TAG;
obj->tag_index = 0;
obj->tag[obj->tag_index++] = *cp;
}
break;
case IN_BEGIN_TAG:
/* go to the IN_TAG state when we see
* the first whitespace
*/
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
if(NET_IS_SPACE(*cp))
{
obj->state = IN_TAG;
obj->tag[obj->tag_index] = '\0';
obj->tag_type = pa_tokenize_tag(obj->tag);
}
else if(*cp == '>')
{
net_EndPICSLabelFinderTag(obj);
}
else if(*cp == '<')
{
/* protect ourselves from markup */
if(!obj->in_broken_html)
{
obj->in_broken_html = PR_TRUE;
}
}
else
{
if (obj->tag_index < MAXTAGLEN)
obj->tag[obj->tag_index++] = *cp;
}
break;
case IN_TAG:
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
/* do nothing until you find a opening '=' or end '>' */
if(*cp == '=')
{
obj->state = BEGIN_ATTRIBUTE_VALUE;
}
else if(*cp == '>')
{
net_EndPICSLabelFinderTag(obj);
}
break;
case BEGIN_ATTRIBUTE_VALUE:
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
/* when we reach the first non-whitespace
* we will enter the UNQUOTED or the QUOTED
* ATTRIBUTE state
*/
if(!NET_IS_SPACE(*cp))
{
if(*cp == '"')
{
obj->state = IN_QUOTED_ATTRIBUTE_VALUE;
/* no need to jump to the quoted attr handler
* since this char can't be a dangerous char
*/
}
else
{
obj->state = IN_UNQUOTED_ATTRIBUTE_VALUE;
/* need to jump to the unquoted attr handler
* since this char can be a dangerous character
*/
goto unquoted_attribute_jump_point;
}
}
else if(*cp == '>')
{
net_EndPICSLabelFinderTag(obj);
}
break;
case IN_UNQUOTED_ATTRIBUTE_VALUE:
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
unquoted_attribute_jump_point:
/* do nothing until you find a whitespace */
if(NET_IS_SPACE(*cp))
{
obj->state = IN_TAG;
}
else if(*cp == '>')
{
net_EndPICSLabelFinderTag(obj);
}
break;
case IN_QUOTED_ATTRIBUTE_VALUE:
/* capture all tag data */
tiny_buf[0] = *cp;
tiny_buf[1] = '\0';
StrAllocCat(obj->tag_data, tiny_buf);
/* do nothing until you find a closing '"' */
if(*cp == '\"')
{
if(obj->in_broken_html)
{
obj->in_broken_html = PR_FALSE;
}
obj->state = IN_TAG;
}
else if(*cp == '>')
{
/* probably a broken attribute value */
if(!obj->in_broken_html)
{
obj->in_broken_html = PR_TRUE;
}
}
break;
case IN_COMMENT:
/* do nothing until you find a closing '-->' */
if(!PL_strncmp(cp, "-->", 3))
{
cp += 2;
i += 2;
obj->state = IN_CONTENT;
}
break;
case IN_AMPERSAND_THINGY:
/* do nothing until you find a ';' or space */
if(*cp == ';' || NET_IS_SPACE(*cp))
{
sprintf(tiny_buf, "%c", *cp);
obj->state = IN_CONTENT;
}
break;
default:
PR_ASSERT(0);
break;
}
}
return(0);
}
/* is the stream ready for writeing?
*/
PRIVATE unsigned int net_PICSLabelFinderWriteReady (NET_StreamClass *stream)
{
return(MAX_WRITE_READY);
}
PRIVATE void net_PICSLabelFinderComplete (NET_StreamClass *stream)
{
}
PRIVATE void net_PICSLabelFinderAbort (NET_StreamClass *stream, int status)
{
}
PUBLIC NET_StreamClass *
net_PICSLabelFinderStream (int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *window_id)
{
DataObject* obj;
NET_StreamClass *new_stream;
PRBool is_html_stream = PR_FALSE;
TRACEMSG(("Setting up PICSLabelFinder stream. Have URL: %s\n", URL_s->address));
new_stream = PR_NEWZAP(NET_StreamClass);
if(!new_stream)
return NULL;
obj = PR_NEW(DataObject);
if (obj == NULL)
{
PR_Free(new_stream);
return(NULL);
}
memset(obj, 0, sizeof(DataObject));
obj->state = IN_CONTENT;
obj->tag_type = P_UNKNOWN;
obj->context = window_id;
obj->URL_s = URL_s;
new_stream->name = "PICSLabelFinder";
new_stream->complete = (MKStreamCompleteFunc) net_PICSLabelFinderComplete;
new_stream->abort = (MKStreamAbortFunc) net_PICSLabelFinderAbort;
new_stream->put_block = (MKStreamWriteFunc) net_PICSLabelFinderWrite;
new_stream->is_write_ready = (MKStreamWriteReadyFunc)
net_PICSLabelFinderWriteReady;
new_stream->data_object = (void *) obj; /* document info object */
new_stream->window_id = window_id;
/* don't cache this URL, since the content type is wrong */
URL_s->dont_cache = PR_TRUE;
return new_stream;
}