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... */