comparison libpurple/protocols/jabber/disco.c @ 25987:c4fd9222dda1

propagate from branch 'im.pidgin.pidgin' (head 303af74a38e7b313d4fb0be4d4054a16cb13d819) to branch 'im.pidgin.cpw.darkrain42.xmpp.bosh' (head 650d82b8a5f0c8860804dd8004cd54badea48e1e)
author Paul Aurich <paul@darkrain42.org>
date Sat, 07 Mar 2009 01:59:40 +0000
parents 5f9a24d1c25e 6a369035fd20
children 2597de135090
comparison
equal deleted inserted replaced
25464:0e93bbb7f5ca 25987:c4fd9222dda1
96 xmlnode *query, *identity, *feature; 96 xmlnode *query, *identity, *feature;
97 JabberIq *iq; 97 JabberIq *iq;
98 98
99 xmlnode *in_query; 99 xmlnode *in_query;
100 const char *node = NULL; 100 const char *node = NULL;
101 char *node_uri = NULL;
102
103 /* create custom caps node URI */
104 node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_own_hash(js), NULL);
101 105
102 if((in_query = xmlnode_get_child(packet, "query"))) { 106 if((in_query = xmlnode_get_child(packet, "query"))) {
103 node = xmlnode_get_attrib(in_query, "node"); 107 node = xmlnode_get_attrib(in_query, "node");
104 } 108 }
105 109
121 xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console, 125 xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console,
122 * handheld, pc, phone, 126 * handheld, pc, phone,
123 * web */ 127 * web */
124 xmlnode_set_attrib(identity, "name", PACKAGE); 128 xmlnode_set_attrib(identity, "name", PACKAGE);
125 129
126 SUPPORT_FEATURE("jabber:iq:last") 130 if(!node || !strcmp(node, node_uri)) {
127 SUPPORT_FEATURE("jabber:iq:oob") 131 GList *features, *identities;
128 SUPPORT_FEATURE("jabber:iq:time") 132 for(identities = jabber_identities; identities; identities = identities->next) {
129 SUPPORT_FEATURE("xmpp:urn:time") 133 JabberIdentity *ident = (JabberIdentity*)identities->data;
130 SUPPORT_FEATURE("jabber:iq:version") 134 identity = xmlnode_new_child(query, "identity");
131 SUPPORT_FEATURE("jabber:x:conference") 135 xmlnode_set_attrib(identity, "category", ident->category);
132 SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") 136 xmlnode_set_attrib(identity, "type", ident->type);
133 SUPPORT_FEATURE("http://jabber.org/protocol/disco#info") 137 if (ident->lang)
134 SUPPORT_FEATURE("http://jabber.org/protocol/disco#items") 138 xmlnode_set_attrib(identity, "xml:lang", ident->lang);
135 SUPPORT_FEATURE("http://jabber.org/protocol/ibb"); 139 if (ident->name)
136 SUPPORT_FEATURE("http://jabber.org/protocol/muc") 140 xmlnode_set_attrib(identity, "name", ident->name);
137 SUPPORT_FEATURE("http://jabber.org/protocol/muc#user") 141 }
138 SUPPORT_FEATURE("http://jabber.org/protocol/si") 142 for(features = jabber_features; features; features = features->next) {
139 SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") 143 JabberFeature *feat = (JabberFeature*)features->data;
140 SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") 144 if (!feat->is_enabled || feat->is_enabled(js, feat->namespace)) {
141 SUPPORT_FEATURE("urn:xmpp:ping") 145 feature = xmlnode_new_child(query, "feature");
142 SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns") 146 xmlnode_set_attrib(feature, "var", feat->namespace);
143 147 }
144 if(!node) { /* non-caps disco#info, add all enabled extensions */
145 GList *features;
146 for(features = jabber_features; features; features = features->next) {
147 JabberFeature *feat = (JabberFeature*)features->data;
148 if(feat->is_enabled == NULL || feat->is_enabled(js, feat->shortname, feat->namespace) == TRUE)
149 SUPPORT_FEATURE(feat->namespace);
150 }
151 } 148 }
152 } else { 149 } else {
153 const char *ext = NULL; 150 xmlnode *error, *inf;
154 unsigned pos; 151
155 unsigned nodelen = strlen(node); 152 /* XXX: gross hack, implement jabber_iq_set_type or something */
156 unsigned capslen = strlen(CAPS0115_NODE); 153 xmlnode_set_attrib(iq->node, "type", "error");
157 /* do a basic plausability check */ 154 iq->type = JABBER_IQ_ERROR;
158 if(nodelen > capslen+1) { 155
159 /* verify that the string is CAPS0115#<ext> and get the pointer to the ext part */ 156 error = xmlnode_new_child(query, "error");
160 for(pos = 0; pos < capslen+1; ++pos) { 157 xmlnode_set_attrib(error, "code", "404");
161 if(pos == capslen) { 158 xmlnode_set_attrib(error, "type", "cancel");
162 if(node[pos] == '#') 159 inf = xmlnode_new_child(error, "item-not-found");
163 ext = &node[pos+1]; 160 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
164 else 161 }
165 break; 162 g_free(node_uri);
166 } else if(node[pos] != CAPS0115_NODE[pos])
167 break;
168 }
169
170 if(ext != NULL) {
171 /* look for that ext */
172 GList *features;
173 for(features = jabber_features; features; features = features->next) {
174 JabberFeature *feat = (JabberFeature*)features->data;
175 if(!strcmp(feat->shortname, ext)) {
176 SUPPORT_FEATURE(feat->namespace);
177 break;
178 }
179 }
180 if(features == NULL)
181 ext = NULL;
182 }
183 }
184
185 if(ext == NULL) {
186 xmlnode *error, *inf;
187
188 /* XXX: gross hack, implement jabber_iq_set_type or something */
189 xmlnode_set_attrib(iq->node, "type", "error");
190 iq->type = JABBER_IQ_ERROR;
191
192 error = xmlnode_new_child(query, "error");
193 xmlnode_set_attrib(error, "code", "404");
194 xmlnode_set_attrib(error, "type", "cancel");
195 inf = xmlnode_new_child(error, "item-not-found");
196 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
197 }
198 }
199
200 jabber_iq_send(iq); 163 jabber_iq_send(iq);
201 } else if(!strcmp(type, "result")) { 164 } else if(!strcmp(type, "result")) {
202 xmlnode *query = xmlnode_get_child(packet, "query"); 165 xmlnode *query = xmlnode_get_child(packet, "query");
203 xmlnode *child; 166 xmlnode *child;
204 JabberID *jid; 167 JabberID *jid;
347 if (!(js->server_caps & JABBER_CAP_GOOGLE_ROSTER)) { 310 if (!(js->server_caps & JABBER_CAP_GOOGLE_ROSTER)) {
348 /* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */ 311 /* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
349 jabber_roster_request(js); 312 jabber_roster_request(js);
350 } 313 }
351 314
352 /* Send initial presence; this will trigger receipt of presence for contacts on the roster */
353 jabber_presence_send(js->gc->account, NULL);
354
355 if (js->server_caps & JABBER_CAP_ADHOC) { 315 if (js->server_caps & JABBER_CAP_ADHOC) {
356 /* The server supports ad-hoc commands, so let's request the list */ 316 /* The server supports ad-hoc commands, so let's request the list */
357 jabber_adhoc_server_get_list(js); 317 jabber_adhoc_server_get_list(js);
358 } 318 }
359 319