comparison libpurple/protocols/jabber/disco.c @ 25663:1d1d1829de11

propagate from branch 'im.pidgin.pidgin' (head 42f77b0e8b8ebf5ff3c30d8f8022ac5d289631e8) to branch 'org.darkrain42.pidgin.xmpp' (head f3aa6c57ecb65ae9dbf729bca259e94f48b87279)
author Paul Aurich <paul@darkrain42.org>
date Sun, 18 Jan 2009 04:17:50 +0000
parents 0700833f0c5d f462fa160f06
children 6a369035fd20
comparison
equal deleted inserted replaced
25330:8a5c0c5c71f9 25663:1d1d1829de11
86 86
87 87
88 void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { 88 void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) {
89 const char *from = xmlnode_get_attrib(packet, "from"); 89 const char *from = xmlnode_get_attrib(packet, "from");
90 const char *type = xmlnode_get_attrib(packet, "type"); 90 const char *type = xmlnode_get_attrib(packet, "type");
91
92 if(!from || !type) 91 if(!from || !type)
93 return; 92 return;
94 93
95 if(!strcmp(type, "get")) { 94 if(!strcmp(type, "get")) {
96 xmlnode *query, *identity, *feature; 95 xmlnode *query, *identity, *feature;
97 JabberIq *iq; 96 JabberIq *iq;
98 97
99 xmlnode *in_query; 98 xmlnode *in_query;
100 const char *node = NULL; 99 const char *node = NULL;
100 char *node_uri = NULL;
101
102 /* create custom caps node URI */
103 node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_own_hash(js), NULL);
101 104
102 if((in_query = xmlnode_get_child(packet, "query"))) { 105 if((in_query = xmlnode_get_child(packet, "query"))) {
103 node = xmlnode_get_attrib(in_query, "node"); 106 node = xmlnode_get_attrib(in_query, "node");
104 } 107 }
105 108
113 query = xmlnode_get_child(iq->node, "query"); 116 query = xmlnode_get_child(iq->node, "query");
114 117
115 if(node) 118 if(node)
116 xmlnode_set_attrib(query, "node", node); 119 xmlnode_set_attrib(query, "node", node);
117 120
118 if(!node || !strcmp(node, CAPS0115_NODE "#" VERSION)) { 121
119 identity = xmlnode_new_child(query, "identity"); 122 if(!node || !strcmp(node, node_uri)) {
120 xmlnode_set_attrib(identity, "category", "client"); 123 GList *features, *identities;
121 xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console, 124 for(identities = jabber_identities; identities; identities = identities->next) {
122 * handheld, pc, phone, 125 JabberIdentity *ident = (JabberIdentity*)identities->data;
123 * web */ 126 identity = xmlnode_new_child(query, "identity");
124 xmlnode_set_attrib(identity, "name", PACKAGE); 127 xmlnode_set_attrib(identity, "category", ident->category);
125 128 xmlnode_set_attrib(identity, "type", ident->type);
126 SUPPORT_FEATURE("jabber:iq:last") 129 if (ident->lang)
127 SUPPORT_FEATURE("jabber:iq:oob") 130 xmlnode_set_attrib(identity, "xml:lang", ident->lang);
128 SUPPORT_FEATURE("jabber:iq:time") 131 if (ident->name)
129 SUPPORT_FEATURE("xmpp:urn:time") 132 xmlnode_set_attrib(identity, "name", ident->name);
130 SUPPORT_FEATURE("jabber:iq:version") 133 }
131 SUPPORT_FEATURE("jabber:x:conference") 134 for(features = jabber_features; features; features = features->next) {
132 SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") 135 JabberFeature *feat = (JabberFeature*)features->data;
133 SUPPORT_FEATURE("http://jabber.org/protocol/disco#info") 136 if (!feat->is_enabled || feat->is_enabled(js, feat->namespace)) {
134 SUPPORT_FEATURE("http://jabber.org/protocol/disco#items") 137 feature = xmlnode_new_child(query, "feature");
135 #if 0 138 xmlnode_set_attrib(feature, "var", feat->namespace);
136 SUPPORT_FEATURE("http://jabber.org/protocol/ibb") 139 }
137 #endif
138 SUPPORT_FEATURE("http://jabber.org/protocol/muc")
139 SUPPORT_FEATURE("http://jabber.org/protocol/muc#user")
140 SUPPORT_FEATURE("http://jabber.org/protocol/si")
141 SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer")
142 SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im")
143 SUPPORT_FEATURE("urn:xmpp:ping")
144 SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns")
145
146 if(!node) { /* non-caps disco#info, add all enabled extensions */
147 GList *features;
148 for(features = jabber_features; features; features = features->next) {
149 JabberFeature *feat = (JabberFeature*)features->data;
150 if(feat->is_enabled == NULL || feat->is_enabled(js, feat->shortname, feat->namespace) == TRUE)
151 SUPPORT_FEATURE(feat->namespace);
152 }
153 } 140 }
154 } else { 141 } else {
155 const char *ext = NULL; 142 xmlnode *error, *inf;
156 unsigned pos;
157 unsigned nodelen = strlen(node);
158 unsigned capslen = strlen(CAPS0115_NODE);
159 /* do a basic plausability check */
160 if(nodelen > capslen+1) {
161 /* verify that the string is CAPS0115#<ext> and get the pointer to the ext part */
162 for(pos = 0; pos < capslen+1; ++pos) {
163 if(pos == capslen) {
164 if(node[pos] == '#')
165 ext = &node[pos+1];
166 else
167 break;
168 } else if(node[pos] != CAPS0115_NODE[pos])
169 break;
170 }
171 143
172 if(ext != NULL) { 144 /* XXX: gross hack, implement jabber_iq_set_type or something */
173 /* look for that ext */ 145 xmlnode_set_attrib(iq->node, "type", "error");
174 GList *features; 146 iq->type = JABBER_IQ_ERROR;
175 for(features = jabber_features; features; features = features->next) {
176 JabberFeature *feat = (JabberFeature*)features->data;
177 if(!strcmp(feat->shortname, ext)) {
178 SUPPORT_FEATURE(feat->namespace);
179 break;
180 }
181 }
182 if(features == NULL)
183 ext = NULL;
184 }
185 }
186 147
187 if(ext == NULL) { 148 error = xmlnode_new_child(query, "error");
188 xmlnode *error, *inf; 149 xmlnode_set_attrib(error, "code", "404");
189 150 xmlnode_set_attrib(error, "type", "cancel");
190 /* XXX: gross hack, implement jabber_iq_set_type or something */ 151 inf = xmlnode_new_child(error, "item-not-found");
191 xmlnode_set_attrib(iq->node, "type", "error"); 152 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
192 iq->type = JABBER_IQ_ERROR; 153 }
193 154 g_free(node_uri);
194 error = xmlnode_new_child(query, "error");
195 xmlnode_set_attrib(error, "code", "404");
196 xmlnode_set_attrib(error, "type", "cancel");
197 inf = xmlnode_new_child(error, "item-not-found");
198 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas");
199 }
200 }
201
202 jabber_iq_send(iq); 155 jabber_iq_send(iq);
203 } else if(!strcmp(type, "result")) { 156 } else if(!strcmp(type, "result")) {
204 xmlnode *query = xmlnode_get_child(packet, "query"); 157 xmlnode *query = xmlnode_get_child(packet, "query");
205 xmlnode *child; 158 xmlnode *child;
206 JabberID *jid; 159 JabberID *jid;
346 /* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */ 299 /* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
347 jabber_roster_request(js); 300 jabber_roster_request(js);
348 } 301 }
349 302
350 /* Send initial presence; this will trigger receipt of presence for contacts on the roster */ 303 /* Send initial presence; this will trigger receipt of presence for contacts on the roster */
351 jabber_presence_send(js->gc->account, NULL); 304 jabber_presence_send(js, TRUE);
352 305
353 if (js->server_caps & JABBER_CAP_ADHOC) { 306 if (js->server_caps & JABBER_CAP_ADHOC) {
354 /* The server supports ad-hoc commands, so let's request the list */ 307 /* The server supports ad-hoc commands, so let's request the list */
355 jabber_adhoc_server_get_list(js); 308 jabber_adhoc_server_get_list(js);
356 } 309 }