Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/jabglue.c @ 772:464be13343a9
Store most data in UTF-8 internally
Only chat buffer data is still using 1 byte for char size.
User input still doesn't handle UTF-8 locales.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sat, 25 Mar 2006 18:10:36 +0100 |
parents | 12dc6bdff8c1 |
children | 46304b773a44 |
comparison
equal
deleted
inserted
replaced
771:ce4f8a2129a4 | 772:464be13343a9 |
---|---|
94 } | 94 } |
95 | 95 |
96 jconn jb_connect(const char *jid, const char *server, unsigned int port, | 96 jconn jb_connect(const char *jid, const char *server, unsigned int port, |
97 int ssl, const char *pass) | 97 int ssl, const char *pass) |
98 { | 98 { |
99 char *utf8_jid; | |
100 if (!port) { | 99 if (!port) { |
101 if (ssl) | 100 if (ssl) |
102 port = JABBERSSLPORT; | 101 port = JABBERSSLPORT; |
103 else | 102 else |
104 port = JABBERPORT; | 103 port = JABBERPORT; |
105 } | 104 } |
106 | 105 |
107 jb_disconnect(); | 106 jb_disconnect(); |
108 | 107 |
109 utf8_jid = to_utf8(jid); | 108 if (!jid) return jc; |
110 if (!utf8_jid) return jc; | 109 |
111 | 110 jc = jab_new((char*)jid, (char*)pass, (char*)server, port, ssl); |
112 jc = jab_new(utf8_jid, (char*)pass, (char*)server, port, ssl); | |
113 g_free(utf8_jid); | |
114 | 111 |
115 /* These 3 functions can deal with a NULL jc, no worry... */ | 112 /* These 3 functions can deal with a NULL jc, no worry... */ |
116 jab_logger(jc, logger); | 113 jab_logger(jc, logger); |
117 jab_packet_handler(jc, &packethandler); | 114 jab_packet_handler(jc, &packethandler); |
118 jab_state_handler(jc, &statehandler); | 115 jab_state_handler(jc, &statehandler); |
266 static xmlnode presnew(enum imstatus st, const char *recipient, | 263 static xmlnode presnew(enum imstatus st, const char *recipient, |
267 const char *msg) | 264 const char *msg) |
268 { | 265 { |
269 unsigned int prio; | 266 unsigned int prio; |
270 xmlnode x; | 267 xmlnode x; |
271 gchar *utf8_recipient = to_utf8(recipient); | |
272 | 268 |
273 x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); | 269 x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); |
274 | 270 |
275 if (utf8_recipient) { | 271 if (recipient) { |
276 xmlnode_put_attrib(x, "to", utf8_recipient); | 272 xmlnode_put_attrib(x, "to", recipient); |
277 g_free(utf8_recipient); | |
278 } | 273 } |
279 | 274 |
280 switch(st) { | 275 switch(st) { |
281 case away: | 276 case away: |
282 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "away", | 277 xmlnode_insert_cdata(xmlnode_insert_tag(x, "show"), "away", |
316 snprintf(strprio, 8, "%u", prio); | 311 snprintf(strprio, 8, "%u", prio); |
317 xmlnode_insert_cdata(xmlnode_insert_tag(x, "priority"), | 312 xmlnode_insert_cdata(xmlnode_insert_tag(x, "priority"), |
318 strprio, (unsigned) -1); | 313 strprio, (unsigned) -1); |
319 } | 314 } |
320 | 315 |
321 if (msg) { | 316 if (msg) |
322 gchar *utf8_msg = to_utf8(msg); | 317 xmlnode_insert_cdata(xmlnode_insert_tag(x, "status"), msg, (unsigned) -1); |
323 xmlnode_insert_cdata(xmlnode_insert_tag(x, "status"), utf8_msg, | |
324 (unsigned) -1); | |
325 g_free(utf8_msg); | |
326 } | |
327 | 318 |
328 return x; | 319 return x; |
329 } | 320 } |
330 | 321 |
331 void jb_setstatus(enum imstatus st, const char *recipient, const char *msg) | 322 void jb_setstatus(enum imstatus st, const char *recipient, const char *msg) |
391 void jb_send_msg(const char *jid, const char *text, int type, | 382 void jb_send_msg(const char *jid, const char *text, int type, |
392 const char *subject) | 383 const char *subject) |
393 { | 384 { |
394 xmlnode x; | 385 xmlnode x; |
395 gchar *strtype; | 386 gchar *strtype; |
396 gchar *utf8_jid; | |
397 gchar *buffer; | |
398 | 387 |
399 if (!online) return; | 388 if (!online) return; |
400 | 389 |
401 if (type == ROSTER_TYPE_ROOM) | 390 if (type == ROSTER_TYPE_ROOM) |
402 strtype = TMSG_GROUPCHAT; | 391 strtype = TMSG_GROUPCHAT; |
403 else | 392 else |
404 strtype = TMSG_CHAT; | 393 strtype = TMSG_CHAT; |
405 | 394 |
406 buffer = to_utf8(text); | 395 x = jutil_msgnew(strtype, (char*)jid, NULL, (char*)text); |
407 utf8_jid = to_utf8(jid); // Resource can require UTF-8 | |
408 | |
409 x = jutil_msgnew(strtype, utf8_jid, NULL, (char*)buffer); | |
410 if (subject) { | 396 if (subject) { |
411 xmlnode y; | 397 xmlnode y; |
412 char *bs = to_utf8(subject); | |
413 y = xmlnode_insert_tag(x, "subject"); | 398 y = xmlnode_insert_tag(x, "subject"); |
414 xmlnode_insert_cdata(y, bs, (unsigned) -1); | 399 xmlnode_insert_cdata(y, subject, (unsigned) -1); |
415 if (bs) g_free(bs); | |
416 } | 400 } |
417 jab_send(jc, x); | 401 jab_send(jc, x); |
418 xmlnode_free(x); | 402 xmlnode_free(x); |
419 | |
420 if (buffer) g_free(buffer); | |
421 if (utf8_jid) g_free(utf8_jid); | |
422 | 403 |
423 jb_reset_keepalive(); | 404 jb_reset_keepalive(); |
424 } | 405 } |
425 | 406 |
426 // jb_subscr_send_auth(jid) | 407 // jb_subscr_send_auth(jid) |
427 // Allow jid to receive our presence updates | 408 // Allow jid to receive our presence updates |
428 void jb_subscr_send_auth(const char *jid) | 409 void jb_subscr_send_auth(const char *jid) |
429 { | 410 { |
430 xmlnode x; | 411 xmlnode x; |
431 char *utf8_jid = to_utf8(jid); | 412 |
432 | 413 x = jutil_presnew(JPACKET__SUBSCRIBED, (char *)jid, NULL); |
433 x = jutil_presnew(JPACKET__SUBSCRIBED, utf8_jid, NULL); | |
434 jab_send(jc, x); | 414 jab_send(jc, x); |
435 xmlnode_free(x); | 415 xmlnode_free(x); |
436 g_free(utf8_jid); | |
437 } | 416 } |
438 | 417 |
439 // jb_subscr_cancel_auth(jid) | 418 // jb_subscr_cancel_auth(jid) |
440 // Cancel jid's subscription to our presence updates | 419 // Cancel jid's subscription to our presence updates |
441 void jb_subscr_cancel_auth(const char *jid) | 420 void jb_subscr_cancel_auth(const char *jid) |
442 { | 421 { |
443 xmlnode x; | 422 xmlnode x; |
444 char *utf8_jid = to_utf8(jid); | 423 |
445 | 424 x = jutil_presnew(JPACKET__UNSUBSCRIBED, (char *)jid, NULL); |
446 x = jutil_presnew(JPACKET__UNSUBSCRIBED, utf8_jid, NULL); | |
447 jab_send(jc, x); | 425 jab_send(jc, x); |
448 xmlnode_free(x); | 426 xmlnode_free(x); |
449 g_free(utf8_jid); | |
450 } | 427 } |
451 | 428 |
452 // jb_subscr_request_auth(jid) | 429 // jb_subscr_request_auth(jid) |
453 // Request a subscription to jid's presence updates | 430 // Request a subscription to jid's presence updates |
454 void jb_subscr_request_auth(const char *jid) | 431 void jb_subscr_request_auth(const char *jid) |
455 { | 432 { |
456 xmlnode x; | 433 xmlnode x; |
457 char *utf8_jid = to_utf8(jid); | 434 |
458 | 435 x = jutil_presnew(JPACKET__SUBSCRIBE, (char *)jid, NULL); |
459 x = jutil_presnew(JPACKET__SUBSCRIBE, utf8_jid, NULL); | |
460 jab_send(jc, x); | 436 jab_send(jc, x); |
461 xmlnode_free(x); | 437 xmlnode_free(x); |
462 g_free(utf8_jid); | |
463 } | 438 } |
464 | 439 |
465 // Note: the caller should check the jid is correct | 440 // Note: the caller should check the jid is correct |
466 void jb_addbuddy(const char *jid, const char *name, const char *group) | 441 void jb_addbuddy(const char *jid, const char *name, const char *group) |
467 { | 442 { |
479 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); | 454 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
480 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); | 455 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); |
481 | 456 |
482 xmlnode_put_attrib(y, "jid", cleanjid); | 457 xmlnode_put_attrib(y, "jid", cleanjid); |
483 | 458 |
484 if (name) { | 459 if (name) |
485 gchar *name_utf8 = to_utf8(name); | 460 xmlnode_put_attrib(y, "name", name); |
486 xmlnode_put_attrib(y, "name", name_utf8); | |
487 g_free(name_utf8); | |
488 } | |
489 | 461 |
490 if (group) { | 462 if (group) { |
491 char *group_utf8 = to_utf8(group); | |
492 z = xmlnode_insert_tag(y, "group"); | 463 z = xmlnode_insert_tag(y, "group"); |
493 xmlnode_insert_cdata(z, group_utf8, (unsigned) -1); | 464 xmlnode_insert_cdata(z, group, (unsigned) -1); |
494 g_free(group_utf8); | |
495 } | 465 } |
496 | 466 |
497 jab_send(jc, iqn->xmldata); | 467 jab_send(jc, iqn->xmldata); |
498 iqs_del(iqn->id); // XXX | 468 iqs_del(iqn->id); // XXX |
499 | 469 |
555 void jb_updatebuddy(const char *jid, const char *name, const char *group) | 525 void jb_updatebuddy(const char *jid, const char *name, const char *group) |
556 { | 526 { |
557 xmlnode y; | 527 xmlnode y; |
558 eviqs *iqn; | 528 eviqs *iqn; |
559 char *cleanjid; | 529 char *cleanjid; |
560 gchar *name_utf8; | |
561 | 530 |
562 if (!online) return; | 531 if (!online) return; |
563 | 532 |
564 // XXX We should check name's and group's correctness | 533 // XXX We should check name's and group's correctness |
565 | 534 |
566 cleanjid = jidtodisp(jid); | 535 cleanjid = jidtodisp(jid); |
567 name_utf8 = to_utf8(name); | |
568 | 536 |
569 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); | 537 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
570 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); | 538 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); |
571 xmlnode_put_attrib(y, "jid", cleanjid); | 539 xmlnode_put_attrib(y, "jid", cleanjid); |
572 xmlnode_put_attrib(y, "name", name_utf8); | 540 xmlnode_put_attrib(y, "name", name); |
573 | 541 |
574 if (group) { | 542 if (group) { |
575 gchar *group_utf8 = to_utf8(group); | |
576 y = xmlnode_insert_tag(y, "group"); | 543 y = xmlnode_insert_tag(y, "group"); |
577 xmlnode_insert_cdata(y, group_utf8, (unsigned) -1); | 544 xmlnode_insert_cdata(y, group, (unsigned) -1); |
578 g_free(group_utf8); | |
579 } | 545 } |
580 | 546 |
581 jab_send(jc, iqn->xmldata); | 547 jab_send(jc, iqn->xmldata); |
582 iqs_del(iqn->id); // XXX | 548 iqs_del(iqn->id); // XXX |
583 g_free(name_utf8); | |
584 g_free(cleanjid); | 549 g_free(cleanjid); |
585 } | 550 } |
586 | 551 |
587 void jb_request(const char *jid, enum iqreq_type reqtype) | 552 void jb_request(const char *jid, enum iqreq_type reqtype) |
588 { | 553 { |
709 | 674 |
710 if (venue && *venue) | 675 if (venue && *venue) |
711 xmlnode_put_attrib(z, "jid", venue); | 676 xmlnode_put_attrib(z, "jid", venue); |
712 | 677 |
713 if (reason) { | 678 if (reason) { |
714 gchar *utf8_reason = to_utf8(reason); | |
715 y = xmlnode_insert_tag(z, "reason"); | 679 y = xmlnode_insert_tag(z, "reason"); |
716 xmlnode_insert_cdata(y, utf8_reason, (unsigned) -1); | 680 xmlnode_insert_cdata(y, reason, (unsigned) -1); |
717 g_free(utf8_reason); | |
718 } | 681 } |
719 | 682 |
720 jab_send(jc, iqn->xmldata); | 683 jab_send(jc, iqn->xmldata); |
721 iqs_del(iqn->id); // XXX | 684 iqs_del(iqn->id); // XXX |
722 jb_reset_keepalive(); | 685 jb_reset_keepalive(); |
757 xmlnode_put_attrib(iqn->xmldata, "type", "set"); | 720 xmlnode_put_attrib(iqn->xmldata, "type", "set"); |
758 y = xmlnode_get_tag(iqn->xmldata, "query"); | 721 y = xmlnode_get_tag(iqn->xmldata, "query"); |
759 z = xmlnode_insert_tag(y, "item"); | 722 z = xmlnode_insert_tag(y, "item"); |
760 | 723 |
761 if (jid) { | 724 if (jid) { |
762 gchar *utf8_jid = to_utf8(jid); | 725 xmlnode_put_attrib(z, "jid", jid); |
763 xmlnode_put_attrib(z, "jid", utf8_jid); | 726 } else { // nickname |
764 if (utf8_jid) g_free(utf8_jid); | 727 xmlnode_put_attrib(z, "nick", nick); |
765 } else { // nick | |
766 gchar *utf8_nickname = to_utf8(nick); | |
767 xmlnode_put_attrib(z, "nick", utf8_nickname); | |
768 g_free(utf8_nickname); | |
769 } | 728 } |
770 | 729 |
771 if (ra.type == type_affil) | 730 if (ra.type == type_affil) |
772 xmlnode_put_attrib(z, "affiliation", straffil[ra.val.affil]); | 731 xmlnode_put_attrib(z, "affiliation", straffil[ra.val.affil]); |
773 else if (ra.type == type_role) | 732 else if (ra.type == type_role) |
774 xmlnode_put_attrib(z, "role", strrole[ra.val.role]); | 733 xmlnode_put_attrib(z, "role", strrole[ra.val.role]); |
775 | 734 |
776 if (reason) { | 735 if (reason) { |
777 gchar *utf8_reason = to_utf8(reason); | |
778 y = xmlnode_insert_tag(z, "reason"); | 736 y = xmlnode_insert_tag(z, "reason"); |
779 xmlnode_insert_cdata(y, utf8_reason, (unsigned) -1); | 737 xmlnode_insert_cdata(y, reason, (unsigned) -1); |
780 g_free(utf8_reason); | |
781 } | 738 } |
782 | 739 |
783 jab_send(jc, iqn->xmldata); | 740 jab_send(jc, iqn->xmldata); |
784 iqs_del(iqn->id); // XXX | 741 iqs_del(iqn->id); // XXX |
785 jb_reset_keepalive(); | 742 jb_reset_keepalive(); |
791 // room syntax: "room@server" | 748 // room syntax: "room@server" |
792 // reason can be null. | 749 // reason can be null. |
793 void jb_room_invite(const char *room, const char *jid, const char *reason) | 750 void jb_room_invite(const char *room, const char *jid, const char *reason) |
794 { | 751 { |
795 xmlnode x, y, z; | 752 xmlnode x, y, z; |
796 gchar *utf8_jid; | |
797 | 753 |
798 if (!online || !room || !jid) return; | 754 if (!online || !room || !jid) return; |
799 | 755 |
800 x = jutil_msgnew(NULL, (char*)room, NULL, NULL); | 756 x = jutil_msgnew(NULL, (char*)room, NULL, NULL); |
801 | 757 |
802 y = xmlnode_insert_tag(x, "x"); | 758 y = xmlnode_insert_tag(x, "x"); |
803 xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); | 759 xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); |
804 | 760 |
805 utf8_jid = to_utf8(jid); // Resource can require UTF-8 | |
806 z = xmlnode_insert_tag(y, "invite"); | 761 z = xmlnode_insert_tag(y, "invite"); |
807 xmlnode_put_attrib(z, "to", utf8_jid); | 762 xmlnode_put_attrib(z, "to", jid); |
808 if (utf8_jid) g_free(utf8_jid); | |
809 | 763 |
810 if (reason) { | 764 if (reason) { |
811 gchar *utf8_reason = to_utf8(reason); | |
812 y = xmlnode_insert_tag(z, "reason"); | 765 y = xmlnode_insert_tag(z, "reason"); |
813 xmlnode_insert_cdata(y, utf8_reason, (unsigned) -1); | 766 xmlnode_insert_cdata(y, reason, (unsigned) -1); |
814 g_free(utf8_reason); | |
815 } | 767 } |
816 | 768 |
817 jab_send(jc, x); | 769 jab_send(jc, x); |
818 xmlnode_free(x); | 770 xmlnode_free(x); |
819 jb_reset_keepalive(); | 771 jb_reset_keepalive(); |
822 static void gotmessage(char *type, const char *from, const char *body, | 774 static void gotmessage(char *type, const char *from, const char *body, |
823 const char *enc, time_t timestamp) | 775 const char *enc, time_t timestamp) |
824 { | 776 { |
825 char *jid; | 777 char *jid; |
826 const char *rname; | 778 const char *rname; |
827 gchar *buffer = from_utf8(body); | |
828 | 779 |
829 jid = jidtodisp(from); | 780 jid = jidtodisp(from); |
830 | |
831 if (!buffer && body) { | |
832 scr_LogPrint(LPRINT_NORMAL, "Decoding of message from <%s> has failed", | |
833 from); | |
834 scr_LogPrint(LPRINT_LOG, "Decoding of message from <%s> has failed: %s", | |
835 from, body); | |
836 scr_WriteIncomingMessage(jid, "Cannot display message: " | |
837 "UTF-8 conversion failure", | |
838 0, HBB_PREFIX_ERR | HBB_PREFIX_IN); | |
839 g_free(jid); | |
840 return; | |
841 } | |
842 | 781 |
843 rname = strchr(from, '/'); | 782 rname = strchr(from, '/'); |
844 if (rname) rname++; | 783 if (rname) rname++; |
845 hk_message_in(jid, rname, timestamp, buffer, type); | 784 hk_message_in(jid, rname, timestamp, body, type); |
846 g_free(jid); | 785 g_free(jid); |
847 g_free(buffer); | |
848 } | 786 } |
849 | 787 |
850 static const char *defaulterrormsg(int code) | 788 static const char *defaulterrormsg(int code) |
851 { | 789 { |
852 const char *desc; | 790 const char *desc; |
922 s = xmlnode_get_data(x); | 860 s = xmlnode_get_data(x); |
923 if (s && *s) desc = s; | 861 if (s && *s) desc = s; |
924 | 862 |
925 // And sometimes there is a text message | 863 // And sometimes there is a text message |
926 s = xmlnode_get_tag_data(x, "text"); | 864 s = xmlnode_get_tag_data(x, "text"); |
927 if (s && *s) desc = s; // FIXME utf8?? | 865 if (s && *s) desc = s; |
928 | 866 |
929 scr_LogPrint(LPRINT_LOGNORM, "Error code from server: %d %s", code, desc); | 867 scr_LogPrint(LPRINT_LOGNORM, "Error code from server: %d %s", code, desc); |
930 } | 868 } |
931 | 869 |
932 static void statehandler(jconn conn, int state) | 870 static void statehandler(jconn conn, int state) |
1075 } | 1013 } |
1076 | 1014 |
1077 // Check for nickname change | 1015 // Check for nickname change |
1078 if (statuscode == 303 && mbnick) { | 1016 if (statuscode == 303 && mbnick) { |
1079 gchar *mbuf; | 1017 gchar *mbuf; |
1080 gchar *newname_noutf8 = from_utf8(mbnick); | 1018 mbuf = g_strdup_printf("%s is now known as %s", rname, mbnick); |
1081 if (!newname_noutf8) | |
1082 scr_LogPrint(LPRINT_LOG, "Decoding of new nickname has failed: %s", | |
1083 mbnick); | |
1084 mbuf = g_strdup_printf("%s is now known as %s", rname, | |
1085 (newname_noutf8 ? newname_noutf8 : "(?)")); | |
1086 scr_WriteIncomingMessage(roomjid, mbuf, usttime, | 1019 scr_WriteIncomingMessage(roomjid, mbuf, usttime, |
1087 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); | 1020 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); |
1088 if (log_muc_conf) hlog_write_message(roomjid, 0, FALSE, mbuf); | 1021 if (log_muc_conf) hlog_write_message(roomjid, 0, FALSE, mbuf); |
1089 g_free(mbuf); | 1022 g_free(mbuf); |
1090 if (newname_noutf8) { | 1023 buddy_resource_setname(room_elt->data, rname, mbnick); |
1091 buddy_resource_setname(room_elt->data, rname, newname_noutf8); | 1024 // Maybe it's _our_ nickname... |
1092 m = buddy_getnickname(room_elt->data); | 1025 m = buddy_getnickname(room_elt->data); |
1093 if (m && !strcmp(rname, m)) | 1026 if (m && !strcmp(rname, m)) |
1094 buddy_setnickname(room_elt->data, newname_noutf8); | 1027 buddy_setnickname(room_elt->data, mbnick); |
1095 g_free(newname_noutf8); | |
1096 } | |
1097 } | 1028 } |
1098 | 1029 |
1099 // Check for departure/arrival | 1030 // Check for departure/arrival |
1100 if (!mbnick && mbrole == role_none) { | 1031 if (!mbnick && mbrole == role_none) { |
1101 gchar *mbuf; | 1032 gchar *mbuf; |
1123 // The message depends on _who_ left, and _how_ | 1054 // The message depends on _who_ left, and _how_ |
1124 if (how) { | 1055 if (how) { |
1125 gchar *mbuf_end; | 1056 gchar *mbuf_end; |
1126 // Forced leave | 1057 // Forced leave |
1127 if (actorjid) { | 1058 if (actorjid) { |
1128 gchar *rsn_noutf8 = from_utf8(reason); | |
1129 if (!rsn_noutf8 && reason) { | |
1130 scr_LogPrint(LPRINT_NORMAL, "UTF-8 decoding of reason has failed"); | |
1131 scr_LogPrint(LPRINT_LOG, "UTF-8 decoding of reason has failed: %s", | |
1132 reason); | |
1133 } | |
1134 mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s", | 1059 mbuf_end = g_strdup_printf("%s from %s by <%s>.\nReason: %s", |
1135 (how == ban ? "banned" : "kicked"), | 1060 (how == ban ? "banned" : "kicked"), |
1136 roomjid, actorjid, | 1061 roomjid, actorjid, reason); |
1137 (rsn_noutf8 ? rsn_noutf8 : "None given")); | |
1138 if (rsn_noutf8) | |
1139 g_free(rsn_noutf8); | |
1140 } else { | 1062 } else { |
1141 mbuf_end = g_strdup_printf("%s from %s.", | 1063 mbuf_end = g_strdup_printf("%s from %s.", |
1142 (how == ban ? "banned" : "kicked"), | 1064 (how == ban ? "banned" : "kicked"), |
1143 roomjid); | 1065 roomjid); |
1144 } | 1066 } |
1151 } else { | 1073 } else { |
1152 // Natural leave | 1074 // Natural leave |
1153 if (we_left) { | 1075 if (we_left) { |
1154 xmlnode destroynode = xmlnode_get_tag(xmldata, "destroy"); | 1076 xmlnode destroynode = xmlnode_get_tag(xmldata, "destroy"); |
1155 if (destroynode) { | 1077 if (destroynode) { |
1156 gchar *rsn_noutf8 = NULL; | 1078 if ((reason = xmlnode_get_tag_data(destroynode, "reason"))) { |
1157 if ((reason = xmlnode_get_tag_data(destroynode, "reason"))) | |
1158 rsn_noutf8 = from_utf8(reason); | |
1159 if (rsn_noutf8) { | |
1160 mbuf = g_strdup_printf("You have left %s, " | 1079 mbuf = g_strdup_printf("You have left %s, " |
1161 "the room has been destroyed: %s", | 1080 "the room has been destroyed: %s", |
1162 roomjid, rsn_noutf8); | 1081 roomjid, reason); |
1163 g_free(rsn_noutf8); | |
1164 } else { | 1082 } else { |
1165 mbuf = g_strdup_printf("You have left %s, " | 1083 mbuf = g_strdup_printf("You have left %s, " |
1166 "the room has been destroyed", roomjid); | 1084 "the room has been destroyed", roomjid); |
1167 } | 1085 } |
1168 } else { | 1086 } else { |
1194 | 1112 |
1195 if (!ournick) { | 1113 if (!ournick) { |
1196 // I think it shouldn't happen, but let's put a warning for a while... | 1114 // I think it shouldn't happen, but let's put a warning for a while... |
1197 mbuf = g_strdup_printf("MUC ERR: you have no nickname, " | 1115 mbuf = g_strdup_printf("MUC ERR: you have no nickname, " |
1198 "please send a bug report!"); | 1116 "please send a bug report!"); |
1199 scr_LogPrint(LPRINT_LOGNORM, mbuf); | 1117 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); |
1200 scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO); | 1118 scr_WriteIncomingMessage(roomjid, mbuf, 0, HBB_PREFIX_INFO); |
1201 g_free(mbuf); | 1119 g_free(mbuf); |
1202 buddylist_build(); | 1120 buddylist_build(); |
1203 scr_DrawRoster(); | 1121 scr_DrawRoster(); |
1204 return; | 1122 return; |
1243 } | 1161 } |
1244 } | 1162 } |
1245 | 1163 |
1246 // Update room member status | 1164 // Update room member status |
1247 if (rname) { | 1165 if (rname) { |
1248 gchar *mbrjid_noutf8 = from_utf8(mbjid); | |
1249 roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime, | 1166 roster_setstatus(roomjid, rname, bpprio, ust, ustmsg, usttime, |
1250 mbrole, mbaffil, mbrjid_noutf8); | 1167 mbrole, mbaffil, mbjid); |
1251 if (mbrjid_noutf8) | |
1252 g_free(mbrjid_noutf8); | |
1253 } else | 1168 } else |
1254 scr_LogPrint(LPRINT_LOGNORM, "MUC DBG: no rname!"); /* DBG */ | 1169 scr_LogPrint(LPRINT_LOGNORM, "MUC DBG: no rname!"); /* DBG */ |
1255 | 1170 |
1256 buddylist_build(); | 1171 buddylist_build(); |
1257 scr_DrawRoster(); | 1172 scr_DrawRoster(); |
1312 } | 1227 } |
1313 | 1228 |
1314 if (type && !strcmp(type, "unavailable")) | 1229 if (type && !strcmp(type, "unavailable")) |
1315 ust = offline; | 1230 ust = offline; |
1316 | 1231 |
1317 ustmsg = NULL; | 1232 ustmsg = xmlnode_get_tag_data(xmldata, "status"); |
1318 p = xmlnode_get_tag_data(xmldata, "status"); | |
1319 if (p) { | |
1320 ustmsg = from_utf8(p); | |
1321 if (!ustmsg) | |
1322 scr_LogPrint(LPRINT_LOG, | |
1323 "Decoding of status message of <%s> has failed: %s", | |
1324 from, p); | |
1325 } | |
1326 | 1233 |
1327 // Timestamp? | 1234 // Timestamp? |
1328 timestamp = xml_get_timestamp(xmldata); | 1235 timestamp = xml_get_timestamp(xmldata); |
1329 | 1236 |
1330 if (muc_packet) { | 1237 if (muc_packet) { |
1340 (!ustmsg && m && m[0]) || (ustmsg && (!m || strcmp(ustmsg, m)))) | 1247 (!ustmsg && m && m[0]) || (ustmsg && (!m || strcmp(ustmsg, m)))) |
1341 hk_statuschange(r, rname, bpprio, timestamp, ust, ustmsg); | 1248 hk_statuschange(r, rname, bpprio, timestamp, ust, ustmsg); |
1342 } | 1249 } |
1343 | 1250 |
1344 g_free(r); | 1251 g_free(r); |
1345 if (ustmsg) g_free(ustmsg); | |
1346 } | 1252 } |
1347 | 1253 |
1348 static void handle_packet_message(jconn conn, char *type, char *from, | 1254 static void handle_packet_message(jconn conn, char *type, char *from, |
1349 xmlnode xmldata) | 1255 xmlnode xmldata) |
1350 { | 1256 { |
1360 p = xmlnode_get_tag_data(xmldata, "subject"); | 1266 p = xmlnode_get_tag_data(xmldata, "subject"); |
1361 if (p != NULL) { | 1267 if (p != NULL) { |
1362 if (type && !strcmp(type, TMSG_GROUPCHAT)) { // Room topic | 1268 if (type && !strcmp(type, TMSG_GROUPCHAT)) { // Room topic |
1363 GSList *roombuddy; | 1269 GSList *roombuddy; |
1364 gchar *mbuf; | 1270 gchar *mbuf; |
1365 gchar *subj_noutf8 = from_utf8(p); | 1271 gchar *subj = p; |
1366 if (!subj_noutf8) | |
1367 scr_LogPrint(LPRINT_LOG, | |
1368 "Decoding of room topic has failed: %s", p); | |
1369 // Get the room (s) and the nickname (r) | 1272 // Get the room (s) and the nickname (r) |
1370 s = g_strdup(from); | 1273 s = g_strdup(from); |
1371 r = strchr(s, '/'); | 1274 r = strchr(s, '/'); |
1372 if (r) *r++ = 0; | 1275 if (r) *r++ = 0; |
1373 else r = s; | 1276 else r = s; |
1374 // Set the new topic | 1277 // Set the new topic |
1375 roombuddy = roster_find(s, jidsearch, 0); | 1278 roombuddy = roster_find(s, jidsearch, 0); |
1376 if (roombuddy) | 1279 if (roombuddy) |
1377 buddy_settopic(roombuddy->data, subj_noutf8); | 1280 buddy_settopic(roombuddy->data, subj); |
1378 // Display inside the room window | 1281 // Display inside the room window |
1379 if (r == s) { | 1282 if (r == s) { |
1380 // No specific resource (this is certainly history) | 1283 // No specific resource (this is certainly history) |
1381 mbuf = g_strdup_printf("The topic has been set to: %s", | 1284 mbuf = g_strdup_printf("The topic has been set to: %s", subj); |
1382 (subj_noutf8 ? subj_noutf8 : "(?)")); | |
1383 } else { | 1285 } else { |
1384 mbuf = g_strdup_printf("%s has set the topic to: %s", r, | 1286 mbuf = g_strdup_printf("%s has set the topic to: %s", r, subj); |
1385 (subj_noutf8 ? subj_noutf8 : "(?)")); | |
1386 } | 1287 } |
1387 scr_WriteIncomingMessage(s, mbuf, 0, | 1288 scr_WriteIncomingMessage(s, mbuf, 0, |
1388 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); | 1289 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); |
1389 if (settings_opt_get_int("log_muc_conf")) | 1290 if (settings_opt_get_int("log_muc_conf")) |
1390 hlog_write_message(s, 0, FALSE, mbuf); | 1291 hlog_write_message(s, 0, FALSE, mbuf); |
1391 if (subj_noutf8) g_free(subj_noutf8); | |
1392 g_free(s); | 1292 g_free(s); |
1393 g_free(mbuf); | 1293 g_free(mbuf); |
1394 // The topic is displayed in the chat status line, so refresh now. | 1294 // The topic is displayed in the chat status line, so refresh now. |
1395 scr_UpdateChatStatus(TRUE); | 1295 scr_UpdateChatStatus(TRUE); |
1396 } else { // Chat message | 1296 } else { // Chat message |
1488 scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO); | 1388 scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO); |
1489 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); | 1389 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
1490 g_free(buf); | 1390 g_free(buf); |
1491 | 1391 |
1492 if (msg) { | 1392 if (msg) { |
1493 char *msg_noutf8 = from_utf8(msg); | 1393 buf = g_strdup_printf("<%s> said: %s", from, msg); |
1494 if (msg_noutf8) { | 1394 scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO); |
1495 buf = g_strdup_printf("<%s> said: %s", from, msg_noutf8); | 1395 replace_nl_with_dots(buf); |
1496 scr_WriteIncomingMessage(r, buf, 0, HBB_PREFIX_INFO); | 1396 scr_LogPrint(LPRINT_LOGNORM, "%s", buf); |
1497 replace_nl_with_dots(buf); | 1397 g_free(buf); |
1498 scr_LogPrint(LPRINT_LOGNORM, buf); | |
1499 g_free(buf); | |
1500 g_free(msg_noutf8); | |
1501 } | |
1502 } | 1398 } |
1503 | 1399 |
1504 // Create a new event item | 1400 // Create a new event item |
1505 evn = evs_new(EVS_TYPE_SUBSCRIPTION, EVS_MAX_TIMEOUT); | 1401 evn = evs_new(EVS_TYPE_SUBSCRIPTION, EVS_MAX_TIMEOUT); |
1506 if (evn) { | 1402 if (evn) { |
1546 g_free(r); | 1442 g_free(r); |
1547 } | 1443 } |
1548 | 1444 |
1549 static void packethandler(jconn conn, jpacket packet) | 1445 static void packethandler(jconn conn, jpacket packet) |
1550 { | 1446 { |
1551 char *p, *r, *s; | 1447 char *p; |
1448 /* | |
1449 char *r, *s; | |
1552 const char *m; | 1450 const char *m; |
1451 */ | |
1553 char *from=NULL, *type=NULL; | 1452 char *from=NULL, *type=NULL; |
1554 | 1453 |
1555 jb_reset_keepalive(); // reset keepalive timeout | 1454 jb_reset_keepalive(); // reset keepalive timeout |
1556 jpacket_reset(packet); | 1455 jpacket_reset(packet); |
1557 | 1456 |
1562 | 1461 |
1563 p = xmlnode_get_attrib(packet->x, "type"); | 1462 p = xmlnode_get_attrib(packet->x, "type"); |
1564 if (p) type = p; | 1463 if (p) type = p; |
1565 | 1464 |
1566 p = xmlnode_get_attrib(packet->x, "from"); | 1465 p = xmlnode_get_attrib(packet->x, "from"); |
1567 if (p) { // Convert from UTF8 | 1466 if (p) from = p; |
1568 // We need to be careful because from_utf8() can fail on some chars | |
1569 // Thus we only convert the resource part | |
1570 from = g_new0(char, strlen(p)+1); | |
1571 strcpy(from, p); | |
1572 r = strchr(from, '/'); | |
1573 m = strchr(p, '/'); | |
1574 if (m++) { | |
1575 s = from_utf8(m); | |
1576 if (s) { | |
1577 // In some cases the allocated memory size could be too small because | |
1578 // when chars cannot be converted strings like "\uxxxx" or "\Uxxxxyyyy" | |
1579 // are used. | |
1580 if (strlen(r+1) < strlen(s)) { | |
1581 from = g_realloc(from, 1+m-p+strlen(s)); | |
1582 r = strchr(from, '/'); | |
1583 } | |
1584 strcpy(r+1, s); | |
1585 g_free(s); | |
1586 } else { | |
1587 *(r+1) = 0; | |
1588 scr_LogPrint(LPRINT_NORMAL, "Decoding of message sender has failed"); | |
1589 scr_LogPrint(LPRINT_LOG, "Decoding of message sender has failed: %s", | |
1590 m); | |
1591 } | |
1592 } | |
1593 } | |
1594 | 1467 |
1595 if (!from && packet->type != JPACKET_IQ) { | 1468 if (!from && packet->type != JPACKET_IQ) { |
1596 scr_LogPrint(LPRINT_LOGNORM, "Error in packet (could be UTF8-related)"); | 1469 scr_LogPrint(LPRINT_LOGNORM, "Error in packet (could be UTF8-related)"); |
1597 return; | 1470 return; |
1598 } | 1471 } |
1615 break; | 1488 break; |
1616 | 1489 |
1617 default: | 1490 default: |
1618 scr_LogPrint(LPRINT_LOG, "Unhandled packet type (%d)", packet->type); | 1491 scr_LogPrint(LPRINT_LOG, "Unhandled packet type (%d)", packet->type); |
1619 } | 1492 } |
1620 if (from) | |
1621 g_free(from); | |
1622 } | 1493 } |
1623 | 1494 |
1624 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ | 1495 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ |