⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mio_xml.c

📁 jabber server jabber server jabber server jabber server
💻 C
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*//** * @file mio_xml.c * @brief handling of XML streams on network connections * * This file implements the functionality used to handle XML streams * over network connections. The user can register a callback, that gets * an event for the open tag for the root element and for the child elements * of the root element (including their child elements). */#include <jabberd.h>/* defined in mio.c */extern char *mio__bounce_uri;/** * internal expat callback for start tags * * @param m the mio * @param name the name of the element * @param attribs attributes of the start tag */void _mio_xstream_startElement(mio m, const char* name, const char** attribs){    /* If stacknode is NULL, we are starting a new packet and must       setup for by pre-allocating some memory */    if (m->stacknode == NULL) {	pool p = pool_heap(5 * 1024); /* 5k, typically 1-2k each, plus copy of self and workspace */	m->stacknode = xmlnode_new_tag_pool(p, name);	xmlnode_put_expat_attribs(m->stacknode, attribs);	/* If the root is 0, this must be the root node.. */	if (m->root == 0) {	    if(m->cb != NULL)		(*(mio_xml_cb)m->cb)(m, MIO_XML_ROOT, m->cb_arg, m->stacknode);	    else		xmlnode_free(m->stacknode);	    m->stacknode = NULL;	    m->root = 1;	}    } else {	m->stacknode = xmlnode_insert_tag(m->stacknode, name);	xmlnode_put_expat_attribs(m->stacknode, attribs);    }}/** * internal expat callback for end tags * * @param m the mio * @param name the name of the element */void _mio_xstream_endElement(mio m, const char* name){    /* If the stacknode is already NULL, then this closing element       must be the closing ROOT tag, so notify and exit */    if (m->stacknode == NULL)    {        mio_close(m);    }    else    {	xmlnode parent = xmlnode_get_parent(m->stacknode);	/* Fire the NODE event if this closing element has no parent */	if (parent == NULL) {	    if(m->cb != NULL)		(*(mio_xml_cb)m->cb)(m, MIO_XML_NODE, m->cb_arg, m->stacknode);	    else		xmlnode_free(m->stacknode);	}	m->stacknode = parent;    }}/** * internal expat callback for CDATA nodes * * @param m the mio * @param cdata content of the CDATA node (not zero terminated!) * @param len length of the content */void _mio_xstream_CDATA(mio m, const char* cdata, int len){    if (m->stacknode != NULL)	    xmlnode_insert_cdata(m->stacknode, cdata, len);}/** * destructor for a mio xstream, frees allocated memory * * @param arg the mio of the xstream, that should be closed */void _mio_xstream_cleanup(void* arg){    mio m = (void*)arg;    xmlnode_free(m->stacknode);    m->stacknode = NULL;    if (m->parser)	XML_ParserFree(m->parser);    m->parser = NULL;}/** * init an xstream for a mio object * * (allocates a XML parser instance) * * @param m which mio object should be prepared for usage as an XML stream */void _mio_xstream_init(mio m){    if (m != NULL)    {	    /* Initialize the parser */	    m->parser = XML_ParserCreate(NULL);	    XML_SetUserData(m->parser, m);	    XML_SetElementHandler(m->parser, (void*)_mio_xstream_startElement, (void*)_mio_xstream_endElement);	    XML_SetCharacterDataHandler(m->parser, (void*)_mio_xstream_CDATA);	    /* Setup a cleanup routine to release the parser when everything is done */	    pool_cleanup(m->p, _mio_xstream_cleanup, (void*)m);    }}/* this function is called when a socket reads data */void _mio_xml_parser(mio m, const void *vbuf, size_t bufsz){    char *nul, *buf = (char*)vbuf;    /* check if the stream has to be resetted (after STARTTLS) */    if (m->reset_stream > 0) {	_mio_xstream_cleanup(m);	m->root = 0;	/* read root element again */	m->reset_stream = 0;    }    /* init the parser if this is the first read call */    if(m->parser == NULL)    {        _mio_xstream_init(m);        /* XXX pretty big hack here, if the initial read contained a nul, assume nul-packet-terminating format stream */        if((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz)        {            m->type = type_NUL;            nul[-2] = ' '; /* assume it's .../>0 and make the stream open again */        }        /* XXX another big hack/experiment, for bypassing dumb proxies */        if(*buf == 'P')            m->type = type_HTTP;	/* Bounce HTTP-GET-Requests to the configured host */	if(*buf == 'G' && mio__bounce_uri != NULL) {	    mio_write(m, NULL, "HTTP/1.1 301 Moved permanently\r\nServer: " PACKAGE " " VERSION "\r\nConnection: close\r\nLocation: ", -1);	    mio_write(m, NULL, mio__bounce_uri, -1);	    mio_write(m, NULL, "\r\n\r\n", -1);	    mio_close(m);	    return;	}    }    /* XXX more http hack to catch the end of the headers */    if(m->type == type_HTTP)    {        if((nul = strstr(buf,"\r\n\r\n")) == NULL)            return;        nul += 4;        bufsz = bufsz - (nul - buf);        buf = nul;        mio_write(m,NULL,"HTTP/1.0 200 Ok\r\nServer: jabber/xmlstream-hack-0.1\r\nExpires: Fri, 10 Oct 1997 10:10:10 GMT\r\nPragma: no-cache\r\nCache-control: private\r\nConnection: close\r\n\r\n",-1);        m->type = type_NORMAL;    }    /* XXX more nul-term hack to ditch the nul's whenever */    if(m->type == type_NUL)        while((nul = strchr(buf,'\0')) != NULL && (nul - buf) < bufsz)        {            memmove(nul,nul+1,strlen(nul+1));            bufsz--;        }    if(XML_Parse(m->parser, buf, bufsz, 0) == 0)        if(m->cb != NULL)        {            log_debug2(ZONE, LOGT_XML, "[%s] XML Parsing Error: %s", ZONE, XML_ErrorString(XML_GetErrorCode(m->parser)));            (*(mio_std_cb)m->cb)(m, MIO_ERROR, m->cb_arg);            mio_write(m, NULL, "<stream:error><invalid-xml xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xmlns='urn:ietf:params:xml:ns:xmpp-streams' xml:lang='en'>Invalid XML</text></stream:error>", -1);            mio_close(m);        }}/** * restart a stream, starting the use of a TLS layer * * @param m the connection * @param originator 1 if we are the originator, 0 else * @param identity identity to use for selecting the certificate * @return 0 on success, non-zero on failure */int mio_xml_starttls(mio m, int originator, const char *identity) {#ifdef HAVE_SSL    int result = 0;    int waited = 0;    /* flush the write queue */    if (_mio_write_dump(m) != 0) {	log_debug2(ZONE, LOGT_IO, "Failed to flush queue before switching to TLS");	return 1;    }    /* start the TLS layer on the connection */    result = mio_ssl_starttls(m, originator, identity);    if (result != 0) {	log_debug2(ZONE, LOGT_IO, "mio_ssl_starttls() failed ... so mio_xml_starttls() fails ...");	return result;    }    /* flag that the stream has to be resetted, we cannot reset it     * here, as we might have been called from within expat and the     * return would fail then */    m->reset_stream = 1;    return 0;#else /* no SSL enabled */    return 1;#endif /* HAVE_SSL */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -