Mercurial > hg
annotate mcabber/src/jabglue.c @ 293:d0295e735768
Assignment lvalue (key, option name, alias...) cannnot contain spaces
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sat, 09 Jul 2005 09:50:01 +0100 |
parents | 4d7040cff8ee |
children | 871e53769084 |
rev | line source |
---|---|
29 | 1 /* |
2 * jabglue.c -- Jabber protocol handling | |
3 * | |
4 * Copyright (C) 2005 Mikael Berthe <bmikael@lists.lilotux.net> | |
5 * Parts come from the centericq project: | |
6 * Copyright (C) 2002-2005 by Konstantin Klyagin <konst@konst.org.ua> | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or (at | |
11 * your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, but | |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
21 * USA | |
22 */ | |
23 | |
237 | 24 #define _GNU_SOURCE /* We need glibc for strptime */ |
29 | 25 #include "../libjabber/jabber.h" |
26 #include "jabglue.h" | |
81 | 27 #include "roster.h" |
29 | 28 #include "screen.h" |
113 | 29 #include "hooks.h" |
213 | 30 #include "utf8.h" |
29 | 31 #include "utils.h" |
32 | |
33 #define JABBERPORT 5222 | |
34 #define JABBERSSLPORT 5223 | |
35 | |
194 | 36 #define JABBER_AGENT_GROUP "Jabber Agents" |
37 | |
29 | 38 jconn jc; |
112 | 39 time_t LastPingTime; |
40 unsigned int KeepaliveDelay; | |
272 | 41 static unsigned int prio; |
31 | 42 static int s_id = 1; // FIXME which use?? |
43 static int regmode, regdone; | |
116 | 44 static enum imstatus mystatus = offline; |
112 | 45 unsigned char online; |
29 | 46 |
46 | 47 char imstatus2char[imstatus_size] = { |
277
4d7040cff8ee
Remove busy/occupied status, which does not really exist
Mikael Berthe <mikael@lilotux.net>
parents:
272
diff
changeset
|
48 '_', 'o', 'i', 'f', 'd', 'n', 'a' |
46 | 49 }; |
50 | |
31 | 51 static enum { |
29 | 52 STATE_CONNECTING, |
53 STATE_GETAUTH, | |
54 STATE_SENDAUTH, | |
55 STATE_LOGGED | |
56 } jstate; | |
57 | |
58 | |
31 | 59 void statehandler(jconn, int); |
60 void packethandler(jconn, jpacket); | |
61 | |
62 void screen_logger(jconn j, int io, const char *buf) | |
63 { | |
36 | 64 scr_LogPrint("%03s: %s", ((io == 0) ? "OUT" : "IN"), buf); |
31 | 65 } |
66 | |
67 void file_logger(jconn j, int io, const char *buf) | |
68 { | |
36 | 69 ut_WriteLog("%03s: %s\n", ((io == 0) ? "OUT" : "IN"), buf); |
31 | 70 } |
71 | |
72 void big_logger(jconn j, int io, const char *buf) | |
73 { | |
74 screen_logger(j, io, buf); | |
75 file_logger(j, io, buf); | |
76 } | |
77 | |
113 | 78 /* |
29 | 79 static void jidsplit(const char *jid, char **user, char **host, |
80 char **res) | |
81 { | |
82 char *tmp, *ptr; | |
83 tmp = strdup(jid); | |
84 | |
85 if ((ptr = strchr(tmp, '/')) != NULL) { | |
86 *res = strdup(ptr+1); | |
87 *ptr = 0; | |
88 } else | |
89 *res = NULL; | |
90 | |
91 if ((ptr = strchr(tmp, '@')) != NULL) { | |
92 *host = strdup(ptr+1); | |
93 *ptr = 0; | |
94 } else | |
95 *host = NULL; | |
96 | |
97 *user = strdup(tmp); | |
98 free(tmp); | |
99 } | |
113 | 100 */ |
29 | 101 |
192 | 102 // jidtodisp(jid) |
103 // Strips the resource part from the jid | |
104 // The caller should g_free the result after use. | |
29 | 105 char *jidtodisp(const char *jid) |
106 { | |
107 char *ptr; | |
165 | 108 char *alias; |
109 | |
110 while ((alias = g_strdup(jid)) == NULL) | |
111 usleep(100); | |
112 | |
29 | 113 if ((ptr = strchr(alias, '/')) != NULL) { |
114 *ptr = 0; | |
115 } | |
116 return alias; | |
117 } | |
118 | |
35 | 119 jconn jb_connect(const char *jid, unsigned int port, int ssl, const char *pass) |
29 | 120 { |
121 if (!port) { | |
122 if (ssl) | |
123 port = JABBERSSLPORT; | |
124 else | |
125 port = JABBERPORT; | |
126 } | |
127 | |
128 if (jc) | |
129 free(jc); | |
130 | |
51 | 131 jc = jab_new((char*)jid, (char*)pass, port, ssl); |
29 | 132 |
35 | 133 jab_logger(jc, file_logger); |
29 | 134 jab_packet_handler(jc, &packethandler); |
135 jab_state_handler(jc, &statehandler); | |
136 | |
137 if (jc->user) { | |
112 | 138 online = TRUE; |
29 | 139 jstate = STATE_CONNECTING; |
140 statehandler(0, -1); | |
141 jab_start(jc); | |
142 } | |
143 | |
144 return jc; | |
145 } | |
146 | |
147 void jb_disconnect(void) | |
148 { | |
149 statehandler(jc, JCONN_STATE_OFF); | |
150 } | |
151 | |
112 | 152 inline void jb_reset_keepalive() |
153 { | |
154 time(&LastPingTime); | |
155 } | |
156 | |
29 | 157 void jb_keepalive() |
158 { | |
113 | 159 if (jc && online) |
112 | 160 jab_send_raw(jc, " \t "); |
161 jb_reset_keepalive(); | |
162 } | |
163 | |
164 void jb_set_keepalive_delay(unsigned int delay) | |
165 { | |
166 KeepaliveDelay = delay; | |
29 | 167 } |
168 | |
272 | 169 inline void jb_set_priority(unsigned int priority) |
170 { | |
171 prio = priority; | |
172 } | |
173 | |
29 | 174 void jb_main() |
175 { | |
176 xmlnode x, z; | |
177 char *cid; | |
178 | |
164 | 179 if (!online) return; |
180 | |
29 | 181 if (jc && jc->state == JCONN_STATE_CONNECTING) { |
182 jab_start(jc); | |
183 return; | |
184 } | |
185 | |
31 | 186 jab_poll(jc, 50); |
29 | 187 |
188 if (jstate == STATE_CONNECTING) { | |
189 if (jc) { | |
190 x = jutil_iqnew(JPACKET__GET, NS_AUTH); | |
191 cid = jab_getid(jc); | |
192 xmlnode_put_attrib(x, "id", cid); | |
193 // id = atoi(cid); | |
194 | |
195 z = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "username"); | |
196 xmlnode_insert_cdata(z, jc->user->user, (unsigned) -1); | |
197 jab_send(jc, x); | |
198 xmlnode_free(x); | |
199 | |
200 jstate = STATE_GETAUTH; | |
201 } | |
202 | |
203 if (!jc || jc->state == JCONN_STATE_OFF) { | |
204 scr_LogPrint("Unable to connect to the server"); | |
112 | 205 online = FALSE; |
29 | 206 } |
207 } | |
208 | |
209 if (!jc) { | |
210 statehandler(jc, JCONN_STATE_OFF); | |
211 } else if (jc->state == JCONN_STATE_OFF || jc->fd == -1) { | |
212 statehandler(jc, JCONN_STATE_OFF); | |
213 } | |
112 | 214 |
215 // Keepalive | |
216 if (KeepaliveDelay) { | |
217 time_t now; | |
218 time(&now); | |
219 if (now > LastPingTime + KeepaliveDelay) | |
220 jb_keepalive(); | |
221 } | |
29 | 222 } |
223 | |
116 | 224 inline enum imstatus jb_getstatus() |
225 { | |
226 return mystatus; | |
227 } | |
228 | |
229 void jb_setstatus(enum imstatus st, char *msg) | |
29 | 230 { |
116 | 231 xmlnode x; |
232 | |
164 | 233 if (!online) return; |
116 | 234 |
235 x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); | |
29 | 236 |
237 switch(st) { | |
238 case away: | |
239 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "away", | |
240 (unsigned) -1); | |
241 break; | |
242 | |
243 case dontdisturb: | |
244 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "dnd", | |
245 (unsigned) -1); | |
246 break; | |
247 | |
248 case freeforchat: | |
249 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "chat", | |
250 (unsigned) -1); | |
251 break; | |
252 | |
253 case notavail: | |
254 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "xa", | |
255 (unsigned) -1); | |
256 break; | |
257 | |
258 case invisible: | |
259 xmlnode_put_attrib(x, "type", "invisible"); | |
260 break; | |
51 | 261 |
118 | 262 case offline: |
263 xmlnode_put_attrib(x, "type", "unavailable"); | |
264 break; | |
265 | |
51 | 266 default: |
267 break; | |
29 | 268 } |
269 | |
272 | 270 if (prio) { |
271 char strprio[8]; | |
272 snprintf(strprio, 8, "%u", prio); | |
29 | 273 xmlnode_insert_cdata(xmlnode_insert_tag(x, "priority"), |
272 | 274 strprio, (unsigned) -1); |
275 } | |
29 | 276 |
116 | 277 if (!msg) { |
51 | 278 msg = ""; // FIXME |
29 | 279 //msg = imstatus2str(st); |
280 } | |
281 | |
282 xmlnode_insert_cdata(xmlnode_insert_tag(x, "status"), msg, | |
283 (unsigned) -1); | |
284 | |
285 jab_send(jc, x); | |
286 xmlnode_free(x); | |
287 | |
116 | 288 //sendvisibility(); ??? |
29 | 289 |
164 | 290 // We'll need to update the roster if we switch to/from offline because |
291 // we don't know the presences of buddies when offline... | |
292 if (mystatus == offline || st == offline) | |
293 update_roster = TRUE; | |
294 | |
116 | 295 hk_mystatuschange(0, mystatus, st); |
296 mystatus = st; | |
29 | 297 } |
298 | |
35 | 299 void jb_send_msg(const char *jid, const char *text) |
300 { | |
213 | 301 char *buffer = utf8_encode(text); |
302 xmlnode x = jutil_msgnew(TMSG_CHAT, (char*)jid, 0, (char*)buffer); | |
35 | 303 jab_send(jc, x); |
304 xmlnode_free(x); | |
213 | 305 free(buffer); |
114 | 306 jb_reset_keepalive(); |
35 | 307 } |
308 | |
213 | 309 // Note: the caller should check the jid is correct |
244 | 310 void jb_addbuddy(const char *jid, const char *name, const char *group) |
124 | 311 { |
312 xmlnode x, y, z; | |
192 | 313 char *cleanjid; |
124 | 314 |
208 | 315 if (!online) return; |
124 | 316 |
317 // We don't check if the jabber user already exists in the roster, | |
318 // because it allows to re-ask for notification. | |
319 | |
320 //x = jutil_presnew(JPACKET__SUBSCRIBE, jid, NULL); | |
125 | 321 x = jutil_presnew(JPACKET__SUBSCRIBE, (char*)jid, "online"); |
124 | 322 jab_send(jc, x); |
323 xmlnode_free(x); | |
324 | |
325 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
326 y = xmlnode_get_tag(x, "query"); | |
327 z = xmlnode_insert_tag(y, "item"); | |
328 xmlnode_put_attrib(z, "jid", jid); | |
329 | |
244 | 330 if (name) { |
331 char *name_utf8 = utf8_encode(name); | |
332 z = xmlnode_insert_tag(z, "name"); | |
333 xmlnode_insert_cdata(z, name_utf8, (unsigned) -1); | |
334 free(name_utf8); | |
335 } | |
336 | |
124 | 337 if (group) { |
213 | 338 char *group_utf8 = utf8_encode(group); |
124 | 339 z = xmlnode_insert_tag(z, "group"); |
213 | 340 xmlnode_insert_cdata(z, group_utf8, (unsigned) -1); |
341 free(group_utf8); | |
124 | 342 } |
343 | |
344 jab_send(jc, x); | |
345 xmlnode_free(x); | |
346 | |
192 | 347 cleanjid = jidtodisp(jid); |
244 | 348 roster_add_user(cleanjid, name, group, ROSTER_TYPE_USER); |
192 | 349 g_free(cleanjid); |
124 | 350 buddylist_build(); |
351 | |
244 | 352 update_roster = TRUE; |
124 | 353 } |
354 | |
205 | 355 void jb_delbuddy(const char *jid) |
356 { | |
357 xmlnode x, y, z; | |
358 char *cleanjid; | |
359 | |
360 if (!online) return; | |
361 | |
362 cleanjid = jidtodisp(jid); | |
363 | |
364 // If the current buddy is an agent, unsubscribe from it | |
365 if (roster_gettype(cleanjid) == ROSTER_TYPE_AGENT) { | |
366 scr_LogPrint("Unregistering from the %s agent", cleanjid); | |
367 | |
368 x = jutil_iqnew(JPACKET__SET, NS_REGISTER); | |
369 xmlnode_put_attrib(x, "to", cleanjid); | |
370 y = xmlnode_get_tag(x, "query"); | |
371 xmlnode_insert_tag(y, "remove"); | |
372 jab_send(jc, x); | |
373 xmlnode_free(x); | |
374 } | |
375 | |
376 // Unsubscribe this buddy from our presence notification | |
377 x = jutil_presnew(JPACKET__UNSUBSCRIBE, cleanjid, 0); | |
378 jab_send(jc, x); | |
379 xmlnode_free(x); | |
380 | |
381 // Ask for removal from roster | |
382 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
383 y = xmlnode_get_tag(x, "query"); | |
384 z = xmlnode_insert_tag(y, "item"); | |
385 xmlnode_put_attrib(z, "jid", cleanjid); | |
386 xmlnode_put_attrib(z, "subscription", "remove"); | |
387 jab_send(jc, x); | |
388 xmlnode_free(x); | |
389 | |
390 roster_del_user(cleanjid); | |
391 g_free(cleanjid); | |
392 buddylist_build(); | |
393 | |
394 update_roster = TRUE; | |
395 } | |
396 | |
208 | 397 void jb_updatebuddy(const char *jid, const char *name, const char *group) |
398 { | |
399 xmlnode x, y; | |
400 char *cleanjid; | |
213 | 401 char *name_utf8; |
208 | 402 |
403 if (!online) return; | |
404 | |
405 // XXX We should check name's and group's correctness | |
406 | |
407 cleanjid = jidtodisp(jid); | |
213 | 408 name_utf8 = utf8_encode(name); |
208 | 409 |
410 x = jutil_iqnew(JPACKET__SET, NS_ROSTER); | |
411 y = xmlnode_insert_tag(xmlnode_get_tag(x, "query"), "item"); | |
412 xmlnode_put_attrib(y, "jid", cleanjid); | |
213 | 413 xmlnode_put_attrib(y, "name", name_utf8); |
208 | 414 |
415 if (group) { | |
213 | 416 char *group_utf8 = utf8_encode(group); |
208 | 417 y = xmlnode_insert_tag(y, "group"); |
213 | 418 xmlnode_insert_cdata(y, group_utf8, (unsigned) -1); |
419 free(group_utf8); | |
208 | 420 } |
421 | |
422 jab_send(jc, x); | |
423 xmlnode_free(x); | |
213 | 424 free(name_utf8); |
208 | 425 g_free(cleanjid); |
426 } | |
427 | |
31 | 428 void postlogin() |
429 { | |
430 //int i; | |
431 | |
432 //flogged = TRUE; | |
433 //ourstatus = available; | |
434 | |
435 //setautostatus(jhook.manualstatus); | |
436 | |
116 | 437 jb_setstatus(available, "I'm here!"); // XXX not always "available"... |
81 | 438 buddylist_build(); |
31 | 439 /* |
440 for (i = 0; i < clist.count; i++) { | |
441 c = (icqcontact *) clist.at(i); | |
442 | |
443 if (c->getdesc().pname == proto) | |
444 if (ischannel(c)) | |
445 if (c->getbasicinfo().requiresauth) | |
446 c->setstatus(available); | |
447 } | |
448 */ | |
449 | |
450 /* | |
451 agents.insert(agents.begin(), agent("vcard", "Jabber VCard", "", agent::atStandard)); | |
452 agents.begin()->params[agent::ptRegister].enabled = TRUE; | |
453 | |
454 string buf; | |
455 ifstream f(conf.getconfigfname("jabber-infoset").c_str()); | |
456 | |
457 if (f.is_open()) { | |
458 icqcontact *c = clist.get(contactroot); | |
459 | |
460 c->clear(); | |
461 icqcontact::basicinfo bi = c->getbasicinfo(); | |
462 icqcontact::reginfo ri = c->getreginfo(); | |
463 | |
464 ri.service = agents.begin()->name; | |
465 getstring(f, buf); c->setnick(buf); | |
466 getstring(f, buf); bi.email = buf; | |
467 getstring(f, buf); bi.fname = buf; | |
468 getstring(f, buf); bi.lname = buf; | |
469 f.close(); | |
470 | |
471 c->setbasicinfo(bi); | |
472 c->setreginfo(ri); | |
473 | |
474 sendupdateuserinfo(*c); | |
475 unlink(conf.getconfigfname("jabber-infoset").c_str()); | |
476 } | |
477 */ | |
478 } | |
479 | |
29 | 480 void gotloggedin(void) |
481 { | |
482 xmlnode x; | |
483 | |
484 x = jutil_iqnew(JPACKET__GET, NS_AGENTS); | |
485 xmlnode_put_attrib(x, "id", "Agent List"); | |
486 jab_send(jc, x); | |
487 xmlnode_free(x); | |
488 | |
489 x = jutil_iqnew(JPACKET__GET, NS_ROSTER); | |
490 xmlnode_put_attrib(x, "id", "Roster"); | |
491 jab_send(jc, x); | |
492 xmlnode_free(x); | |
493 } | |
494 | |
495 void gotroster(xmlnode x) | |
496 { | |
33 | 497 xmlnode y, z; |
29 | 498 |
499 for (y = xmlnode_get_tag(x, "item"); y; y = xmlnode_get_nextsibling(y)) { | |
500 const char *alias = xmlnode_get_attrib(y, "jid"); | |
51 | 501 //const char *sub = xmlnode_get_attrib(y, "subscription"); // TODO Not used |
29 | 502 const char *name = xmlnode_get_attrib(y, "name"); |
213 | 503 char *group = NULL; |
29 | 504 |
33 | 505 z = xmlnode_get_tag(y, "group"); |
506 if (z) group = xmlnode_get_data(z); | |
29 | 507 |
508 if (alias) { | |
35 | 509 char *buddyname; |
192 | 510 char *cleanalias = jidtodisp(alias); |
213 | 511 char *name_noutf8 = NULL; |
512 char *group_noutf8 = NULL; | |
513 | |
514 if (name) { | |
515 name_noutf8 = utf8_decode(name); | |
516 buddyname = name_noutf8; | |
517 } else | |
192 | 518 buddyname = cleanalias; |
35 | 519 |
213 | 520 if (group) group_noutf8 = utf8_decode(group); |
521 roster_add_user(cleanalias, buddyname, group_noutf8, ROSTER_TYPE_USER); | |
522 if (name_noutf8) free(name_noutf8); | |
523 if (group_noutf8) free(group_noutf8); | |
192 | 524 g_free(cleanalias); |
29 | 525 } |
526 } | |
527 | |
528 postlogin(); | |
529 } | |
530 | |
531 void gotmessage(char *type, const char *from, const char *body, | |
223 | 532 const char *enc, time_t timestamp) |
29 | 533 { |
113 | 534 char *jid; |
213 | 535 char *buffer = utf8_decode(body); |
29 | 536 |
35 | 537 /* |
113 | 538 //char *u, *h, *r; |
539 //jidsplit(from, &u, &h, &r); | |
35 | 540 // Maybe we should remember the resource? |
541 if (r) | |
542 scr_LogPrint("There is an extra part in message (resource?): %s", r); | |
113 | 543 //scr_LogPrint("Msg from <%s>, type=%s", jidtodisp(from), type); |
35 | 544 */ |
545 | |
113 | 546 jid = jidtodisp(from); |
223 | 547 hk_message_in(jid, timestamp, buffer); |
192 | 548 g_free(jid); |
213 | 549 free(buffer); |
29 | 550 } |
551 | |
31 | 552 void statehandler(jconn conn, int state) |
553 { | |
554 static int previous_state = -1; | |
555 | |
35 | 556 ut_WriteLog("StateHandler called (state=%d).\n", state); |
31 | 557 |
558 switch(state) { | |
559 case JCONN_STATE_OFF: | |
192 | 560 if (previous_state != JCONN_STATE_OFF) |
561 scr_LogPrint("+ JCONN_STATE_OFF"); | |
37 | 562 |
112 | 563 online = FALSE; |
159 | 564 mystatus = offline; |
164 | 565 roster_free(); |
566 update_roster = TRUE; | |
31 | 567 break; |
568 | |
569 case JCONN_STATE_CONNECTED: | |
35 | 570 scr_LogPrint("+ JCONN_STATE_CONNECTED"); |
31 | 571 break; |
572 | |
573 case JCONN_STATE_AUTH: | |
35 | 574 scr_LogPrint("+ JCONN_STATE_AUTH"); |
31 | 575 break; |
576 | |
577 case JCONN_STATE_ON: | |
35 | 578 scr_LogPrint("+ JCONN_STATE_ON"); |
112 | 579 online = TRUE; |
31 | 580 break; |
581 | |
35 | 582 case JCONN_STATE_CONNECTING: |
583 scr_LogPrint("+ JCONN_STATE_CONNECTING"); | |
584 break; | |
585 | |
31 | 586 default: |
587 break; | |
588 } | |
589 previous_state = state; | |
590 } | |
591 | |
592 void packethandler(jconn conn, jpacket packet) | |
593 { | |
91 | 594 char *p, *r; |
37 | 595 xmlnode x, y; |
31 | 596 char *from=NULL, *type=NULL, *body=NULL, *enc=NULL; |
597 char *ns=NULL; | |
598 char *id=NULL; | |
35 | 599 enum imstatus ust; |
31 | 600 // int npos; |
601 | |
112 | 602 jb_reset_keepalive(); // reset keepalive delay |
31 | 603 jpacket_reset(packet); |
604 | |
605 p = xmlnode_get_attrib(packet->x, "from"); if (p) from = p; | |
606 p = xmlnode_get_attrib(packet->x, "type"); if (p) type = p; | |
607 | |
608 switch (packet->type) { | |
609 case JPACKET_MESSAGE: | |
52 | 610 { |
611 char *tmp = NULL; | |
223 | 612 time_t timestamp = 0; |
613 | |
52 | 614 x = xmlnode_get_tag(packet->x, "body"); |
615 p = xmlnode_get_data(x); if (p) body = p; | |
31 | 616 |
52 | 617 if ((x = xmlnode_get_tag(packet->x, "subject")) != NULL) |
618 if ((p = xmlnode_get_data(x)) != NULL) { | |
165 | 619 tmp = g_new(char, strlen(body)+strlen(p)+4); |
52 | 620 *tmp = '['; |
621 strcpy(tmp+1, p); | |
622 strcat(tmp, "]\n"); | |
623 strcat(tmp, body); | |
624 body = tmp; | |
625 } | |
626 | |
627 /* there can be multiple <x> tags. we're looking for one with | |
628 xmlns = jabber:x:encrypted */ | |
629 | |
630 for (x = xmlnode_get_firstchild(packet->x); x; x = xmlnode_get_nextsibling(x)) { | |
631 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) | |
632 if ((p = xmlnode_get_attrib(x, "xmlns")) && | |
633 !strcasecmp(p, "jabber:x:encrypted")) | |
634 if ((p = xmlnode_get_data(x)) != NULL) { | |
635 enc = p; | |
636 break; | |
637 } | |
31 | 638 } |
639 | |
223 | 640 // Timestamp? |
641 if ((x = xmlnode_get_tag(packet->x, "x")) != NULL) { | |
241 | 642 if ((p = xmlnode_get_attrib(x, "stamp")) != NULL) |
643 timestamp = from_iso8601(p, 1); | |
223 | 644 } |
645 | |
165 | 646 if (from && body) |
223 | 647 gotmessage(type, from, body, enc, timestamp); |
52 | 648 if (tmp) |
159 | 649 g_free(tmp); |
31 | 650 } |
651 break; | |
652 | |
653 case JPACKET_IQ: | |
654 if (!strcmp(type, "result")) { | |
655 | |
51 | 656 if ((p = xmlnode_get_attrib(packet->x, "id")) != NULL) { |
31 | 657 int iid = atoi(p); |
658 | |
659 ut_WriteLog("iid = %d\n", iid); | |
660 if (iid == s_id) { | |
661 if (!regmode) { | |
662 if (jstate == STATE_GETAUTH) { | |
51 | 663 if ((x = xmlnode_get_tag(packet->x, "query")) != NULL) |
31 | 664 if (!xmlnode_get_tag(x, "digest")) { |
665 jc->sid = 0; | |
666 } | |
667 | |
668 s_id = atoi(jab_auth(jc)); | |
669 jstate = STATE_SENDAUTH; | |
670 } else { | |
671 gotloggedin(); | |
672 jstate = STATE_LOGGED; | |
673 } | |
674 } else { | |
675 regdone = TRUE; | |
676 } | |
677 return; | |
678 } | |
679 | |
680 if (!strcmp(p, "VCARDreq")) { | |
681 x = xmlnode_get_firstchild(packet->x); | |
682 if (!x) x = packet->x; | |
683 | |
684 //jhook.gotvcard(ic, x); TODO | |
685 scr_LogPrint("Got VCARD"); | |
686 return; | |
687 } else if (!strcmp(p, "versionreq")) { | |
688 // jhook.gotversion(ic, packet->x); TODO | |
689 scr_LogPrint("Got version"); | |
690 return; | |
691 } | |
692 } | |
693 | |
51 | 694 if ((x = xmlnode_get_tag(packet->x, "query")) != NULL) { |
31 | 695 p = xmlnode_get_attrib(x, "xmlns"); if (p) ns = p; |
696 | |
697 if (!strcmp(ns, NS_ROSTER)) { | |
698 gotroster(x); | |
699 } else if (!strcmp(ns, NS_AGENTS)) { | |
700 for (y = xmlnode_get_tag(x, "agent"); y; y = xmlnode_get_nextsibling(y)) { | |
701 const char *alias = xmlnode_get_attrib(y, "jid"); | |
702 | |
703 if (alias) { | |
704 const char *name = xmlnode_get_tag_data(y, "name"); | |
705 const char *desc = xmlnode_get_tag_data(y, "description"); | |
51 | 706 // const char *service = xmlnode_get_tag_data(y, "service"); TODO |
37 | 707 enum agtype atype = unknown; |
31 | 708 |
37 | 709 if (xmlnode_get_tag(y, "groupchat")) atype = groupchat; else |
710 if (xmlnode_get_tag(y, "transport")) atype = transport; else | |
711 if (xmlnode_get_tag(y, "search")) atype = search; | |
31 | 712 |
192 | 713 if (atype == transport) { |
714 char *cleanjid = jidtodisp(alias); | |
194 | 715 roster_add_user(cleanjid, NULL, JABBER_AGENT_GROUP, |
716 ROSTER_TYPE_AGENT); | |
192 | 717 g_free(cleanjid); |
718 } | |
31 | 719 if (alias && name && desc) { |
37 | 720 scr_LogPrint("Agent: %s / %s / %s / type=%d", |
721 alias, name, desc, atype); | |
31 | 722 |
37 | 723 if (atype == search) { |
31 | 724 x = jutil_iqnew (JPACKET__GET, NS_SEARCH); |
725 xmlnode_put_attrib(x, "to", alias); | |
726 xmlnode_put_attrib(x, "id", "Agent info"); | |
727 jab_send(conn, x); | |
728 xmlnode_free(x); | |
729 } | |
730 | |
731 if (xmlnode_get_tag(y, "register")) { | |
732 x = jutil_iqnew (JPACKET__GET, NS_REGISTER); | |
733 xmlnode_put_attrib(x, "to", alias); | |
734 xmlnode_put_attrib(x, "id", "Agent info"); | |
735 jab_send(conn, x); | |
736 xmlnode_free(x); | |
737 } | |
738 } | |
739 } | |
740 } | |
741 | |
37 | 742 /* |
31 | 743 if (find(jhook.agents.begin(), jhook.agents.end(), DEFAULT_CONFSERV) == jhook.agents.end()) |
744 jhook.agents.insert(jhook.agents.begin(), agent(DEFAULT_CONFSERV, DEFAULT_CONFSERV, | |
745 _("Default Jabber conference server"), agent::atGroupchat)); | |
746 | |
747 */ | |
748 } else if (!strcmp(ns, NS_SEARCH) || !strcmp(ns, NS_REGISTER)) { | |
749 p = xmlnode_get_attrib(packet->x, "id"); id = p ? p : (char*)""; | |
750 | |
751 if (!strcmp(id, "Agent info")) { | |
752 // jhook.gotagentinfo(packet->x); TODO | |
753 scr_LogPrint("Got agent info"); | |
754 } else if (!strcmp(id, "Lookup")) { | |
755 // jhook.gotsearchresults(packet->x); TODO | |
756 scr_LogPrint("Got search results"); | |
757 } else if (!strcmp(id, "Register")) { | |
758 x = jutil_iqnew(JPACKET__GET, NS_REGISTER); | |
759 xmlnode_put_attrib(x, "to", from); | |
760 xmlnode_put_attrib(x, "id", "Agent info"); | |
761 jab_send(conn, x); | |
762 xmlnode_free(x); | |
763 } | |
764 | |
765 } | |
766 } | |
767 } else if (!strcmp(type, "set")) { | |
768 } else if (!strcmp(type, "error")) { | |
769 char *name=NULL, *desc=NULL; | |
52 | 770 int code = 0; |
31 | 771 |
772 x = xmlnode_get_tag(packet->x, "error"); | |
773 p = xmlnode_get_attrib(x, "code"); if (p) code = atoi(p); | |
774 p = xmlnode_get_attrib(x, "id"); if (p) name = p; | |
775 p = xmlnode_get_tag_data(packet->x, "error"); if (p) desc = p; | |
776 | |
231 | 777 #if 0 |
31 | 778 switch(code) { |
779 case 401: /* Unauthorized */ | |
780 case 302: /* Redirect */ | |
781 case 400: /* Bad request */ | |
782 case 402: /* Payment Required */ | |
783 case 403: /* Forbidden */ | |
784 case 404: /* Not Found */ | |
785 case 405: /* Not Allowed */ | |
786 case 406: /* Not Acceptable */ | |
787 case 407: /* Registration Required */ | |
788 case 408: /* Request Timeout */ | |
789 case 409: /* Conflict */ | |
790 case 500: /* Internal Server Error */ | |
791 case 501: /* Not Implemented */ | |
792 case 502: /* Remote Server Error */ | |
793 case 503: /* Service Unavailable */ | |
794 case 504: /* Remote Server Timeout */ | |
795 default: | |
796 /* | |
797 if (!regmode) { | |
798 face.log(desc.empty() ? | |
799 _("+ [jab] error %d") : | |
800 _("+ [jab] error %d: %s"), | |
801 code, desc.c_str()); | |
802 | |
803 if (!jhook.flogged && code != 501) { | |
804 close(jc->fd); | |
805 jc->fd = -1; | |
806 } | |
807 | |
808 } else { | |
809 jhook.regerr = desc; | |
810 | |
811 } | |
812 */ | |
813 } | |
231 | 814 #endif |
31 | 815 scr_LogPrint("Error code from server (%d)", code); |
816 | |
817 } | |
818 break; | |
819 | |
820 case JPACKET_PRESENCE: | |
821 x = xmlnode_get_tag(packet->x, "show"); | |
35 | 822 ust = available; |
31 | 823 |
824 if (x) { | |
825 p = xmlnode_get_data(x); if (p) ns = p; | |
826 | |
827 if (ns) { | |
35 | 828 if (!strcmp(ns, "away")) ust = away; |
829 else if (!strcmp(ns, "dnd")) ust = dontdisturb; | |
830 else if (!strcmp(ns, "xa")) ust = notavail; | |
831 else if (!strcmp(ns, "chat")) ust = freeforchat; | |
31 | 832 } |
833 } | |
834 | |
35 | 835 if (type && !strcmp(type, "unavailable")) { |
836 ust = offline; | |
31 | 837 } |
838 | |
221 | 839 if ((x = xmlnode_get_tag(packet->x, "status")) != NULL) |
840 p = xmlnode_get_data(x); | |
841 else | |
842 p = NULL; | |
843 | |
91 | 844 r = jidtodisp(from); |
113 | 845 if (ust != roster_getstatus(r)) |
221 | 846 hk_statuschange(r, 0, ust, p); |
159 | 847 g_free(r); |
31 | 848 break; |
849 | |
850 case JPACKET_S10N: | |
205 | 851 scr_LogPrint("Received (un)subscription packet (type=%s)", |
852 ((type) ? type : "")); | |
31 | 853 |
43 | 854 if (!strcmp(type, "subscribe")) { |
91 | 855 int isagent; |
856 r = jidtodisp(from); | |
857 isagent = (roster_gettype(r) & ROSTER_TYPE_AGENT) != 0; | |
159 | 858 g_free(r); |
91 | 859 scr_LogPrint("isagent=%d", isagent); // XXX DBG |
860 if (!isagent) { | |
43 | 861 scr_LogPrint("<%s> wants to subscribe " |
862 "to your network presence updates", from); | |
125 | 863 // FIXME we accept everybody... |
864 x = jutil_presnew(JPACKET__SUBSCRIBED, from, 0); | |
865 jab_send(jc, x); | |
866 xmlnode_free(x); | |
91 | 867 } else { |
868 x = jutil_presnew(JPACKET__SUBSCRIBED, from, 0); | |
31 | 869 jab_send(jc, x); |
870 xmlnode_free(x); | |
91 | 871 } |
43 | 872 } else if (!strcmp(type, "unsubscribe")) { |
873 x = jutil_presnew(JPACKET__UNSUBSCRIBED, from, 0); | |
31 | 874 jab_send(jc, x); |
875 xmlnode_free(x); | |
43 | 876 scr_LogPrint("<%s> has unsubscribed to your presence updates", from); |
31 | 877 } |
878 break; | |
879 | |
880 default: | |
881 break; | |
882 } | |
883 } | |
884 |