00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "gloox.h"
00016
00017 #include "parser.h"
00018 #include "clientbase.h"
00019 #include "stanza.h"
00020
00021 namespace gloox
00022 {
00023
00024 Parser::Parser( ClientBase *parent )
00025 : m_parent( parent ), m_current( 0 ), m_root( 0 )
00026 {
00027 m_parser = iks_sax_new( this, (iksTagHook*)tagHook, (iksCDataHook*)cdataHook );
00028 }
00029
00030 Parser::~Parser()
00031 {
00032 iks_parser_delete( m_parser );
00033 delete m_root;
00034 }
00035
00036 Parser::ParserState Parser::feed( const std::string& data )
00037 {
00038 int res = iks_parse( m_parser, data.c_str(), data.length(), 0 );
00039 switch( res )
00040 {
00041 case IKS_NOMEM:
00042 return PARSER_NOMEM;
00043 break;
00044 case IKS_BADXML:
00045 return PARSER_BADXML;
00046 break;
00047 case IKS_OK:
00048 default:
00049 return PARSER_OK;
00050 break;
00051 }
00052 }
00053
00054 void Parser::streamEvent( Stanza *stanza )
00055 {
00056 if( m_parent && stanza )
00057 {
00058 ClientBase::NodeType type = ClientBase::NODE_STREAM_CHILD;
00059 if( m_root->name() == "stream:stream" )
00060 type = ClientBase::NODE_STREAM_START;
00061 else if( m_root->name() == "stream:error" )
00062 type = ClientBase::NODE_STREAM_ERROR;
00063
00064 m_parent->filter( type, stanza );
00065 }
00066 else if( !stanza )
00067 m_parent->filter( ClientBase::NODE_STREAM_CLOSE, 0 );
00068 }
00069
00070 int tagHook( Parser *parser, char *name, char **atts, int type )
00071 {
00072 if( !name )
00073 return IKS_OK;
00074
00075 switch( type )
00076 {
00077 case IKS_OPEN:
00078 case IKS_SINGLE:
00079 {
00080 Stanza *tag = new Stanza( name, "", "default", true );
00081 for(int i=0; atts && atts[i]; )
00082 {
00083 tag->addAttribute( atts[i], atts[i+1] );
00084 i+=2;
00085 }
00086 if( !parser->m_root )
00087 {
00088 parser->m_root = tag;
00089 parser->m_current = parser->m_root;
00090 }
00091 else
00092 {
00093 parser->m_current->addChild( tag );
00094 parser->m_current = tag;
00095 }
00096 if( tag->name() == "stream:stream" )
00097 {
00098 parser->streamEvent( parser->m_root );
00099 delete parser->m_root;
00100 parser->m_root = 0;
00101 parser->m_current = 0;
00102 }
00103 if( type == IKS_OPEN )
00104 break;
00105 }
00106 case IKS_CLOSE:
00107 if( iks_strncmp( name, "stream:stream", 13 ) == 0 )
00108 {
00109 parser->streamEvent( 0 );
00110 break;
00111 }
00112 parser->m_current = dynamic_cast<Stanza*>( parser->m_current->parent() );
00113 if( !parser->m_current )
00114 {
00115 parser->m_root->finalize();
00116 parser->streamEvent( parser->m_root );
00117 delete parser->m_root;
00118 parser->m_root = 0;
00119 parser->m_current = 0;
00120 }
00121 break;
00122 }
00123 return IKS_OK;
00124 }
00125
00126 int cdataHook( Parser *parser, char *data, size_t len )
00127 {
00128 if( parser->m_current && data && len )
00129 {
00130 std::string tmp;
00131 tmp.assign( data, len );
00132 parser->m_current->addCData( tmp );
00133 }
00134
00135 return IKS_OK;
00136 }
00137
00138 }