Thu, 14 Dec 2006 04:56:54 +0000
[gaim-migrate @ 17993]
Blocking on Google Talk. Our Privacy API sucks so bad that even with no prior support for blocking in Jabber, this has no interface changes. If someone wanted to implement the deprecated Jabber privacy lists API, though, that would be ok by me.
| 7014 | 1 | /* |
| 2 | * gaim - Jabber XML parser stuff | |
| 3 | * | |
| 4 | * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
| 5 | * | |
| 6 | * This program is free software; you can redistribute it and/or modify | |
| 7 | * it under the terms of the GNU General Public License as published by | |
| 8 | * the Free Software Foundation; either version 2 of the License, or | |
| 9 | * (at your option) any later version. | |
| 10 | * | |
| 11 | * This program is distributed in the hope that it will be useful, | |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | * GNU General Public License for more details. | |
| 15 | * | |
| 16 | * You should have received a copy of the GNU General Public License | |
| 17 | * along with this program; if not, write to the Free Software | |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | * | |
| 20 | */ | |
| 21 | #include "internal.h" | |
| 22 | ||
| 13808 | 23 | #include <libxml/parser.h> |
| 24 | ||
| 7014 | 25 | #include "connection.h" |
| 13808 | 26 | #include "debug.h" |
| 7014 | 27 | #include "jabber.h" |
| 28 | #include "parser.h" | |
| 15159 | 29 | #include "util.h" |
| 7014 | 30 | #include "xmlnode.h" |
| 31 | ||
| 13808 | 32 | static void |
| 33 | jabber_parser_element_start_libxml(void *user_data, | |
| 34 | const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace, | |
| 35 | int nb_namespaces, const xmlChar **namespaces, | |
| 36 | int nb_attributes, int nb_defaulted, const xmlChar **attributes) | |
| 37 | { | |
| 38 | JabberStream *js = user_data; | |
| 39 | xmlnode *node; | |
| 40 | int i; | |
| 41 | ||
| 42 | if(!element_name) { | |
| 43 | return; | |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
44 | } else if(!xmlStrcmp(element_name, (xmlChar*) "stream")) { |
| 13808 | 45 | js->protocol_version = JABBER_PROTO_0_9; |
| 46 | for(i=0; i < nb_attributes * 5; i += 5) { | |
| 47 | int attrib_len = attributes[i+4] - attributes[i+3]; | |
| 48 | char *attrib = g_malloc(attrib_len + 1); | |
| 49 | memcpy(attrib, attributes[i+3], attrib_len); | |
| 50 | attrib[attrib_len] = '\0'; | |
|
14498
ede839a78714
[gaim-migrate @ 17150]
Mark Doliner <markdoliner@pidgin.im>
parents:
14476
diff
changeset
|
51 | |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
52 | if(!xmlStrcmp(attributes[i], (xmlChar*) "version") |
| 13808 | 53 | && !strcmp(attrib, "1.0")) { |
| 54 | js->protocol_version = JABBER_PROTO_1_0; | |
|
14685
7622a9ca1794
[gaim-migrate @ 17352]
Daniel Atallah <datallah@pidgin.im>
parents:
14538
diff
changeset
|
55 | g_free(attrib); |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
56 | } else if(!xmlStrcmp(attributes[i], (xmlChar*) "id")) { |
| 13808 | 57 | if(js->stream_id) |
| 58 | g_free(js->stream_id); | |
|
14685
7622a9ca1794
[gaim-migrate @ 17352]
Daniel Atallah <datallah@pidgin.im>
parents:
14538
diff
changeset
|
59 | js->stream_id = attrib; |
| 13808 | 60 | } |
| 61 | } | |
| 62 | if(js->protocol_version == JABBER_PROTO_0_9) | |
| 63 | js->auth_type = JABBER_AUTH_IQ_AUTH; | |
| 64 | ||
| 65 | if(js->state == JABBER_STREAM_INITIALIZING) | |
| 66 | jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING); | |
| 67 | } else { | |
| 68 | ||
| 69 | if(js->current) | |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
70 | node = xmlnode_new_child(js->current, (const char*) element_name); |
| 13808 | 71 | else |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
72 | node = xmlnode_new((const char*) element_name); |
|
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
73 | xmlnode_set_namespace(node, (const char*) namespace); |
| 13808 | 74 | |
| 75 | for(i=0; i < nb_attributes * 5; i+=5) { | |
| 15158 | 76 | char *txt; |
| 13808 | 77 | int attrib_len = attributes[i+4] - attributes[i+3]; |
| 78 | char *attrib = g_malloc(attrib_len + 1); | |
| 15265 | 79 | char *attrib_ns = NULL; |
| 80 | ||
| 81 | if (attributes[i+2]) { | |
| 82 | attrib_ns = g_strdup(attributes[i+2]);; | |
| 83 | } | |
| 84 | ||
| 13808 | 85 | memcpy(attrib, attributes[i+3], attrib_len); |
| 86 | attrib[attrib_len] = '\0'; | |
| 15265 | 87 | |
| 15158 | 88 | txt = attrib; |
| 89 | attrib = gaim_unescape_html(txt); | |
| 90 | g_free(txt); | |
| 15265 | 91 | xmlnode_set_attrib_with_namespace(node, (const char*) attributes[i], attrib_ns, attrib); |
| 13808 | 92 | g_free(attrib); |
| 15265 | 93 | g_free(attrib_ns); |
| 13808 | 94 | } |
| 95 | ||
| 96 | js->current = node; | |
| 97 | } | |
| 98 | } | |
| 99 | ||
| 100 | static void | |
|
14498
ede839a78714
[gaim-migrate @ 17150]
Mark Doliner <markdoliner@pidgin.im>
parents:
14476
diff
changeset
|
101 | jabber_parser_element_end_libxml(void *user_data, const xmlChar *element_name, |
| 13808 | 102 | const xmlChar *prefix, const xmlChar *namespace) |
| 103 | { | |
| 104 | JabberStream *js = user_data; | |
| 105 | ||
| 106 | if(!js->current) | |
| 107 | return; | |
| 108 | ||
| 109 | if(js->current->parent) { | |
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
110 | if(!xmlStrcmp((xmlChar*) js->current->name, element_name)) |
| 13808 | 111 | js->current = js->current->parent; |
| 112 | } else { | |
| 113 | xmlnode *packet = js->current; | |
| 114 | js->current = NULL; | |
| 115 | jabber_process_packet(js, packet); | |
| 116 | xmlnode_free(packet); | |
| 117 | } | |
| 118 | } | |
| 119 | ||
| 120 | static void | |
| 121 | jabber_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len) | |
| 122 | { | |
| 123 | JabberStream *js = user_data; | |
| 124 | ||
| 125 | if(!js->current) | |
| 126 | return; | |
| 127 | ||
| 128 | if(!text || !text_len) | |
| 129 | return; | |
| 130 | ||
|
14690
9287ecc4adb1
[gaim-migrate @ 17369]
Daniel Atallah <datallah@pidgin.im>
parents:
14685
diff
changeset
|
131 | xmlnode_insert_data(js->current, (const char*) text, text_len); |
| 13808 | 132 | } |
| 133 | ||
| 134 | static xmlSAXHandler jabber_parser_libxml = { | |
| 135 | .internalSubset = NULL, | |
| 136 | .isStandalone = NULL, | |
| 137 | .hasInternalSubset = NULL, | |
| 138 | .hasExternalSubset = NULL, | |
| 139 | .resolveEntity = NULL, | |
| 140 | .getEntity = NULL, | |
| 141 | .entityDecl = NULL, | |
| 142 | .notationDecl = NULL, | |
| 143 | .attributeDecl = NULL, | |
| 144 | .elementDecl = NULL, | |
| 145 | .unparsedEntityDecl = NULL, | |
| 146 | .setDocumentLocator = NULL, | |
| 147 | .startDocument = NULL, | |
| 148 | .endDocument = NULL, | |
| 149 | .startElement = NULL, | |
| 150 | .endElement = NULL, | |
| 151 | .reference = NULL, | |
| 152 | .characters = jabber_parser_element_text_libxml, | |
| 153 | .ignorableWhitespace = NULL, | |
| 154 | .processingInstruction = NULL, | |
| 155 | .comment = NULL, | |
| 156 | .warning = NULL, | |
| 157 | .error = NULL, | |
| 158 | .fatalError = NULL, | |
| 159 | .getParameterEntity = NULL, | |
| 160 | .cdataBlock = NULL, | |
| 161 | .externalSubset = NULL, | |
| 162 | .initialized = XML_SAX2_MAGIC, | |
| 163 | ._private = NULL, | |
| 164 | .startElementNs = jabber_parser_element_start_libxml, | |
| 165 | .endElementNs = jabber_parser_element_end_libxml, | |
| 166 | .serror = NULL | |
| 167 | }; | |
| 7014 | 168 | |
| 169 | void | |
| 170 | jabber_parser_setup(JabberStream *js) | |
| 171 | { | |
| 14538 | 172 | /* This seems backwards, but it makes sense. The libxml code creates |
| 173 | * the parser context when you try to use it (this way, it can figure | |
| 174 | * out the encoding at creation time. So, setting up the parser is | |
| 175 | * just a matter of destroying any current parser. */ | |
| 13808 | 176 | if (js->context) { |
| 177 | xmlParseChunk(js->context, NULL,0,1); | |
| 178 | xmlFreeParserCtxt(js->context); | |
| 179 | js->context = NULL; | |
| 180 | } | |
| 7014 | 181 | } |
| 182 | ||
| 183 | ||
| 184 | void jabber_parser_process(JabberStream *js, const char *buf, int len) | |
| 185 | { | |
| 13808 | 186 | if (js->context == NULL) { |
| 14538 | 187 | /* libxml inconsistently starts parsing on creating the |
| 188 | * parser, so do a ParseChunk right afterwards to force it. */ | |
| 13808 | 189 | js->context = xmlCreatePushParserCtxt(&jabber_parser_libxml, js, buf, len, NULL); |
| 14700 | 190 | xmlParseChunk(js->context, "", 0, 0); |
| 13808 | 191 | } else if (xmlParseChunk(js->context, buf, len, 0) < 0) { |
| 192 | gaim_connection_error(js->gc, _("XML Parse error")); | |
| 193 | } | |
| 7014 | 194 | } |
| 195 |