Tue, 31 Jul 2001 01:00:39 +0000
[gaim-migrate @ 2096]
moving protocols from plugins/ to src/protocols. making it so that you can select which protocols are compiled statically.
| 2086 | 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 | /* xstream 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 | /******* internal expat callbacks *********/ | |
| 25 | void _xstream_startElement(xstream xs, const char* name, const char** atts) | |
| 26 | { | |
| 27 | pool p; | |
| 28 | ||
| 29 | /* if xstream is bad, get outa here */ | |
| 30 | if(xs->status > XSTREAM_NODE) return; | |
| 31 | ||
| 32 | if(xs->node == NULL) | |
| 33 | { | |
| 34 | p = pool_heap(5*1024); /* 5k, typically 1-2k each plus copy of self and workspace */ | |
| 35 | xs->node = xmlnode_new_tag_pool(p,name); | |
| 36 | xmlnode_put_expat_attribs(xs->node, atts); | |
| 37 | ||
| 38 | if(xs->status == XSTREAM_ROOT) | |
| 39 | { | |
| 40 | xs->status = XSTREAM_NODE; /* flag status that we're processing nodes now */ | |
| 41 | (xs->f)(XSTREAM_ROOT, xs->node, xs->arg); /* send the root, f must free all nodes */ | |
| 42 | xs->node = NULL; | |
| 43 | } | |
| 44 | }else{ | |
| 45 | xs->node = xmlnode_insert_tag(xs->node, name); | |
| 46 | xmlnode_put_expat_attribs(xs->node, atts); | |
| 47 | } | |
| 48 | ||
| 49 | /* depth check */ | |
| 50 | xs->depth++; | |
| 51 | if(xs->depth > XSTREAM_MAXDEPTH) | |
| 52 | xs->status = XSTREAM_ERR; | |
| 53 | } | |
| 54 | ||
| 55 | ||
| 56 | void _xstream_endElement(xstream xs, const char* name) | |
| 57 | { | |
| 58 | xmlnode parent; | |
| 59 | ||
| 60 | /* if xstream is bad, get outa here */ | |
| 61 | if(xs->status > XSTREAM_NODE) return; | |
| 62 | ||
| 63 | /* if it's already NULL we've received </stream>, tell the app and we're outta here */ | |
| 64 | if(xs->node == NULL) | |
| 65 | { | |
| 66 | xs->status = XSTREAM_CLOSE; | |
| 67 | (xs->f)(XSTREAM_CLOSE, NULL, xs->arg); | |
| 68 | }else{ | |
| 69 | parent = xmlnode_get_parent(xs->node); | |
| 70 | ||
| 71 | /* we are the top-most node, feed to the app who is responsible to delete it */ | |
| 72 | if(parent == NULL) | |
| 73 | (xs->f)(XSTREAM_NODE, xs->node, xs->arg); | |
| 74 | ||
| 75 | xs->node = parent; | |
| 76 | } | |
| 77 | xs->depth--; | |
| 78 | } | |
| 79 | ||
| 80 | ||
| 81 | void _xstream_charData(xstream xs, const char *str, int len) | |
| 82 | { | |
| 83 | /* if xstream is bad, get outa here */ | |
| 84 | if(xs->status > XSTREAM_NODE) return; | |
| 85 | ||
| 86 | if(xs->node == NULL) | |
| 87 | { | |
| 88 | /* we must be in the root of the stream where CDATA is irrelevant */ | |
| 89 | return; | |
| 90 | } | |
| 91 | ||
| 92 | xmlnode_insert_cdata(xs->node, str, len); | |
| 93 | } | |
| 94 | ||
| 95 | ||
| 96 | void _xstream_cleanup(void *arg) | |
| 97 | { | |
| 98 | xstream xs = (xstream)arg; | |
| 99 | ||
| 100 | xmlnode_free(xs->node); /* cleanup anything left over */ | |
| 101 | XML_ParserFree(xs->parser); | |
| 102 | } | |
| 103 | ||
| 104 | ||
| 105 | /* creates a new xstream with given pool, xstream will be cleaned up w/ pool */ | |
| 106 | xstream xstream_new(pool p, xstream_onNode f, void *arg) | |
| 107 | { | |
| 108 | xstream newx; | |
| 109 | ||
| 110 | if(p == NULL || f == NULL) | |
| 111 | { | |
| 112 | fprintf(stderr,"Fatal Programming Error: xstream_new() was improperly called with NULL.\n"); | |
| 113 | return NULL; | |
| 114 | } | |
| 115 | ||
| 116 | newx = pmalloco(p, sizeof(_xstream)); | |
| 117 | newx->p = p; | |
| 118 | newx->f = f; | |
| 119 | newx->arg = arg; | |
| 120 | ||
| 121 | /* create expat parser and ensure cleanup */ | |
| 122 | newx->parser = XML_ParserCreate(NULL); | |
| 123 | XML_SetUserData(newx->parser, (void *)newx); | |
| 124 | XML_SetElementHandler(newx->parser, (void *)_xstream_startElement, (void *)_xstream_endElement); | |
| 125 | XML_SetCharacterDataHandler(newx->parser, (void *)_xstream_charData); | |
| 126 | pool_cleanup(p, _xstream_cleanup, (void *)newx); | |
| 127 | ||
| 128 | return newx; | |
| 129 | } | |
| 130 | ||
| 131 | /* attempts to parse the buff onto this stream firing events to the handler, returns the last known status */ | |
| 132 | int xstream_eat(xstream xs, char *buff, int len) | |
| 133 | { | |
| 134 | char *err; | |
| 135 | xmlnode xerr; | |
| 136 | static char maxerr[] = "maximum node size reached"; | |
| 137 | static char deeperr[] = "maximum node depth reached"; | |
| 138 | ||
| 139 | if(xs == NULL) | |
| 140 | { | |
| 141 | fprintf(stderr,"Fatal Programming Error: xstream_eat() was improperly called with NULL.\n"); | |
| 142 | return XSTREAM_ERR; | |
| 143 | } | |
| 144 | ||
| 145 | if(len == 0 || buff == NULL) | |
| 146 | return xs->status; | |
| 147 | ||
| 148 | if(len == -1) /* easy for hand-fed eat calls */ | |
| 149 | len = strlen(buff); | |
| 150 | ||
| 151 | if(!XML_Parse(xs->parser, buff, len, 0)) | |
| 152 | { | |
| 153 | err = (char *)XML_ErrorString(XML_GetErrorCode(xs->parser)); | |
| 154 | xs->status = XSTREAM_ERR; | |
| 155 | }else if(pool_size(xmlnode_pool(xs->node)) > XSTREAM_MAXNODE || xs->cdata_len > XSTREAM_MAXNODE){ | |
| 156 | err = maxerr; | |
| 157 | xs->status = XSTREAM_ERR; | |
| 158 | }else if(xs->status == XSTREAM_ERR){ /* set within expat handlers */ | |
| 159 | err = deeperr; | |
| 160 | } | |
| 161 | ||
| 162 | /* fire parsing error event, make a node containing the error string */ | |
| 163 | if(xs->status == XSTREAM_ERR) | |
| 164 | { | |
| 165 | xerr = xmlnode_new_tag("error"); | |
| 166 | xmlnode_insert_cdata(xerr,err,-1); | |
| 167 | (xs->f)(XSTREAM_ERR, xerr, xs->arg); | |
| 168 | } | |
| 169 | ||
| 170 | return xs->status; | |
| 171 | } | |
| 172 | ||
| 173 | ||
| 174 | /* STREAM CREATION UTILITIES */ | |
| 175 | ||
| 176 | /* give a standard template xmlnode to work from */ | |
| 177 | xmlnode xstream_header(char *namespace, char *to, char *from) | |
| 178 | { | |
| 179 | xmlnode x; | |
| 180 | char id[10]; | |
| 181 | ||
| 182 | sprintf(id,"%X",(int)time(NULL)); | |
| 183 | ||
| 184 | x = xmlnode_new_tag("stream:stream"); | |
| 185 | xmlnode_put_attrib(x, "xmlns:stream", "http://etherx.jabber.org/streams"); | |
| 186 | xmlnode_put_attrib(x, "id", id); | |
| 187 | if(namespace != NULL) | |
| 188 | xmlnode_put_attrib(x, "xmlns", namespace); | |
| 189 | if(to != NULL) | |
| 190 | xmlnode_put_attrib(x, "to", to); | |
| 191 | if(from != NULL) | |
| 192 | xmlnode_put_attrib(x, "from", from); | |
| 193 | ||
| 194 | return x; | |
| 195 | } | |
| 196 | ||
| 197 | /* trim the xmlnode to only the opening header :) [NO CHILDREN ALLOWED] */ | |
| 198 | char *xstream_header_char(xmlnode x) | |
| 199 | { | |
| 200 | spool s; | |
| 201 | char *fixr, *head; | |
| 202 | ||
| 203 | if(xmlnode_has_children(x)) | |
| 204 | { | |
| 205 | fprintf(stderr,"Fatal Programming Error: xstream_header_char() was sent a header with children!\n"); | |
| 206 | return NULL; | |
| 207 | } | |
| 208 | ||
| 209 | s = spool_new(xmlnode_pool(x)); | |
| 210 | spooler(s,"<?xml version='1.0'?>",xmlnode2str(x),s); | |
| 211 | head = spool_print(s); | |
| 212 | fixr = strstr(head,"/>"); | |
| 213 | *fixr = '>'; | |
| 214 | ++fixr; | |
| 215 | *fixr = '\0'; | |
| 216 | ||
| 217 | return head; | |
| 218 | } | |
| 219 |