root/trunk/src/search.c

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

- dates in the copyright header updated

Line 
1 /* $Id: search.c,v 1.37 2003/06/27 17:30: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 <libgadu.h>
22 #include "search.h"
23 #include "requests.h"
24 #include "sessions.h"
25 #include "stream.h"
26 #include "iq.h"
27 #include "jid.h"
28 #include "encoding.h"
29 #include "gg_versions.h"
30 #include "forms.h"
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include "debug.h"
35
36
37 const char *search_instructions;
38
39 void jabber_iq_set_search_byform(Stream *s,const char *from,const char *to,
40                                 const char *id,xmlnode q);
41
42 xmlnode search_form(xmlnode parent){
43 xmlnode form,field;
44
45         form=form_new(parent,_("GG public directory search"),_("Enter your search filter"));
46
47         form_add_field(form,"text-single","uin",_("GG number"),NULL,0);
48         form_add_field(form,"text-single","nick",_("Nick"),NULL,0);
49         form_add_field(form,"text-single","firstname",_("First name"),NULL,0);
50         form_add_field(form,"text-single","lastname",_("Last name"),NULL,0);
51         form_add_field(form,"text-single","birthyear",_("Birth year"),NULL,0);
52         form_add_field(form,"text-single","city",_("City"),NULL,0);
53         field=form_add_field(form,"list-single","gender",_("Sex"),"_any_",0);
54         form_add_option(field,_("Any"),"_any_");
55         form_add_option(field,_("Female"),GG_PUBDIR50_GENDER_FEMALE);
56         form_add_option(field,_("Male"),GG_PUBDIR50_GENDER_MALE);
57         form_add_field(form,"boolean","active",_("Active only"),"0",0);
58         form_add_field(form,"text-single","familyname",_("Family name"),NULL,0);
59         form_add_field(form,"text-single","familycity",_("Family city"),NULL,0);
60         return form;
61 }
62
63 #define GG_SEARCH_FRIENDS_MASK  0x0080
64
65 int search_byform_done(struct request_s *r, gg_pubdir50_t results){
66 int i;
67 xmlnode q,form,item;
68 char *jid;
69 const char *val;
70
71         q=xmlnode_new_tag("query");
72         xmlnode_put_attrib(q,"xmlns","jabber:iq:search");
73         form=form_new_result(_("GG public directory search results"));
74
75         form_add_result_field(form,"jid",_("JID"),"jid-single");
76         form_add_result_field(form,"nick",_("Nick"),"text-single");
77         form_add_result_field(form,"status",_("Status"),"text-single");
78         form_add_result_field(form,"firstname",_("First name"),"text-single");
79         form_add_result_field(form,"lastname",_("Last name"),"text-single");
80         form_add_result_field(form,"city",_("City"),"text-single");
81         form_add_result_field(form,"gender",_("Sex"),"text-single");
82         form_add_result_field(form,"birthyear","Birth year","text-single");
83         form_add_result_field(form,"familyname",_("Family name"),"text-single");
84         form_add_result_field(form,"familycity",_("Family city"),"text-single");
85
86         for(i=0;i<gg_pubdir50_count(results);i++){
87                 item=form_add_result_item(form);
88                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_UIN);
89                 if (val==NULL) continue;
90                 jid=jid_build(atoi(val));
91                 form_add_result_value(item,"jid",jid);
92                 g_free(jid);
93                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_NICKNAME);
94                 form_add_result_value(item,"nick",to_utf8(val));
95                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_STATUS);
96                 switch((val)?(atoi(val) & ~GG_SEARCH_FRIENDS_MASK):-1){
97                         case GG_STATUS_AVAIL:
98                                 form_add_result_value(item,"status",_("Available"));
99                                 break;
100                         case GG_STATUS_BUSY:
101                                 form_add_result_value(item,"status",_("Away"));
102                                 break;
103                         default:
104                                 form_add_result_value(item,"status",_("Unavailable"));
105                                 break;
106                 }
107                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_FIRSTNAME);
108                 form_add_result_value(item,"firstname",to_utf8(val));
109                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_LASTNAME);
110                 form_add_result_value(item,"lastname",to_utf8(val));
111                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_CITY);
112                 form_add_result_value(item,"city",to_utf8(val));
113                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_GENDER);
114                 if (val && !strcmp(val,GG_PUBDIR50_GENDER_FEMALE))
115                         form_add_result_value(item,"gender",_("female"));
116                 else if (val && !strcmp(val,GG_PUBDIR50_GENDER_MALE))
117                         form_add_result_value(item,"gender",_("male"));
118                 else form_add_result_value(item,"gender","");
119                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_BIRTHYEAR);
120                 form_add_result_value(item,"birthyear",to_utf8(val));
121                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_FAMILYNAME);
122                 form_add_result_value(item,"familyname",to_utf8(val));
123                 val=gg_pubdir50_get(results, i, GG_PUBDIR50_FAMILYCITY);
124                 form_add_result_value(item,"familycity",to_utf8(val));
125         }
126         xmlnode_insert_tag_node(q,form);
127         jabber_iq_send_result(r->stream,r->from,r->to,r->id,q);
128         xmlnode_free(q);
129         xmlnode_free(form);
130         return 0;
131 }
132
133 int search_done(struct request_s *r, gg_pubdir50_t results){
134 xmlnode q,item,n;
135 char *jid,*name;
136 int i;
137 const char *uin, *first_name, *last_name, *nickname, *born, *city, *gender, *active;
138
139         n=xmlnode_get_tag(r->query,"x?xmlns=jabber:x:data");
140         if (n){
141                 return search_byform_done(r,results);
142         }
143         q=xmlnode_new_tag("query");
144         xmlnode_put_attrib(q,"xmlns","jabber:iq:search");
145         for(i=0;i<gg_pubdir50_count(results);i++){
146                 item=xmlnode_insert_tag(q,"item");
147                 uin=gg_pubdir50_get(results, i, GG_PUBDIR50_UIN);
148                 if (uin==NULL) continue;
149                 jid=jid_build(atoi(uin));
150                 xmlnode_put_attrib(item,"jid",jid);
151                 g_free(jid);
152                 first_name=gg_pubdir50_get(results, i, GG_PUBDIR50_FIRSTNAME);
153                 last_name=gg_pubdir50_get(results, i, GG_PUBDIR50_LASTNAME);
154                 name=g_strdup_printf("%s %s",first_name,last_name);
155                 n=xmlnode_insert_tag(item,"name");
156                 xmlnode_insert_cdata(n,to_utf8(name),-1);
157                 g_free(name);
158                 n=xmlnode_insert_tag(item,"first");
159                 xmlnode_insert_cdata(n,to_utf8(first_name),-1);
160                 n=xmlnode_insert_tag(item,"last");
161                 xmlnode_insert_cdata(n,to_utf8(last_name),-1);
162                 nickname=gg_pubdir50_get(results, i, GG_PUBDIR50_NICKNAME);
163                 n=xmlnode_insert_tag(item,"nick");
164                 xmlnode_insert_cdata(n,to_utf8(nickname),-1);
165                 born=gg_pubdir50_get(results, i, GG_PUBDIR50_BIRTHYEAR);
166                 if (born){
167                         n=xmlnode_insert_tag(item,"born");
168                         xmlnode_insert_cdata(n,born,-1);
169                 }
170                 gender=gg_pubdir50_get(results, i, GG_PUBDIR50_GENDER);
171                 if (gender && strcmp(gender, GG_PUBDIR50_GENDER_FEMALE)==0)
172                         xmlnode_insert_cdata(xmlnode_insert_tag(item,"gender"),"f",-1);
173                 else if (gender && strcmp(gender, GG_PUBDIR50_GENDER_MALE)==0)
174                         xmlnode_insert_cdata(xmlnode_insert_tag(item,"gender"),"m",-1);
175                 city=gg_pubdir50_get(results, i, GG_PUBDIR50_CITY);
176                 n=xmlnode_insert_tag(item,"city");
177                 xmlnode_insert_cdata(n,to_utf8(city),-1);
178                 active=gg_pubdir50_get(results, i, GG_PUBDIR50_ACTIVE);
179                 if (active && strcmp(active, GG_PUBDIR50_ACTIVE_TRUE)==0)
180                         xmlnode_insert_cdata(xmlnode_insert_tag(item,"active"),"yes",-1);
181         }
182         jabber_iq_send_result(r->stream,r->from,r->to,r->id,q);
183         xmlnode_free(q);
184         return 0;
185 }
186
187 void jabber_iq_get_search(Stream *s,const char *from,const char *to,const char *id,xmlnode q){
188 xmlnode iq,n;
189 Session *sess;
190
191         sess=session_get_by_jid(from,NULL,0);
192         if (!sess || !sess->connected){
193                 jabber_iq_send_error(s,from,to,id,407,_("Not logged in"));
194                 return;
195         }
196
197         iq=xmlnode_new_tag("query");
198         xmlnode_put_attrib(iq,"xmlns","jabber:iq:search");
199         n=xmlnode_insert_tag(iq,"instructions");
200         xmlnode_insert_cdata(n,search_instructions,-1);
201         xmlnode_insert_tag(iq,"active");
202         xmlnode_insert_tag(iq,"first");
203         xmlnode_insert_tag(iq,"last");
204         xmlnode_insert_tag(iq,"nick");
205         xmlnode_insert_tag(iq,"city");
206         xmlnode_insert_tag(iq,"gender");
207         xmlnode_insert_tag(iq,"born");
208         xmlnode_insert_tag(iq,"phone");
209         xmlnode_insert_tag(iq,"username");
210         search_form(iq);
211
212         jabber_iq_send_result(s,from,to,id,iq);
213         xmlnode_free(iq);
214 }
215
216 #define FIELD_TO_PUBDIR(fieldname,symbol) \
217         val=NULL; \
218         field=xmlnode_get_tag(form,"field?var=" fieldname); \
219         if (field!=NULL){ \
220                 value=xmlnode_get_tag(field,"value"); \
221                 if (value!=NULL) val=xmlnode_get_data(value); \
222         } \
223         if (val!=NULL && val[0]) \
224                 gg_pubdir50_add(search, symbol, from_utf8(val));
225
226 void jabber_iq_set_search_byform(Stream *s,const char *from,const char *to,
227                 const char *id,xmlnode q){
228 xmlnode form,field,value;
229 char *val;
230 gg_pubdir50_t search;
231 Session *sess;
232 Request *r;
233
234         form=xmlnode_get_tag(q,"x?xmlns=jabber:x:data");
235
236         sess=session_get_by_jid(from,NULL,0);
237         if (!sess || !sess->connected){
238                 jabber_iq_send_error(s,from,to,id,407,_("Not logged in"));
239                 return;
240         }
241
242         search=gg_pubdir50_new(GG_PUBDIR50_SEARCH);
243         FIELD_TO_PUBDIR("uin",GG_PUBDIR50_UIN);
244         FIELD_TO_PUBDIR("firstname",GG_PUBDIR50_FIRSTNAME);
245         FIELD_TO_PUBDIR("lastname",GG_PUBDIR50_LASTNAME);
246         FIELD_TO_PUBDIR("nick",GG_PUBDIR50_NICKNAME);
247         FIELD_TO_PUBDIR("city",GG_PUBDIR50_CITY);
248
249         field=xmlnode_get_tag(form,"field?var=gender");
250         if (field!=NULL){
251                 value=xmlnode_get_tag(field,"value");
252                 if (value!=NULL) val=xmlnode_get_data(value);
253         }
254         if (val!=NULL && val[0] && ( !strcmp(val,GG_PUBDIR50_GENDER_FEMALE)
255                                         || !strcmp(val,GG_PUBDIR50_GENDER_FEMALE)) )
256                 gg_pubdir50_add(search, GG_PUBDIR50_GENDER, val);
257
258         val=NULL;
259         field=xmlnode_get_tag(form,"field?var=active");
260         if (field!=NULL){
261                 value=xmlnode_get_tag(field,"value");
262                 if (value!=NULL) val=xmlnode_get_data(value);
263         }
264         if (val!=NULL && strcmp(val,"1")==0 )
265                 gg_pubdir50_add(search, GG_PUBDIR50_ACTIVE,GG_PUBDIR50_ACTIVE_TRUE);
266
267         FIELD_TO_PUBDIR("birthyear",GG_PUBDIR50_BIRTHYEAR);
268         FIELD_TO_PUBDIR("familyname",GG_PUBDIR50_FAMILYNAME);
269         FIELD_TO_PUBDIR("familycity",GG_PUBDIR50_FAMILYCITY);
270
271         gg_pubdir50_add(search, GG_PUBDIR50_START, "0");
272
273         r=add_request(RT_SEARCH,from,to,id,q,search,s);
274         gg_pubdir50_free(search);
275 }
276
277 void jabber_iq_set_search(Stream *s,const char *from,const char *to,const char *id,xmlnode q){
278 gg_pubdir50_t sr;
279 xmlnode n;
280 Session *sess;
281 char *data;
282
283         n=xmlnode_get_tag(q,"x?xmlns=jabber:x:data");
284         if (n){
285                 return jabber_iq_set_search_byform(s,from,to,id,q);
286         }
287         sess=session_get_by_jid(from,NULL,0);
288         if (!sess || !sess->connected){
289                 jabber_iq_send_error(s,from,to,id,407,_("Not logged in"));
290                 return;
291         }
292
293         q=xmlnode_dup(q);
294         sr=gg_pubdir50_new(GG_PUBDIR50_SEARCH);
295         n=xmlnode_get_tag(q,"active");
296         if (n){
297                 data=xmlnode_get_data(n);
298                 if (data!=NULL && (data[0]=='y' || data[0]=='Y' || data[0]=='t' || data[0]=='T'))
299                         gg_pubdir50_add(sr, GG_PUBDIR50_ACTIVE, GG_PUBDIR50_ACTIVE_TRUE);
300         }
301         n=xmlnode_get_tag(q,"nick");
302         if (n){
303                 data=xmlnode_get_data(n);
304                 if (data)
305                         gg_pubdir50_add(sr, GG_PUBDIR50_NICKNAME, from_utf8(data));
306         }
307         n=xmlnode_get_tag(q,"first");
308         if (n){
309                 data=xmlnode_get_data(n);
310                 if (data)
311                         gg_pubdir50_add(sr, GG_PUBDIR50_FIRSTNAME, from_utf8(data));
312         }
313         n=xmlnode_get_tag(q,"last");
314         if (n){
315                 data=xmlnode_get_data(n);
316                 if (data)
317                         gg_pubdir50_add(sr, GG_PUBDIR50_LASTNAME, from_utf8(data));
318         }
319         n=xmlnode_get_tag(q,"city");
320         if (n){
321                 data=xmlnode_get_data(n);
322                 if (data)
323                         gg_pubdir50_add(sr, GG_PUBDIR50_CITY, from_utf8(data));
324         }
325         n=xmlnode_get_tag(q,"gender");
326         if (n){
327                 data=xmlnode_get_data(n);
328                 if (data!=NULL){
329                         if (data[0]=='k' || data[0]=='f' || data[0]=='K' || data[0]=='F')
330                                 gg_pubdir50_add(sr, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_FEMALE);
331                         else if (data[0]=='m' || data[0]=='M')
332                                 gg_pubdir50_add(sr, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_MALE);
333                 }
334         }
335         n=xmlnode_get_tag(q,"born");
336         if (n){
337                 data=xmlnode_get_data(n);
338                 if (data)
339                         gg_pubdir50_add(sr, GG_PUBDIR50_BIRTHYEAR, data);
340         }
341         n=xmlnode_get_tag(q,"username");
342         if (n){
343                 data=xmlnode_get_data(n);
344                 if (data)
345                         gg_pubdir50_add(sr, GG_PUBDIR50_UIN, data);
346         }
347
348         add_request(RT_SEARCH,from,to,id,q,(void*)sr,s);
349         gg_pubdir50_free(sr);
350 }
351
352 void jabber_iq_get_user_vcard(Stream *s,const char *from,const char * to,const char *id,xmlnode q){
353 int i=0;
354 char *uin;
355 gg_pubdir50_t sr;
356
357         sr=gg_pubdir50_new(GG_PUBDIR50_SEARCH);
358
359         while(to[i]!='@')
360                 i++;
361
362         uin=g_strndup(to, i);
363
364         gg_pubdir50_add(sr, GG_PUBDIR50_UIN, uin);
365
366         add_request(RT_VCARD,from,to,id,q,(void*)sr,s);
367
368         gg_pubdir50_free(sr);
369         g_free(uin);
370 }
371
372 int vcard_done(struct request_s *r, gg_pubdir50_t results){
373 xmlnode vc,n,n1;
374 char *jid,*name=NULL,*str;
375 GList *it;
376 Contact *c;
377 User *u;
378 const char *uin, *first_name, *last_name, *nickname, *born, *city;
379
380
381         if (gg_pubdir50_count(results)<1){
382                 jabber_iq_send_error(r->stream,r->from,r->to,r->id,404,_("Not Found"));
383                 return 1;
384         }
385
386         uin=gg_pubdir50_get(results, 0, GG_PUBDIR50_UIN);
387         first_name=gg_pubdir50_get(results, 0, GG_PUBDIR50_FIRSTNAME);
388         last_name=gg_pubdir50_get(results, 0, GG_PUBDIR50_LASTNAME);
389         nickname=gg_pubdir50_get(results, 0, GG_PUBDIR50_NICKNAME);
390         born=gg_pubdir50_get(results, 0, GG_PUBDIR50_BIRTHYEAR);
391         city=gg_pubdir50_get(results, 0, GG_PUBDIR50_CITY);
392
393         vc=xmlnode_new_tag("vCard");
394         xmlnode_put_attrib(vc,"xmlns","vcard-temp");
395         xmlnode_put_attrib(vc,"version","2.0");
396
397         n=xmlnode_insert_tag(vc,"FN");
398         if (first_name && last_name){
399                 name=g_strdup_printf("%s %s",first_name,
400                                                         last_name);
401                 xmlnode_insert_cdata(n,to_utf8(name),-1);
402         }
403         else if (first_name){
404                 xmlnode_insert_cdata(n,to_utf8(first_name),-1);
405         }
406         else if (last_name){
407                 xmlnode_insert_cdata(n,to_utf8(last_name),-1);
408         }
409         g_free(name);
410
411         n1=xmlnode_insert_tag(vc,"N");
412         n=xmlnode_insert_tag(n1,"GIVEN");
413         if (first_name){
414                 xmlnode_insert_cdata(n,to_utf8(first_name),-1);
415         }
416         n=xmlnode_insert_tag(n1,"FAMILY");
417         if (last_name){
418                 xmlnode_insert_cdata(n,to_utf8(last_name),-1);
419         }
420
421         n=xmlnode_insert_tag(vc,"NICKNAME");
422         if (nickname){
423                 xmlnode_insert_cdata(n,to_utf8(nickname),-1);
424         }
425
426         if (born){
427                 n=xmlnode_insert_tag(vc,"BDAY");
428                 xmlnode_insert_cdata(n,born,-1);
429         }
430
431         n1=xmlnode_insert_tag(vc,"ADR");
432         xmlnode_insert_tag(n1,"HOME");
433         n=xmlnode_insert_tag(n1,"LOCALITY");
434         xmlnode_insert_cdata(n,to_utf8(city),-1);
435
436         if (uin){
437                 jid=jid_build(atoi(uin));
438                 n=xmlnode_insert_tag(vc,"JABBERID");
439                 xmlnode_insert_cdata(n,jid,-1);
440                 g_free(jid);
441         }
442
443         c=NULL;
444         u=user_get_by_jid(r->from);
445         if (u){
446                 for(it=g_list_first(u->contacts);it;it=it->next){
447                         c=(Contact *)it->data;
448                         if (c->uin==atoi(uin)) break;
449                 }
450                 if (it==NULL) c=NULL;
451         }
452
453         n=xmlnode_insert_tag(vc,"DESC");
454         xmlnode_insert_cdata(n,_("GG user\n"),-1);
455         if (c!=NULL){
456                 struct in_addr a;
457                 a.s_addr=c->ip;
458                 str=g_strdup_printf(_("Client version: %s (prot.0x%02X)\n"),
459                                         ((c->version & 0xff) < GG_VERSION_ELEMENTS) && gg_version[c->version & 0xff]
460                                                 ? gg_version[c->version & 0xff]
461                                                 : "?.?.?",
462                                         c->version & 0xff);
463                 xmlnode_insert_cdata(n,str,-1);
464                 g_free(str);
465                 str=g_strdup_printf(_("User IP: %s\n"),inet_ntoa(a));
466                 xmlnode_insert_cdata(n,str,-1);
467                 g_free(str);
468                 str=g_strdup_printf(_("User port: %u\n"),(unsigned)c->port);
469                 xmlnode_insert_cdata(n,str,-1);
470                 g_free(str);
471         }
472
473         jabber_iq_send_result(r->stream,r->from,r->to,r->id,vc);
474         xmlnode_free(vc);
475         return 0;
476 }
477
Note: See TracBrowser for help on using the browser.