root/trunk/src/iq.c

Revision 680, 11.8 kB (checked in by jajcus, 3 years ago)

- dates in the copyright header updated

Line 
1 /* $Id: iq.c,v 1.48 2004/02/20 17:42:51 jajcus Exp $ */
2
3 /*
4  *  (C) Copyright 2002-2006 Jacek Konieczny [jajcus(a)jajcus,net]
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 Version 2 as
8  *  published by the Free Software Foundation.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include "ggtrans.h"
21 #include "jabber.h"
22 #include "register.h"
23 #include "jid.h"
24 #include "users.h"
25 #include "search.h"
26 #include "iq.h"
27 #include "browse.h"
28 #include "disco.h"
29 #include "stats.h"
30 #include "conf.h"
31 #include "gg_versions.h"
32 #include "acl.h"
33 #include <sys/utsname.h>
34 #include "debug.h"
35
36 char *gateway_desc;
37 char *gateway_prompt;
38
39 void jabber_iq_get_agent(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
40 void jabber_iq_get_server_vcard(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
41 void jabber_iq_get_gateway(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
42 void jabber_iq_set_gateway(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
43 void jabber_iq_get_server_version(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
44 void jabber_iq_get_client_version(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
45 void jabber_iq_not_implemented(Stream *s,const char *from,const char * to,const char *id,xmlnode q);
46
47 IqNamespace server_iq_ns[]={
48         {"jabber:iq:register","query",jabber_iq_get_register,jabber_iq_set_register},
49         {"jabber:iq:search","query",jabber_iq_get_search,jabber_iq_set_search},
50         {"jabber:iq:agent","query",jabber_iq_get_agent,NULL},
51         {"jabber:iq:gateway","query",jabber_iq_get_gateway,jabber_iq_set_gateway},
52         {"jabber:iq:browse","item",jabber_iq_get_server_browse,NULL},
53         {"jabber:iq:browse","query",jabber_iq_get_server_browse,NULL},/* WinJab/Psi bug workaround */
54         {"jabber:iq:version","query",jabber_iq_get_server_version,NULL},
55         {"vcard-temp","vCard",jabber_iq_get_server_vcard,NULL},
56         {"vcard-temp","VCARD",jabber_iq_get_server_vcard,NULL}, /* WinJab bug workaround */
57         {"http://jabber.org/protocol/stats","query",jabber_iq_get_server_stats,NULL},
58         {"http://jabber.org/protocol/disco#items","query",jabber_iq_get_server_disco_items,NULL},
59         {"http://jabber.org/protocol/disco#info","query",jabber_iq_get_server_disco_info,NULL},
60         {NULL,NULL,NULL,NULL}
61 };
62
63 IqNamespace client_iq_ns[]={
64         {"vcard-temp","vCard",jabber_iq_get_user_vcard,NULL},
65         {"vcard-temp","VCARD",jabber_iq_get_user_vcard,NULL}, /* WinJab bug workaround */
66         {"jabber:iq:browse","item",jabber_iq_get_client_browse,NULL},
67         {"jabber:iq:browse","query",jabber_iq_get_client_browse,NULL},/* WinJab/Psi bug workaround */
68         {"jabber:iq:version","query",jabber_iq_get_client_version,NULL},
69         {"http://jabber.org/protocol/disco#items","query",jabber_iq_get_client_disco_items,NULL},
70         {"http://jabber.org/protocol/disco#info","query",jabber_iq_get_client_disco_info,NULL},
71         {NULL,NULL,NULL,NULL}
72 };
73
74 void jabber_iq_send_error(Stream *s,const char *was_from,const char *was_to,const char *id,int code,char *string){
75 xmlnode iq;
76 xmlnode error;
77 char *str;
78
79         if (was_from==NULL) was_from=my_name;
80         iq=xmlnode_new_tag("iq");
81         xmlnode_put_attrib(iq,"type","error");
82         if (id) xmlnode_put_attrib(iq,"id",id);
83         xmlnode_put_attrib(iq,"to",was_from);
84         if (was_to) xmlnode_put_attrib(iq,"from",was_to);
85         else xmlnode_put_attrib(iq,"from",my_name);
86         error=xmlnode_insert_tag(iq,"error");
87         if (code>0){
88                 str=g_strdup_printf("%03u",(unsigned)code);
89                 xmlnode_put_attrib(error,"code",str);
90                 g_free(str);
91         }
92         xmlnode_insert_cdata(error,string,-1);
93         stream_write(s,iq);
94         xmlnode_free(iq);
95 }
96
97 void jabber_iq_send_result(Stream *s,const char *was_from,const char *was_to,const char *id,xmlnode content){
98 xmlnode iq;
99
100         if (was_from==NULL) was_from=my_name;
101         iq=xmlnode_new_tag("iq");
102         xmlnode_put_attrib(iq,"type","result");
103         if (id) xmlnode_put_attrib(iq,"id",id);
104         xmlnode_put_attrib(iq,"to",was_from);
105         if (was_to) xmlnode_put_attrib(iq,"from",was_to);
106         else xmlnode_put_attrib(iq,"from",my_name);
107         if (content) xmlnode_insert_tag_node(iq,content);
108         stream_write(s,iq);
109         xmlnode_free(iq);
110 }
111
112 void jabber_iq_get_agent(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
113 xmlnode n;
114 xmlnode query;
115 char *data;
116
117         query=xmlnode_new_tag("query");
118         xmlnode_put_attrib(query,"xmlns","jabber:iq:agent");
119         n=xmlnode_get_tag(config,"vCard/FN");
120         if (n!=NULL){
121                 data=xmlnode_get_data(n);
122                 if (data!=NULL)
123                         xmlnode_insert_cdata( xmlnode_insert_tag(query,"name"),data,-1);
124         }
125         n=xmlnode_get_tag(config,"vCard/DESC");
126         if (n!=NULL){
127                 data=xmlnode_get_data(n);
128                 if (data!=NULL)
129                         xmlnode_insert_cdata(xmlnode_insert_tag(query,"description"),data,-1);
130         }
131         xmlnode_insert_cdata(xmlnode_insert_tag(query,"transport"),gateway_prompt,-1);
132         xmlnode_insert_cdata(xmlnode_insert_tag(query,"service"),"x-gadugadu",-1); /* until gg is registered */
133         xmlnode_insert_tag(query,"register");
134         xmlnode_insert_tag(query,"search");
135
136         jabber_iq_send_result(s,from,to,id,query);
137 }
138
139 void jabber_iq_get_gateway(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
140 xmlnode query;
141
142         query=xmlnode_new_tag("query");
143         xmlnode_put_attrib(query,"xmlns","jabber:iq:gateway");
144         xmlnode_insert_cdata(xmlnode_insert_tag(query,"desc"),gateway_desc,-1);
145         xmlnode_insert_cdata(xmlnode_insert_tag(query,"prompt"),gateway_prompt,-1);
146         jabber_iq_send_result(s,from,to,id,query);
147 }
148
149 void jabber_iq_get_server_version(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
150 xmlnode query;
151 xmlnode os;
152 char *rel,*p;
153 struct utsname un;
154
155
156         query=xmlnode_new_tag("query");
157         xmlnode_put_attrib(query,"xmlns","jabber:iq:version");
158         xmlnode_insert_cdata(xmlnode_insert_tag(query,"name"),"Gadu-Gadu Transport",-1);
159         xmlnode_insert_cdata(xmlnode_insert_tag(query,"version"),VERSION,-1);
160         uname(&un);
161         os = xmlnode_insert_tag(query,"os");
162         xmlnode_insert_cdata(os,un.sysname,-1);
163         xmlnode_insert_cdata(os," ",1);
164         rel=g_strdup(un.release);
165         p=strchr(rel,'.');
166         if (p) p=strchr(p+1,'.');
167         if (p && p[1]){
168                 p[1]='x';
169                 p[2]='\000';
170         }
171         xmlnode_insert_cdata(os,rel,-1);
172         g_free(rel);
173         jabber_iq_send_result(s,from,to,id,query);
174 }
175
176 void jabber_iq_get_client_version(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
177 xmlnode query;
178 int uin;
179 User *u;
180 GList *it;
181 Contact *c;
182 char verstring[20] = N_("- unknown -"); /* let it be a bit longer */
183 char *ver;
184 int version;
185
186         u=user_get_by_jid(from);
187         if (u==NULL){
188                 g_warning(N_("Unknown user: %s"),from);
189                 jabber_iq_send_error(s,from,to,id,401,_("I don't know you"));
190                 return;
191         }
192         if (!jid_has_uin(to)){
193                 g_warning(N_("No UIN given in 'to': %s"),to);
194                 jabber_iq_send_error(s,from,to,id,400,_("Bad Request"));
195                 return;
196         }
197         query=xmlnode_new_tag("query");
198         xmlnode_put_attrib(query,"xmlns","jabber:iq:version");
199         xmlnode_insert_cdata(xmlnode_insert_tag(query,"name"),"Gadu-Gadu(tm)",-1);
200         uin=jid_get_uin(to);
201         sprintf(verstring, "%s", _(verstring));
202         ver=verstring;
203         for(it=u->contacts;it;it=it->next){
204                 c=(Contact *)it->data;
205                 version=c->version & 0xff;
206                 if (c->uin==uin && version){
207                         if (version < GG_VERSION_ELEMENTS   /* < elements in gg_version[] */
208                            && gg_version[version]){
209                                 ver=gg_version[version];
210                         } else{
211                                 sprintf(verstring, "(prot.0x%02X)", version);
212                         }
213                 }
214         }
215         xmlnode_insert_cdata(xmlnode_insert_tag(query,"version"),ver,-1);
216         jabber_iq_send_result(s,from,to,id,query);
217         xmlnode_free(query);
218 }
219
220 void jabber_iq_set_gateway(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
221 xmlnode n;
222 char *str;
223 int uin;
224 xmlnode query;
225
226         n=xmlnode_get_tag(q,"prompt");
227         if (n==NULL){
228                 jabber_iq_send_error(s,from,to,id,406,_("Not Acceptable"));
229                 return;
230         }
231         str=xmlnode_get_data(n);
232         if (str==NULL){
233                 jabber_iq_send_error(s,from,to,id,406,_("Not Acceptable"));
234                 return;
235         }
236         uin=atoi(str);
237         if (uin<=0){
238                 jabber_iq_send_error(s,from,to,id,406,_("Not Acceptable"));
239                 return;
240         }
241
242         query=xmlnode_new_tag("query");
243         xmlnode_put_attrib(query,"xmlns","jabber:iq:gateway");
244         str=jid_build(uin);
245         xmlnode_insert_cdata(xmlnode_insert_tag(query,"prompt"),str,-1);
246         xmlnode_insert_cdata(xmlnode_insert_tag(query,"jid"),str,-1);
247         g_free(str);
248         jabber_iq_send_result(s,from,to,id,query);
249 }
250
251 void jabber_iq_get_server_vcard(Stream *s,const char *from,const char *to,const char *id,xmlnode q){
252 xmlnode n;
253
254         n=xmlnode_get_tag(config,"vCard");
255         if (!n){
256                 jabber_iq_send_error(s,from,to,id,503,_("Service Unavailable"));
257                 g_warning(N_("No vcard for server defined"));
258                 return;
259         }
260         jabber_iq_send_result(s,from,to,id,n);
261 }
262
263 static void jabber_iq_getset(Stream *s,xmlnode x,int set){
264 char *to;
265 char *id;
266 char *from;
267 char *ns,*name;
268 xmlnode query;
269 IqNamespace *table;
270 int i;
271
272         to=xmlnode_get_attrib(x,"to");
273         id=xmlnode_get_attrib(x,"id");
274         from=xmlnode_get_attrib(x,"from");
275         if (!to || !jid_is_my(to) ){
276                 g_warning(N_("Wrong to=%s (my name is %s)"),to?to:"(null)",my_name);
277                 jabber_iq_send_error(s,from,to,id,400,_("Bad Request"));
278                 return;
279         }
280         if (!from){
281                 g_warning(N_("No from in query: %s"),xmlnode2str(x));
282                 jabber_iq_send_error(s,from,to,id,400,_("Bad Request"));
283                 return;
284         }
285
286         for(query=xmlnode_get_firstchild(x);query;query=xmlnode_get_nextsibling(query))
287                 if (xmlnode_get_type(query)==NTYPE_TAG) break;
288
289         if (!query){
290                 g_warning(N_("No subelement in <iq type='get'> in query: %s"),xmlnode2str(x));
291                 jabber_iq_send_error(s,from,to,id,400,_("Bad Request"));
292                 return;
293         }
294         name=xmlnode_get_name(query);
295         ns=xmlnode_get_attrib(query,"xmlns");
296         if (!ns){
297                 g_warning(N_("No namespace defined for <iq/> subelement: %s"),xmlnode2str(query));
298                 jabber_iq_send_error(s,from,to,id,400,_("Bad Request"));
299                 return;
300         }
301
302         if (jid_is_me(to)) table=server_iq_ns;
303         else table=client_iq_ns;
304
305         for(i=0;table[i].ns;i++)
306                 if (!strcmp(table[i].ns,ns) && !strcmp(table[i].node_name,name)){
307                         if (set){
308                                 if (table[i].set_handler) table[i].set_handler(s,from,to,id,query);
309                                 else{
310                                         g_warning(N_("No <iq type='set'/> implemented for %s"),ns);
311                                         jabber_iq_send_error(s,from,to,id,501,_("Not implemented"));
312                                         return;
313                                 }
314                         }
315                         else{
316                                 if (table[i].get_handler) table[i].get_handler(s,from,to,id,query);
317                                 else{
318                                         g_warning(N_("No <iq type='get'/> implemented for %s"),ns);
319                                         jabber_iq_send_error(s,from,to,id,501,_("Not implemented"));
320                                         return;
321                                 }
322                         }
323                         return;
324                 }
325
326         g_warning(N_("No known content in iq: %s"),xmlnode2str(x));
327         jabber_iq_send_error(s,from,to,id,501,_("Not implemented"));
328 }
329
330 void jabber_iq_not_implemented(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
331
332         jabber_iq_send_error(s,from,to,id,501,_("Not implemented"));
333 }
334
335
336 void jabber_iq_result(Stream *s,xmlnode x){}
337
338 void jabber_iq_error(Stream *s,xmlnode x){
339
340         g_warning(N_("Error iq received: %s"),xmlnode2str(x));
341 }
342
343 void jabber_iq(Stream *s,xmlnode x){
344 char *type;
345 char *from;
346 char *to;
347 char *id;
348 User *u;
349
350         if (jabber_state!=JS_CONNECTED){
351                 g_warning(N_("unexpected <iq/> (not connected yet)"));
352                 return;
353         }
354
355         from=xmlnode_get_attrib(x,"from");
356         type=xmlnode_get_attrib(x,"type");
357         if (!acl_is_allowed(from,x)){
358                 if (type && !strcmp(type,"error")){
359                         debug("Ignoring forbidden error");
360                         return;
361                 }
362                 if (!from) return;
363                 to=xmlnode_get_attrib(x,"to");
364                 id=xmlnode_get_attrib(x,"id");
365                 jabber_iq_send_error(s,from,to,id,405,_("Not allowed"));
366                 return;
367         }
368
369         if (from) u=user_get_by_jid(from);
370         else u=NULL;
371         user_load_locale(u);
372
373         if (strcmp(type,"get")==0)
374                 jabber_iq_getset(s,x,0);
375         else if (strcmp(type,"set")==0)
376                 jabber_iq_getset(s,x,1);
377         else if (strcmp(type,"result")==0)
378                 jabber_iq_result(s,x);
379         else if (strcmp(type,"error")==0)
380                 jabber_iq_error(s,x);
381         else g_warning(N_("Unsupported <iq/> type in: %s"),xmlnode2str(x));
382 }
383
Note: See TracBrowser for help on using the browser.