Annotation of libwww/Library/src/HTXML.c, revision 2.9

2.1       frystyk     1: /*
                      2: **     LIBWWW STREAM WRAPPER FOR EXPAT XML PARSER
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
2.9     ! kahan       6: **     @(#) $Id: HTXML.c,v 2.8 2000/08/30 07:03:52 kahan Exp $
2.1       frystyk     7: **
                      8: **     This module requires expat in order to compile/link
                      9: */
                     10: 
                     11: /* Library include files */
                     12: #include "wwwsys.h"
                     13: #include "WWWUtil.h"
                     14: #include "WWWCore.h"
2.7       kahan      15: 
                     16: /* 2000-29-08 JK : pre-pruning code out of libwww */
2.8       kahan      17: #ifdef HT_STRUCT_XML_STREAM 
2.7       kahan      18: #undef HT_STRUCT_XML_STREAM
                     19: #endif
                     20: 
                     21: #ifdef HT_STRUCT_XML_STREAM
2.5       frystyk    22: #include "SGML.h"
2.7       kahan      23: #endif /* HT_STRUCT_XML_STREAM */
2.2       frystyk    24: #include "HTXML.h"                                      /* Implemented here */
2.1       frystyk    25: 
2.2       frystyk    26: #define XML_MAX_ATTRIBUTES 50
2.1       frystyk    27: 
                     28: struct _HTStream {
                     29:     const HTStreamClass *      isa;
                     30:     int                                state;
                     31:     HTRequest *                        request;
2.2       frystyk    32:     HTStream *                  target;
                     33:     HTStructuredClass *         actions;       
                     34:     HTStructured *              starget;       
2.1       frystyk    35:     XML_Parser                         xmlstream;
2.7       kahan      36: #ifdef HT_STRUCT_XML_STREAM
2.2       frystyk    37:     SGML_dtd *                  dtd;
2.7       kahan      38: #endif /* HT_STRUCT_XML_STREAM */
2.2       frystyk    39:     XML_StartElementHandler     xml_start_element;
                     40:     XML_EndElementHandler       xml_end_element;
                     41:     XML_CharacterDataHandler    xml_character_data;
                     42:     XML_DefaultHandler          xml_default_handler;
                     43:     void *                      xml_user_data;
2.1       frystyk    44: };
                     45: 
2.6       frystyk    46: /* @@@ SHould not be global but controlled by name spaces @@@ */
                     47: PRIVATE HTXMLCallback_new *    XMLInstance = NULL;
                     48: PRIVATE void *                 XMLInstanceContext = NULL;
2.2       frystyk    49: 
2.1       frystyk    50: /* ------------------------------------------------------------------------- */
                     51: 
                     52: PRIVATE int HTXML_flush (HTStream * me)
                     53: {
2.2       frystyk    54:     if(me->target)
                     55:        return (*me->target->isa->flush)(me->target);
                     56:     else if (me->starget)
                     57:        return (*me->actions->flush)(me->starget);
                     58:     return HT_OK;
2.1       frystyk    59: }
                     60: 
                     61: PRIVATE int HTXML_free (HTStream * me)
                     62: {
                     63:     int status = HT_OK;
                     64:     XML_ParserFree(me->xmlstream);
2.2       frystyk    65:     if (me->target) {
                     66:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                     67:            return HT_WOULD_BLOCK;
                     68:     } else if(me->starget) {
                     69:       if ((status = (*me->actions->_free)(me->starget)) == HT_WOULD_BLOCK)
                     70:            return HT_WOULD_BLOCK;
                     71:     }
2.3       frystyk    72:     HTTRACE(XML_TRACE, "XML Parser.. FREEING...\n");
2.1       frystyk    73:     HT_FREE(me);
                     74:     return status;
                     75: }
                     76: 
                     77: PRIVATE int HTXML_abort (HTStream * me, HTList * e)
                     78: {
2.3       frystyk    79:     HTTRACE(XML_TRACE, "XML Parser.. ABORTING...\n");
2.1       frystyk    80:     XML_ParserFree(me->xmlstream);
2.2       frystyk    81:     if (me->target)    
                     82:        (*me->target->isa->abort)(me->target, NULL);
                     83:     else if (me->starget)      
                     84:        (*me->actions->abort)(me->starget, e);
2.1       frystyk    85:     HT_FREE(me);
                     86:     return HT_ERROR;
                     87: }
                     88: 
                     89: PRIVATE int HTXML_write (HTStream * me, const char * buf, int len)
                     90: {
                     91:     if (me->state == HT_OK) {
                     92:        int status = XML_Parse(me->xmlstream, buf, len, 0);
                     93:        if (!status) {
2.3       frystyk    94:            HTTRACE(XML_TRACE, "XML Parser..  `%s\'\n" _
2.2       frystyk    95:                    (char *)XML_ErrorString(XML_GetErrorCode(me->xmlstream)));
2.1       frystyk    96:            me->state = HT_ERROR;
                     97:        }
                     98:     }
2.4       frystyk    99: 
                    100:     /* 
                    101:     **  We don't want to return an error here as this kills
                    102:     **  a potential pipeline of requests we might have
                    103:     */
                    104:     return HT_OK;
2.1       frystyk   105: }
                    106: 
                    107: PRIVATE int HTXML_putCharacter (HTStream * me, char c)
                    108: {
                    109:     return HTXML_write(me, &c, 1);
                    110: }
                    111: 
                    112: PRIVATE int HTXML_putString (HTStream * me, const char * s)
                    113: {
                    114:     return HTXML_write(me, s, (int) strlen(s));
                    115: }
                    116: 
2.7       kahan     117: #ifdef HT_STRUCT_XML_STREAM
                    118: 
2.2       frystyk   119: PRIVATE BOOL set_attributes_values(HTTag *tag,BOOL *present,char **value,
                    120:                                   const char *nameatt,const char *valueatt)
                    121: {
                    122:     if(tag && nameatt && valueatt) {
                    123:        int i;
                    124:        HTAttr *attributes= tag->attributes;
                    125:        for(i = 0; i< tag->number_of_attributes ; i++) {
                    126:            if(!strcasecomp(attributes[i].name,nameatt)) {
                    127:                present[i] = TRUE;
                    128:                value[i] = (char *)valueatt;
                    129:                return TRUE;
                    130:            }
                    131:        }
                    132:     }
                    133:     return FALSE;
                    134: }
                    135: 
                    136: PRIVATE void start_element(HTStream *  me,
                    137:                           const XML_Char *name,
                    138:                           const XML_Char **atts)
                    139: {
                    140:     int element_number = 
                    141:        SGML_findElementNumber((SGML_dtd *)me->dtd,(char *)name);
                    142:     if(element_number >= 0) {
                    143:        HTTag *tag = SGML_findTag (me->dtd,element_number);
                    144:        int i = 0;  
                    145:        BOOL present[XML_MAX_ATTRIBUTES];
                    146:        const char *value[XML_MAX_ATTRIBUTES];
                    147:        memset((void *) present, '\0', XML_MAX_ATTRIBUTES);
                    148:        memset((void *) value, '\0', XML_MAX_ATTRIBUTES*sizeof(char *));
                    149: 
                    150:        while(atts[i]) {
                    151:           set_attributes_values(tag,present,(char **)value,atts[i],atts[i+1]);
                    152:            i+=2;
                    153:            /* attributes that are not in the dtd will be lost */
                    154:        }
                    155:        (*me->actions->start_element)
                    156:            (me->starget,element_number,present,value); 
                    157:     } else {
                    158:        /* elements that are not in the dtd will be lost */     
                    159:     }
                    160: }
                    161: 
                    162: PRIVATE void end_element(HTStream * me, const XML_Char *name)
                    163: {
                    164:     int element_number = SGML_findElementNumber(me->dtd,(char *)name);
                    165: 
                    166:     if(element_number > 0) {
                    167:        (*me->actions->end_element)(me->starget, element_number);
                    168:     } else {
                    169:        /* elements that are not in the dtd will be lost */     
                    170:     }
                    171: }
                    172: PRIVATE void character_data(HTStream *me, const XML_Char *s, int len)
                    173: {
                    174:     (*me->actions->put_block)(me->starget, s, len);
                    175: }
                    176: 
                    177: PRIVATE void default_handler(HTStream *me, const XML_Char *s, int len)
                    178: {
                    179:     if(s[0] == '&' && s[len-1]==';') {
                    180:        (*me->actions->unparsed_entity)(me->starget, s,len);
                    181:     } else {
                    182:        /* characters that can not be parsed are lost */
                    183:     }
                    184: }
                    185: 
2.7       kahan     186: #endif /* HT_STRUCT_XML_STREAM */
                    187: 
2.1       frystyk   188: PRIVATE const HTStreamClass HTXMLClass =
                    189: {              
                    190:     "xml",
                    191:     HTXML_flush,
                    192:     HTXML_free,
                    193:     HTXML_abort,
                    194:     HTXML_putCharacter,
                    195:     HTXML_putString,
                    196:     HTXML_write
                    197: }; 
                    198: 
                    199: PUBLIC HTStream * HTXML_new (HTRequest *       request,
                    200:                             void *             param,
                    201:                             HTFormat           input_format,
                    202:                             HTFormat           output_format,
                    203:                             HTStream *         output_stream)
                    204: {
                    205:     HTStream * me = NULL;
                    206:     HTCharset charset = HTResponse_charset (HTRequest_response(request));
                    207:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    208:        HT_OUTOFMEM("HTXML_new");
                    209:     me->isa = &HTXMLClass;
                    210:     me->state = HT_OK;
                    211:     me->request = request;
                    212:     me->target = output_stream ? output_stream : HTErrorStream();
                    213: 
                    214:     /* Now create the XML parser instance */
                    215:     if ((me->xmlstream = XML_ParserCreate(HTAtom_name(charset))) == NULL) {
                    216:        HT_FREE(me);
                    217:        return HTErrorStream();
                    218:     }
2.3       frystyk   219:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   220:     
                    221:     /* Call the stream callback handler (if any) with this new stream */
2.6       frystyk   222:     if (XMLInstance)
                    223:        (*XMLInstance)(me, request, output_format, output_stream, me->xmlstream, XMLInstanceContext);
2.2       frystyk   224: 
2.1       frystyk   225:     return me;
2.2       frystyk   226: }
                    227: 
2.6       frystyk   228: PUBLIC BOOL HTXMLCallback_registerNew (HTXMLCallback_new * me, void * context)
2.2       frystyk   229: {
2.6       frystyk   230:     XMLInstance = me;
                    231:     XMLInstanceContext = context;
2.2       frystyk   232:     return YES;
                    233: }
                    234: 
2.7       kahan     235: #ifdef HT_STRUCT_XML_STREAM
                    236: 
2.9     ! kahan     237: PRIVATE HTStream * HTXMLStructured_new (const SGML_dtd * dtd, HTStructured * starget)
2.2       frystyk   238: {
                    239:     HTStream * me = NULL;
                    240:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    241:        HT_OUTOFMEM("HTXML_new");
                    242:     me->isa = &HTXMLClass;
                    243:     me->state = HT_OK;
                    244:     me->starget = starget;
                    245:     me->dtd = (SGML_dtd *)dtd; 
                    246:     me->actions = (HTStructuredClass*)(((HTStream*)starget)->isa);
                    247: 
                    248:     /* Now create the XML parser instance */
                    249:     if ((me->xmlstream = XML_ParserCreate(NULL)) == NULL) {
                    250:        HT_FREE(me);
                    251:        return HTErrorStream();
                    252:     }
                    253:     XML_SetUserData(me->xmlstream,me);
                    254:     XML_SetElementHandler(me->xmlstream,
                    255:                          (XML_StartElementHandler)start_element, 
                    256:                          (XML_EndElementHandler)end_element);
                    257:     XML_SetCharacterDataHandler(me->xmlstream,  
                    258:                                (XML_CharacterDataHandler)character_data);
                    259:     XML_SetDefaultHandler(me->xmlstream,
                    260:                          (XML_DefaultHandler)default_handler);
                    261: 
2.3       frystyk   262:     HTTRACE(XML_TRACE, "XML Parser.. Stream created\n");
2.2       frystyk   263:     return me;
                    264: }
                    265: 
2.9     ! kahan     266: PRIVATE BOOL HTXMLStructured_setHandlers (HTStream *                   me,
2.2       frystyk   267:                                         XML_StartElementHandler        start,
                    268:                                         XML_EndElementHandler          end, 
                    269:                                         XML_CharacterDataHandler       char_data,
                    270:                                         XML_DefaultHandler             def_handler)
                    271: {
                    272:     if(me) {
                    273:        me->xml_start_element = start;
                    274:        me->xml_end_element = end;
                    275:        me->xml_character_data = char_data;
                    276:        me->xml_default_handler = def_handler;
                    277:        XML_SetElementHandler(me->xmlstream,start,end);
                    278:        XML_SetCharacterDataHandler(me->xmlstream,char_data);
                    279:        XML_SetDefaultHandler(me->xmlstream,def_handler);
                    280:        return YES;
                    281:     }
                    282:     return NO;
                    283: }
                    284:                        
2.9     ! kahan     285: PRIVATE BOOL HTXMLStructured_setUserData(HTStream *me, void *user_data)
2.2       frystyk   286: {
                    287:     if(me) {
                    288:        me->xml_user_data = user_data;
                    289:        XML_SetUserData(me->xmlstream,me->xml_user_data);
                    290:        return YES;
                    291:     }
                    292:     return NO;
2.1       frystyk   293: }
2.7       kahan     294: 
                    295: #endif /* HT_STRUCT_XML_STREAM */

Webmaster