| 77 |
77 |
| 78 |
78 |
| 79 void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { |
79 void jabber_disco_info_parse(JabberStream *js, xmlnode *packet) { |
| 80 const char *from = xmlnode_get_attrib(packet, "from"); |
80 const char *from = xmlnode_get_attrib(packet, "from"); |
| 81 const char *type = xmlnode_get_attrib(packet, "type"); |
81 const char *type = xmlnode_get_attrib(packet, "type"); |
| 82 |
|
| 83 if(!from || !type) |
82 if(!from || !type) |
| 84 return; |
83 return; |
| 85 |
84 |
| 86 if(!strcmp(type, "get")) { |
85 if(!strcmp(type, "get")) { |
| 87 xmlnode *query, *identity, *feature; |
86 xmlnode *query, *identity, *feature; |
| 88 JabberIq *iq; |
87 JabberIq *iq; |
| 89 |
88 |
| 90 xmlnode *in_query; |
89 xmlnode *in_query; |
| 91 const char *node = NULL; |
90 const char *node = NULL; |
| |
91 const char *node_uri = NULL; |
| |
92 |
| |
93 // create custom caps node URI |
| |
94 node_uri = g_strconcat(CAPS0115_NODE, "#", jabber_caps_get_hash(), NULL); |
| 92 |
95 |
| 93 if((in_query = xmlnode_get_child(packet, "query"))) { |
96 if((in_query = xmlnode_get_child(packet, "query"))) { |
| 94 node = xmlnode_get_attrib(in_query, "node"); |
97 node = xmlnode_get_attrib(in_query, "node"); |
| 95 } |
98 } |
| 96 |
99 |
| 104 query = xmlnode_get_child(iq->node, "query"); |
107 query = xmlnode_get_child(iq->node, "query"); |
| 105 |
108 |
| 106 if(node) |
109 if(node) |
| 107 xmlnode_set_attrib(query, "node", node); |
110 xmlnode_set_attrib(query, "node", node); |
| 108 |
111 |
| 109 if(!node || !strcmp(node, CAPS0115_NODE "#" VERSION)) { |
112 |
| 110 identity = xmlnode_new_child(query, "identity"); |
113 if(!node || !strcmp(node, node_uri)) { |
| 111 xmlnode_set_attrib(identity, "category", "client"); |
114 GList *identities; |
| 112 xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console, |
115 for(identities = jabber_identities; identities; identities = identities->next) { |
| 113 * handheld, pc, phone, |
116 JabberIdentity *ident = (JabberIdentity*)identities->data; |
| 114 * web */ |
117 identity = xmlnode_new_child(query, "identity"); |
| 115 xmlnode_set_attrib(identity, "name", PACKAGE); |
118 xmlnode_set_attrib(identity, "category", ident->category); |
| 116 |
119 xmlnode_set_attrib(identity, "type", ident->type); |
| 117 SUPPORT_FEATURE("jabber:iq:last") |
120 if (ident->name != 0) xmlnode_set_attrib(identity, "name", ident->name); |
| 118 SUPPORT_FEATURE("jabber:iq:oob") |
121 } |
| 119 SUPPORT_FEATURE("jabber:iq:time") |
122 GList *features; |
| 120 SUPPORT_FEATURE("xmpp:urn:time") |
123 for(features = jabber_features; features; features = features->next) { |
| 121 SUPPORT_FEATURE("jabber:iq:version") |
124 JabberFeature *feat = (JabberFeature*)features->data; |
| 122 SUPPORT_FEATURE("jabber:x:conference") |
125 if(feat->is_enabled == NULL || feat->is_enabled(js, feat->namespace) == TRUE) { |
| 123 SUPPORT_FEATURE("http://jabber.org/protocol/bytestreams") |
126 feature = xmlnode_new_child(query, "feature"); |
| 124 SUPPORT_FEATURE("http://jabber.org/protocol/disco#info") |
127 xmlnode_set_attrib(feature, "var", feat->namespace); |
| 125 SUPPORT_FEATURE("http://jabber.org/protocol/disco#items") |
128 } |
| 126 #if 0 |
|
| 127 SUPPORT_FEATURE("http://jabber.org/protocol/ibb") |
|
| 128 #endif |
|
| 129 SUPPORT_FEATURE("http://jabber.org/protocol/muc") |
|
| 130 SUPPORT_FEATURE("http://jabber.org/protocol/muc#user") |
|
| 131 SUPPORT_FEATURE("http://jabber.org/protocol/si") |
|
| 132 SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") |
|
| 133 SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") |
|
| 134 SUPPORT_FEATURE("urn:xmpp:ping") |
|
| 135 SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns") |
|
| 136 |
|
| 137 if(!node) { /* non-caps disco#info, add all enabled extensions */ |
|
| 138 GList *features; |
|
| 139 for(features = jabber_features; features; features = features->next) { |
|
| 140 JabberFeature *feat = (JabberFeature*)features->data; |
|
| 141 if(feat->is_enabled == NULL || feat->is_enabled(js, feat->shortname, feat->namespace) == TRUE) |
|
| 142 SUPPORT_FEATURE(feat->namespace); |
|
| 143 } |
|
| 144 } |
129 } |
| 145 } else { |
130 } else { |
| 146 const char *ext = NULL; |
131 xmlnode *error, *inf; |
| 147 unsigned pos; |
|
| 148 unsigned nodelen = strlen(node); |
|
| 149 unsigned capslen = strlen(CAPS0115_NODE); |
|
| 150 /* do a basic plausability check */ |
|
| 151 if(nodelen > capslen+1) { |
|
| 152 /* verify that the string is CAPS0115#<ext> and get the pointer to the ext part */ |
|
| 153 for(pos = 0; pos < capslen+1; ++pos) { |
|
| 154 if(pos == capslen) { |
|
| 155 if(node[pos] == '#') |
|
| 156 ext = &node[pos+1]; |
|
| 157 else |
|
| 158 break; |
|
| 159 } else if(node[pos] != CAPS0115_NODE[pos]) |
|
| 160 break; |
|
| 161 } |
|
| 162 |
132 |
| 163 if(ext != NULL) { |
133 /* XXX: gross hack, implement jabber_iq_set_type or something */ |
| 164 /* look for that ext */ |
134 xmlnode_set_attrib(iq->node, "type", "error"); |
| 165 GList *features; |
135 iq->type = JABBER_IQ_ERROR; |
| 166 for(features = jabber_features; features; features = features->next) { |
|
| 167 JabberFeature *feat = (JabberFeature*)features->data; |
|
| 168 if(!strcmp(feat->shortname, ext)) { |
|
| 169 SUPPORT_FEATURE(feat->namespace); |
|
| 170 break; |
|
| 171 } |
|
| 172 } |
|
| 173 if(features == NULL) |
|
| 174 ext = NULL; |
|
| 175 } |
|
| 176 } |
|
| 177 |
136 |
| 178 if(ext == NULL) { |
137 error = xmlnode_new_child(query, "error"); |
| 179 xmlnode *error, *inf; |
138 xmlnode_set_attrib(error, "code", "404"); |
| 180 |
139 xmlnode_set_attrib(error, "type", "cancel"); |
| 181 /* XXX: gross hack, implement jabber_iq_set_type or something */ |
140 inf = xmlnode_new_child(error, "item-not-found"); |
| 182 xmlnode_set_attrib(iq->node, "type", "error"); |
141 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
| 183 iq->type = JABBER_IQ_ERROR; |
142 } |
| 184 |
143 g_free(node_uri); |
| 185 error = xmlnode_new_child(query, "error"); |
|
| 186 xmlnode_set_attrib(error, "code", "404"); |
|
| 187 xmlnode_set_attrib(error, "type", "cancel"); |
|
| 188 inf = xmlnode_new_child(error, "item-not-found"); |
|
| 189 xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
|
| 190 } |
|
| 191 } |
|
| 192 |
|
| 193 jabber_iq_send(iq); |
144 jabber_iq_send(iq); |
| 194 } else if(!strcmp(type, "result")) { |
145 } else if(!strcmp(type, "result")) { |
| 195 xmlnode *query = xmlnode_get_child(packet, "query"); |
146 xmlnode *query = xmlnode_get_child(packet, "query"); |
| 196 xmlnode *child; |
147 xmlnode *child; |
| 197 JabberID *jid; |
148 JabberID *jid; |