source: trunk/third/jwgc/lib/libxode/xstream.c @ 22406

Revision 22406, 5.6 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22405, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 *  This program is free software; you can redistribute it and/or modify
3 *  it under the terms of the GNU General Public License as published by
4 *  the Free Software Foundation; either version 2 of the License, or
5 *  (at your option) any later version.
6 *
7 *  This program is distributed in the hope that it will be useful,
8 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *  GNU General Public License for more details.
11 *
12 *  You should have received a copy of the GNU General Public License
13 *  along with this program; if not, write to the Free Software
14 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 *  Jabber
17 *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
18 */
19
20#include <libxode.h>
21
22/* xode_stream is a way to have a consistent method of handling incoming XML Stream based events... it doesn't handle the generation of an XML Stream, but provides some facilities to help do that */
23
24
25static void _xode_put_expatattribs(xode owner, const char** atts)
26{
27    int i = 0;
28    if (atts == NULL) return;
29    while (atts[i] != '\0')
30    {
31        xode_put_attrib(owner, atts[i], atts[i+1]);
32        i += 2;
33    }
34}
35
36/******* internal expat callbacks *********/
37static void _xode_stream_startElement(xode_stream xs, const char* name, const char** atts)
38{
39    xode_pool p;
40
41    /* if xode_stream is bad, get outa here */
42    if(xs->status > XODE_STREAM_NODE) return;
43
44    if(xs->node == NULL)
45    {
46        p = xode_pool_heap(5*1024); /* 5k, typically 1-2k each plus copy of self and workspace */
47        xs->node = xode_new_frompool(p,name);
48        _xode_put_expatattribs(xs->node, atts);
49
50        if(xs->status == XODE_STREAM_ROOT)
51        {
52            xs->status = XODE_STREAM_NODE; /* flag status that we're processing nodes now */
53            (xs->f)(XODE_STREAM_ROOT, xs->node, xs->arg); /* send the root, f must free all nodes */
54            xs->node = NULL;
55        }
56    }else{
57        xs->node = xode_insert_tag(xs->node, name);
58        _xode_put_expatattribs(xs->node, atts);
59    }
60
61    /* depth check */
62    xs->depth++;
63    if(xs->depth > XODE_STREAM_MAXDEPTH)
64        xs->status = XODE_STREAM_ERROR;
65}
66
67
68static void _xode_stream_endElement(xode_stream xs, const char* name)
69{
70    xode parent;
71
72    /* if xode_stream is bad, get outa here */
73    if(xs->status > XODE_STREAM_NODE) return;
74
75    /* if it's already NULL we've received </stream>, tell the app and we're outta here */
76    if(xs->node == NULL)
77    {
78        xs->status = XODE_STREAM_CLOSE;
79        (xs->f)(XODE_STREAM_CLOSE, NULL, xs->arg);
80    }else{
81        parent = xode_get_parent(xs->node);
82
83        /* we are the top-most node, feed to the app who is responsible to delete it */
84        if(parent == NULL)
85            (xs->f)(XODE_STREAM_NODE, xs->node, xs->arg);
86
87        xs->node = parent;
88    }
89    xs->depth--;
90}
91
92
93static void _xode_stream_charData(xode_stream xs, const char *str, int len)
94{
95    /* if xode_stream is bad, get outa here */
96    if(xs->status > XODE_STREAM_NODE) return;
97
98    if(xs->node == NULL)
99    {
100        /* we must be in the root of the stream where CDATA is irrelevant */
101        return;
102    }
103
104    xode_insert_cdata(xs->node, str, len);
105}
106
107
108static void _xode_stream_cleanup(void *arg)
109{
110    xode_stream xs = (xode_stream)arg;
111
112    xode_free(xs->node); /* cleanup anything left over */
113    XML_ParserFree(xs->parser);
114}
115
116
117/* creates a new xode_stream with given pool, xode_stream will be cleaned up w/ pool */
118xode_stream xode_stream_new(xode_pool p, xode_stream_onNode f, void *arg)
119{
120    xode_stream newx;
121
122    if(p == NULL || f == NULL)
123    {
124        fprintf(stderr,"Fatal Programming Error: xode_streamnew() was improperly called with NULL.\n");
125        return NULL;
126    }
127
128    newx = xode_pool_malloco(p, sizeof(_xode_stream));
129    newx->p = p;
130    newx->f = f;
131    newx->arg = arg;
132
133    /* create expat parser and ensure cleanup */
134    newx->parser = XML_ParserCreate(NULL);
135    XML_SetUserData(newx->parser, (void *)newx);
136    XML_SetElementHandler(newx->parser, (void *)_xode_stream_startElement, (void *)_xode_stream_endElement);
137    XML_SetCharacterDataHandler(newx->parser, (void *)_xode_stream_charData);
138    xode_pool_cleanup(p, _xode_stream_cleanup, (void *)newx);
139
140    return newx;
141}
142
143/* attempts to parse the buff onto this stream firing events to the handler, returns the last known status */
144int xode_stream_eat(xode_stream xs, char *buff, int len)
145{
146    char *err;
147    xode xerr;
148    static char maxerr[] = "maximum node size reached";
149    static char deeperr[] = "maximum node depth reached";
150
151    if(xs == NULL)
152    {
153        fprintf(stderr,"Fatal Programming Error: xode_streameat() was improperly called with NULL.\n");
154        return XODE_STREAM_ERROR;
155    }
156
157    if(len == 0 || buff == NULL)
158        return xs->status;
159
160    if(len == -1) /* easy for hand-fed eat calls */
161        len = strlen(buff);
162
163    if(!XML_Parse(xs->parser, buff, len, 0))
164    {
165        err = (char *)XML_ErrorString(XML_GetErrorCode(xs->parser));
166        xs->status = XODE_STREAM_ERROR;
167    }else if(xode_pool_size(xode_get_pool(xs->node)) > XODE_STREAM_MAXNODE || xs->cdata_len > XODE_STREAM_MAXNODE){
168        err = maxerr;
169        xs->status = XODE_STREAM_ERROR;
170    }else if(xs->status == XODE_STREAM_ERROR){ /* set within expat handlers */
171        err = deeperr;
172    }
173
174    /* fire parsing error event, make a node containing the error string */
175    if(xs->status == XODE_STREAM_ERROR)
176    {
177        xerr = xode_new("error");
178        xode_insert_cdata(xerr,err,-1);
179        (xs->f)(XODE_STREAM_ERROR, xerr, xs->arg);
180    }
181
182    return xs->status;
183}
Note: See TracBrowser for help on using the repository browser.