64 } |
64 } |
65 |
65 |
66 // jidtodisp(jid) |
66 // jidtodisp(jid) |
67 // Strips the resource part from the jid |
67 // Strips the resource part from the jid |
68 // The caller should g_free the result after use. |
68 // The caller should g_free the result after use. |
69 char *jidtodisp(const char *jid) |
69 char *jidtodisp(const char *fjid) |
70 { |
70 { |
71 char *ptr; |
71 char *ptr; |
72 char *alias; |
72 char *alias; |
73 |
73 |
74 alias = g_strdup(jid); |
74 alias = g_strdup(fjid); |
75 |
75 |
76 if ((ptr = strchr(alias, JID_RESOURCE_SEPARATOR)) != NULL) { |
76 if ((ptr = strchr(alias, JID_RESOURCE_SEPARATOR)) != NULL) { |
77 *ptr = 0; |
77 *ptr = 0; |
78 } |
78 } |
79 return alias; |
79 return alias; |
80 } |
80 } |
81 |
81 |
82 char *compose_jid(const char *username, const char *servername, |
82 char *compose_jid(const char *username, const char *servername, |
83 const char *resource) |
83 const char *resource) |
84 { |
84 { |
85 char *jid = g_new(char, 3 + |
85 char *fjid = g_new(char, 3 + |
86 strlen(username) + strlen(servername) + strlen(resource)); |
86 strlen(username) + strlen(servername) + strlen(resource)); |
87 strcpy(jid, username); |
87 strcpy(fjid, username); |
88 if (!strchr(jid, JID_DOMAIN_SEPARATOR)) { |
88 if (!strchr(fjid, JID_DOMAIN_SEPARATOR)) { |
89 strcat(jid, JID_DOMAIN_SEPARATORSTR); |
89 strcat(fjid, JID_DOMAIN_SEPARATORSTR); |
90 strcat(jid, servername); |
90 strcat(fjid, servername); |
91 } |
91 } |
92 strcat(jid, JID_RESOURCE_SEPARATORSTR); |
92 strcat(fjid, JID_RESOURCE_SEPARATORSTR); |
93 strcat(jid, resource); |
93 strcat(fjid, resource); |
94 return jid; |
94 return fjid; |
95 } |
95 } |
96 |
96 |
97 inline unsigned char jb_getonline(void) |
97 inline unsigned char jb_getonline(void) |
98 { |
98 { |
99 return online; |
99 return online; |
100 } |
100 } |
101 |
101 |
102 jconn jb_connect(const char *jid, const char *server, unsigned int port, |
102 jconn jb_connect(const char *fjid, const char *server, unsigned int port, |
103 int ssl, const char *pass) |
103 int ssl, const char *pass) |
104 { |
104 { |
105 if (!port) { |
105 if (!port) { |
106 if (ssl) |
106 if (ssl) |
107 port = JABBERSSLPORT; |
107 port = JABBERSSLPORT; |
109 port = JABBERPORT; |
109 port = JABBERPORT; |
110 } |
110 } |
111 |
111 |
112 jb_disconnect(); |
112 jb_disconnect(); |
113 |
113 |
114 if (!jid) return jc; |
114 if (!fjid) return jc; |
115 |
115 |
116 jc = jab_new((char*)jid, (char*)pass, (char*)server, port, ssl); |
116 jc = jab_new((char*)fjid, (char*)pass, (char*)server, port, ssl); |
117 |
117 |
118 /* These 3 functions can deal with a NULL jc, no worry... */ |
118 /* These 3 functions can deal with a NULL jc, no worry... */ |
119 jab_logger(jc, logger); |
119 jab_logger(jc, logger); |
120 jab_packet_handler(jc, &packethandler); |
120 jab_packet_handler(jc, &packethandler); |
121 jab_state_handler(jc, &statehandler); |
121 jab_state_handler(jc, &statehandler); |
243 tv.tv_sec = LastPingTime + (time_t)KeepaliveDelay - now; |
243 tv.tv_sec = LastPingTime + (time_t)KeepaliveDelay - now; |
244 } |
244 } |
245 } |
245 } |
246 |
246 |
247 // Check auto-away timeout |
247 // Check auto-away timeout |
248 timeout = scr_GetAutoAwayTimeout(now); |
248 tmout = scr_GetAutoAwayTimeout(now); |
249 if (tv.tv_sec > timeout) { |
249 if (tv.tv_sec > tmout) { |
250 tv.tv_sec = timeout; |
250 tv.tv_sec = tmout; |
251 } |
251 } |
252 |
252 |
253 #if defined JEP0022 || defined JEP0085 |
253 #if defined JEP0022 || defined JEP0085 |
254 // Check composing timeout |
254 // Check composing timeout |
255 timeout = scr_GetChatStatesTimeout(now); |
255 tmout = scr_GetChatStatesTimeout(now); |
256 if (tv.tv_sec > timeout) { |
256 if (tv.tv_sec > tmout) { |
257 tv.tv_sec = timeout; |
257 tv.tv_sec = tmout; |
258 } |
258 } |
259 #endif |
259 #endif |
260 |
260 |
261 if (!tv.tv_sec) |
261 if (!tv.tv_sec) |
262 tv.tv_usec = 350000; |
262 tv.tv_usec = 350000; |
321 return mystatusmsg; |
321 return mystatusmsg; |
322 } |
322 } |
323 |
323 |
324 static void roompresence(gpointer room, void *presencedata) |
324 static void roompresence(gpointer room, void *presencedata) |
325 { |
325 { |
326 const char *jid; |
326 const char *bjid; |
327 const char *nickname; |
327 const char *nickname; |
328 char *to; |
328 char *to; |
329 struct T_presence *pres = presencedata; |
329 struct T_presence *pres = presencedata; |
330 |
330 |
331 if (!buddy_getinsideroom(room)) |
331 if (!buddy_getinsideroom(room)) |
332 return; |
332 return; |
333 |
333 |
334 jid = buddy_getjid(room); |
334 bjid = buddy_getjid(room); |
335 if (!jid) return; |
335 if (!bjid) return; |
336 nickname = buddy_getnickname(room); |
336 nickname = buddy_getnickname(room); |
337 if (!nickname) return; |
337 if (!nickname) return; |
338 |
338 |
339 to = g_strdup_printf("%s/%s", jid, nickname); |
339 to = g_strdup_printf("%s/%s", bjid, nickname); |
340 jb_setstatus(pres->st, to, pres->msg, TRUE); |
340 jb_setstatus(pres->st, to, pres->msg, TRUE); |
341 g_free(to); |
341 g_free(to); |
342 } |
342 } |
343 |
343 |
344 // presnew(status, recipient, message) |
344 // presnew(status, recipient, message) |
507 } |
507 } |
508 |
508 |
509 // jb_send_msg(jid, test, type, subject, msgid, *encrypted) |
509 // jb_send_msg(jid, test, type, subject, msgid, *encrypted) |
510 // When encrypted is not NULL, the function set *encrypted to TRUE if the |
510 // When encrypted is not NULL, the function set *encrypted to TRUE if the |
511 // message has been PGP-encrypted. |
511 // message has been PGP-encrypted. |
512 void jb_send_msg(const char *jid, const char *text, int type, |
512 void jb_send_msg(const char *fjid, const char *text, int type, |
513 const char *subject, const char *msgid, guint *encrypted) |
513 const char *subject, const char *msgid, guint *encrypted) |
514 { |
514 { |
515 xmlnode x; |
515 xmlnode x; |
516 gchar *strtype; |
516 gchar *strtype; |
517 #if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 |
517 #if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 |
534 strtype = TMSG_GROUPCHAT; |
534 strtype = TMSG_GROUPCHAT; |
535 else |
535 else |
536 strtype = TMSG_CHAT; |
536 strtype = TMSG_CHAT; |
537 |
537 |
538 #if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 |
538 #if defined HAVE_GPGME || defined JEP0022 || defined JEP0085 |
539 rname = strchr(jid, JID_RESOURCE_SEPARATOR); |
539 rname = strchr(fjid, JID_RESOURCE_SEPARATOR); |
540 barejid = jidtodisp(jid); |
540 barejid = jidtodisp(fjid); |
541 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
541 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
542 g_free(barejid); |
542 g_free(barejid); |
543 |
543 |
544 // If we can get a resource name, we use it. Else we use NULL, |
544 // If we can get a resource name, we use it. Else we use NULL, |
545 // which hopefully will give us the most likely resource. |
545 // which hopefully will give us the most likely resource. |
554 if (res_pgpdata && res_pgpdata->sign_keyid) |
554 if (res_pgpdata && res_pgpdata->sign_keyid) |
555 enc = gpg_encrypt(text, res_pgpdata->sign_keyid); |
555 enc = gpg_encrypt(text, res_pgpdata->sign_keyid); |
556 } |
556 } |
557 #endif |
557 #endif |
558 |
558 |
559 x = jutil_msgnew(strtype, (char*)jid, NULL, |
559 x = jutil_msgnew(strtype, (char*)fjid, NULL, |
560 (enc ? "This message is PGP-encrypted." : (char*)text)); |
560 (enc ? "This message is PGP-encrypted." : (char*)text)); |
561 if (subject) { |
561 if (subject) { |
562 xmlnode y; |
562 xmlnode y; |
563 y = xmlnode_insert_tag(x, "subject"); |
563 y = xmlnode_insert_tag(x, "subject"); |
564 xmlnode_insert_cdata(y, subject, (unsigned) -1); |
564 xmlnode_insert_cdata(y, subject, (unsigned) -1); |
642 |
642 |
643 |
643 |
644 #ifdef JEP0085 |
644 #ifdef JEP0085 |
645 // jb_send_jep85_chatstate() |
645 // jb_send_jep85_chatstate() |
646 // Send a JEP-85 chatstate. |
646 // Send a JEP-85 chatstate. |
647 static void jb_send_jep85_chatstate(const char *jid, guint state) |
647 static void jb_send_jep85_chatstate(const char *fjid, guint state) |
648 { |
648 { |
649 xmlnode x; |
649 xmlnode x; |
650 xmlnode event; |
650 xmlnode event; |
651 char *rname, *barejid; |
651 char *rname, *barejid; |
652 GSList *sl_buddy; |
652 GSList *sl_buddy; |
653 const char *chattag; |
653 const char *chattag; |
654 struct jep0085 *jep85 = NULL; |
654 struct jep0085 *jep85 = NULL; |
655 |
655 |
656 if (!online) return; |
656 if (!online) return; |
657 |
657 |
658 rname = strchr(jid, JID_RESOURCE_SEPARATOR); |
658 rname = strchr(fjid, JID_RESOURCE_SEPARATOR); |
659 barejid = jidtodisp(jid); |
659 barejid = jidtodisp(fjid); |
660 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
660 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
661 g_free(barejid); |
661 g_free(barejid); |
662 |
662 |
663 // If we can get a resource name, we use it. Else we use NULL, |
663 // If we can get a resource name, we use it. Else we use NULL, |
664 // which hopefully will give us the most likely resource. |
664 // which hopefully will give us the most likely resource. |
711 struct jep0022 *jep22 = NULL; |
711 struct jep0022 *jep22 = NULL; |
712 guint jep22_state; |
712 guint jep22_state; |
713 |
713 |
714 if (!online) return; |
714 if (!online) return; |
715 |
715 |
716 rname = strchr(jid, JID_RESOURCE_SEPARATOR); |
716 rname = strchr(fjid, JID_RESOURCE_SEPARATOR); |
717 barejid = jidtodisp(jid); |
717 barejid = jidtodisp(fjid); |
718 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
718 sl_buddy = roster_find(barejid, jidsearch, ROSTER_TYPE_USER); |
719 g_free(barejid); |
719 g_free(barejid); |
720 |
720 |
721 // If we can get a resource name, we use it. Else we use NULL, |
721 // If we can get a resource name, we use it. Else we use NULL, |
722 // which hopefully will give us the most likely resource. |
722 // which hopefully will give us the most likely resource. |
745 if (jep22_state == jep22->last_state_sent) |
745 if (jep22_state == jep22->last_state_sent) |
746 return; |
746 return; |
747 jep22->last_state_sent = jep22_state; |
747 jep22->last_state_sent = jep22_state; |
748 } |
748 } |
749 |
749 |
750 x = jutil_msgnew(TMSG_CHAT, (char*)jid, NULL, NULL); |
750 x = jutil_msgnew(TMSG_CHAT, (char*)fjid, NULL, NULL); |
751 |
751 |
752 event = xmlnode_insert_tag(x, "x"); |
752 event = xmlnode_insert_tag(x, "x"); |
753 xmlnode_put_attrib(event, "xmlns", NS_EVENT); |
753 xmlnode_put_attrib(event, "xmlns", NS_EVENT); |
754 if (type == ROSTER_EVENT_DELIVERED) |
754 if (type == ROSTER_EVENT_DELIVERED) |
755 xmlnode_insert_tag(event, "delivered"); |
755 xmlnode_insert_tag(event, "delivered"); |
768 // Send a chatstate or event (JEP-22/85) according to the buddy's capabilities. |
768 // Send a chatstate or event (JEP-22/85) according to the buddy's capabilities. |
769 // The message is sent to one of the resources with the highest priority. |
769 // The message is sent to one of the resources with the highest priority. |
770 #if defined JEP0022 || defined JEP0085 |
770 #if defined JEP0022 || defined JEP0085 |
771 void jb_send_chatstate(gpointer buddy, guint chatstate) |
771 void jb_send_chatstate(gpointer buddy, guint chatstate) |
772 { |
772 { |
773 const char *jid; |
773 const char *bjid; |
774 struct jep0085 *jep85 = NULL; |
774 struct jep0085 *jep85 = NULL; |
775 struct jep0022 *jep22 = NULL; |
775 struct jep0022 *jep22 = NULL; |
776 |
776 |
777 jid = buddy_getjid(buddy); |
777 bjid = buddy_getjid(buddy); |
778 if (!jid) return; |
778 if (!bjid) return; |
779 |
779 |
780 #ifdef JEP0085 |
780 #ifdef JEP0085 |
781 jep85 = buddy_resource_jep85(buddy, NULL); |
781 jep85 = buddy_resource_jep85(buddy, NULL); |
782 if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) { |
782 if (jep85 && jep85->support == CHATSTATES_SUPPORT_OK) { |
783 jb_send_jep85_chatstate(jid, chatstate); |
783 jb_send_jep85_chatstate(bjid, chatstate); |
784 return; |
784 return; |
785 } |
785 } |
786 #endif |
786 #endif |
787 #ifdef JEP0022 |
787 #ifdef JEP0022 |
788 jep22 = buddy_resource_jep22(buddy, NULL); |
788 jep22 = buddy_resource_jep22(buddy, NULL); |
789 if (jep22 && jep22->support == CHATSTATES_SUPPORT_OK) { |
789 if (jep22 && jep22->support == CHATSTATES_SUPPORT_OK) { |
790 jb_send_jep22_event(jid, chatstate); |
790 jb_send_jep22_event(bjid, chatstate); |
791 } |
791 } |
792 #endif |
792 #endif |
793 } |
793 } |
794 #endif |
794 #endif |
795 |
795 |
825 } |
825 } |
826 #endif |
826 #endif |
827 |
827 |
828 // jb_subscr_send_auth(jid) |
828 // jb_subscr_send_auth(jid) |
829 // Allow jid to receive our presence updates |
829 // Allow jid to receive our presence updates |
830 void jb_subscr_send_auth(const char *jid) |
830 void jb_subscr_send_auth(const char *bjid) |
831 { |
831 { |
832 xmlnode x; |
832 xmlnode x; |
833 |
833 |
834 x = jutil_presnew(JPACKET__SUBSCRIBED, (char *)jid, NULL); |
834 x = jutil_presnew(JPACKET__SUBSCRIBED, (char *)bjid, NULL); |
835 jab_send(jc, x); |
835 jab_send(jc, x); |
836 xmlnode_free(x); |
836 xmlnode_free(x); |
837 } |
837 } |
838 |
838 |
839 // jb_subscr_cancel_auth(jid) |
839 // jb_subscr_cancel_auth(jid) |
840 // Cancel jid's subscription to our presence updates |
840 // Cancel jid's subscription to our presence updates |
841 void jb_subscr_cancel_auth(const char *jid) |
841 void jb_subscr_cancel_auth(const char *bjid) |
842 { |
842 { |
843 xmlnode x; |
843 xmlnode x; |
844 |
844 |
845 x = jutil_presnew(JPACKET__UNSUBSCRIBED, (char *)jid, NULL); |
845 x = jutil_presnew(JPACKET__UNSUBSCRIBED, (char *)bjid, NULL); |
846 jab_send(jc, x); |
846 jab_send(jc, x); |
847 xmlnode_free(x); |
847 xmlnode_free(x); |
848 } |
848 } |
849 |
849 |
850 // jb_subscr_request_auth(jid) |
850 // jb_subscr_request_auth(jid) |
851 // Request a subscription to jid's presence updates |
851 // Request a subscription to jid's presence updates |
852 void jb_subscr_request_auth(const char *jid) |
852 void jb_subscr_request_auth(const char *bjid) |
853 { |
853 { |
854 xmlnode x; |
854 xmlnode x; |
855 |
855 |
856 x = jutil_presnew(JPACKET__SUBSCRIBE, (char *)jid, NULL); |
856 x = jutil_presnew(JPACKET__SUBSCRIBE, (char *)bjid, NULL); |
857 jab_send(jc, x); |
857 jab_send(jc, x); |
858 xmlnode_free(x); |
858 xmlnode_free(x); |
859 } |
859 } |
860 |
860 |
861 // jb_subscr_request_cancel(jid) |
861 // jb_subscr_request_cancel(jid) |
862 // Request to cancel jour subscription to jid's presence updates |
862 // Request to cancel jour subscription to jid's presence updates |
863 void jb_subscr_request_cancel(const char *jid) |
863 void jb_subscr_request_cancel(const char *bjid) |
864 { |
864 { |
865 xmlnode x; |
865 xmlnode x; |
866 |
866 |
867 x = jutil_presnew(JPACKET__UNSUBSCRIBE, (char *)jid, NULL); |
867 x = jutil_presnew(JPACKET__UNSUBSCRIBE, (char *)bjid, NULL); |
868 jab_send(jc, x); |
868 jab_send(jc, x); |
869 xmlnode_free(x); |
869 xmlnode_free(x); |
870 } |
870 } |
871 |
871 |
872 // Note: the caller should check the jid is correct |
872 // Note: the caller should check the jid is correct |
873 void jb_addbuddy(const char *jid, const char *name, const char *group) |
873 void jb_addbuddy(const char *bjid, const char *name, const char *group) |
874 { |
874 { |
875 xmlnode y, z; |
875 xmlnode y, z; |
876 eviqs *iqn; |
876 eviqs *iqn; |
877 char *cleanjid; |
877 char *cleanjid; |
878 |
878 |
879 if (!online) return; |
879 if (!online) return; |
880 |
880 |
881 cleanjid = jidtodisp(jid); |
881 cleanjid = jidtodisp(bjid); // Stripping resource, just in case... |
882 |
882 |
883 // We don't check if the jabber user already exists in the roster, |
883 // We don't check if the jabber user already exists in the roster, |
884 // because it allows to re-ask for notification. |
884 // because it allows to re-ask for notification. |
885 |
885 |
886 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
886 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
906 buddylist_build(); |
906 buddylist_build(); |
907 |
907 |
908 update_roster = TRUE; |
908 update_roster = TRUE; |
909 } |
909 } |
910 |
910 |
911 void jb_delbuddy(const char *jid) |
911 void jb_delbuddy(const char *bjid) |
912 { |
912 { |
913 xmlnode y, z; |
913 xmlnode y, z; |
914 eviqs *iqn; |
914 eviqs *iqn; |
915 char *cleanjid; |
915 char *cleanjid; |
916 |
916 |
917 if (!online) return; |
917 if (!online) return; |
918 |
918 |
919 cleanjid = jidtodisp(jid); |
919 cleanjid = jidtodisp(bjid); // Stripping resource, just in case... |
920 |
920 |
921 // If the current buddy is an agent, unsubscribe from it |
921 // If the current buddy is an agent, unsubscribe from it |
922 if (roster_gettype(cleanjid) == ROSTER_TYPE_AGENT) { |
922 if (roster_gettype(cleanjid) == ROSTER_TYPE_AGENT) { |
923 scr_LogPrint(LPRINT_LOGNORM, "Unregistering from the %s agent", cleanjid); |
923 scr_LogPrint(LPRINT_LOGNORM, "Unregistering from the %s agent", cleanjid); |
924 |
924 |
948 buddylist_build(); |
948 buddylist_build(); |
949 |
949 |
950 update_roster = TRUE; |
950 update_roster = TRUE; |
951 } |
951 } |
952 |
952 |
953 void jb_updatebuddy(const char *jid, const char *name, const char *group) |
953 void jb_updatebuddy(const char *bjid, const char *name, const char *group) |
954 { |
954 { |
955 xmlnode y; |
955 xmlnode y; |
956 eviqs *iqn; |
956 eviqs *iqn; |
957 char *cleanjid; |
957 char *cleanjid; |
958 |
958 |
959 if (!online) return; |
959 if (!online) return; |
960 |
960 |
961 // XXX We should check name's and group's correctness |
961 // XXX We should check name's and group's correctness |
962 |
962 |
963 cleanjid = jidtodisp(jid); |
963 cleanjid = jidtodisp(bjid); // Stripping resource, just in case... |
964 |
964 |
965 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
965 iqn = iqs_new(JPACKET__SET, NS_ROSTER, NULL, IQS_DEFAULT_TIMEOUT); |
966 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); |
966 y = xmlnode_insert_tag(xmlnode_get_tag(iqn->xmldata, "query"), "item"); |
967 xmlnode_put_attrib(y, "jid", cleanjid); |
967 xmlnode_put_attrib(y, "jid", cleanjid); |
968 xmlnode_put_attrib(y, "name", name); |
968 xmlnode_put_attrib(y, "name", name); |
998 } else |
998 } else |
999 return; |
999 return; |
1000 |
1000 |
1001 // vCard request |
1001 // vCard request |
1002 if (reqtype == iqreq_vcard) { |
1002 if (reqtype == iqreq_vcard) { |
1003 char *bjid = jidtodisp(jid); |
1003 char *bjid = jidtodisp(fjid); |
1004 request_vcard(bjid); |
1004 request_vcard(bjid); |
1005 scr_LogPrint(LPRINT_NORMAL, "Sent vCard request to <%s>", bjid); |
1005 scr_LogPrint(LPRINT_NORMAL, "Sent vCard request to <%s>", bjid); |
1006 g_free(bjid); |
1006 g_free(bjid); |
1007 return; |
1007 return; |
1008 } |
1008 } |
1009 |
1009 |
1010 if (strchr(jid, JID_RESOURCE_SEPARATOR)) { |
1010 if (strchr(fjid, JID_RESOURCE_SEPARATOR)) { |
1011 // This is a full JID |
1011 // This is a full JID |
1012 (*request_fn)(jid); |
1012 (*request_fn)(fjid); |
1013 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, jid); |
1013 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); |
1014 return; |
1014 return; |
1015 } |
1015 } |
1016 |
1016 |
1017 // The resource has not been specified |
1017 // The resource has not been specified |
1018 roster_elt = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); |
1018 roster_elt = roster_find(fjid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); |
1019 if (!roster_elt) { |
1019 if (!roster_elt) { |
1020 scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", jid); |
1020 scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); |
1021 (*request_fn)(jid); // Let's send a request anyway... |
1021 (*request_fn)(fjid); // Let's send a request anyway... |
1022 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, jid); |
1022 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); |
1023 return; |
1023 return; |
1024 } |
1024 } |
1025 |
1025 |
1026 // Send a request to each resource |
1026 // Send a request to each resource |
1027 resources = buddy_getresources(roster_elt->data); |
1027 resources = buddy_getresources(roster_elt->data); |
1028 if (!resources) { |
1028 if (!resources) { |
1029 scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", jid); |
1029 scr_LogPrint(LPRINT_NORMAL, "No known resource for <%s>...", fjid); |
1030 (*request_fn)(jid); // Let's send a request anyway... |
1030 (*request_fn)(fjid); // Let's send a request anyway... |
1031 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, jid); |
1031 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fjid); |
1032 } |
1032 } |
1033 for ( ; resources ; resources = g_slist_next(resources) ) { |
1033 for ( ; resources ; resources = g_slist_next(resources) ) { |
1034 gchar *fulljid; |
1034 gchar *fulljid; |
1035 fulljid = g_strdup_printf("%s/%s", jid, (char*)resources->data); |
1035 fulljid = g_strdup_printf("%s/%s", fjid, (char*)resources->data); |
1036 (*request_fn)(fulljid); |
1036 (*request_fn)(fulljid); |
1037 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fulljid); |
1037 scr_LogPrint(LPRINT_NORMAL, "Sent %s request to <%s>", strreqtype, fulljid); |
1038 g_free(fulljid); |
1038 g_free(fulljid); |
1039 } |
1039 } |
1040 } |
1040 } |
1142 // allowed) |
1142 // allowed) |
1143 // ra: new role or affiliation |
1143 // ra: new role or affiliation |
1144 // (ex. role none for kick, affil outcast for ban...) |
1144 // (ex. role none for kick, affil outcast for ban...) |
1145 // The reason can be null |
1145 // The reason can be null |
1146 // Return 0 if everything is ok |
1146 // Return 0 if everything is ok |
1147 int jb_room_setattrib(const char *roomid, const char *jid, const char *nick, |
1147 int jb_room_setattrib(const char *roomid, const char *fjid, const char *nick, |
1148 struct role_affil ra, const char *reason) |
1148 struct role_affil ra, const char *reason) |
1149 { |
1149 { |
1150 xmlnode y, z; |
1150 xmlnode y, z; |
1151 eviqs *iqn; |
1151 eviqs *iqn; |
1152 |
1152 |
1153 if (!online || !roomid) return 1; |
1153 if (!online || !roomid) return 1; |
1154 if (!jid && !nick) return 1; |
1154 if (!fjid && !nick) return 1; |
1155 |
1155 |
1156 if (check_jid_syntax((char*)roomid)) { |
1156 if (check_jid_syntax((char*)roomid)) { |
1157 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid); |
1157 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", roomid); |
1158 return 1; |
1158 return 1; |
1159 } |
1159 } |
1160 if (jid && check_jid_syntax((char*)jid)) { |
1160 if (fjid && check_jid_syntax((char*)fjid)) { |
1161 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", jid); |
1161 scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber id", fjid); |
1162 return 1; |
1162 return 1; |
1163 } |
1163 } |
1164 |
1164 |
1165 if (ra.type == type_affil && ra.val.affil == affil_outcast && !jid) |
1165 if (ra.type == type_affil && ra.val.affil == affil_outcast && !fjid) |
1166 return 1; // Shouldn't happen (jid mandatory when banning) |
1166 return 1; // Shouldn't happen (jid mandatory when banning) |
1167 |
1167 |
1168 iqn = iqs_new(JPACKET__SET, "http://jabber.org/protocol/muc#admin", |
1168 iqn = iqs_new(JPACKET__SET, "http://jabber.org/protocol/muc#admin", |
1169 "roleaffil", IQS_DEFAULT_TIMEOUT); |
1169 "roleaffil", IQS_DEFAULT_TIMEOUT); |
1170 xmlnode_put_attrib(iqn->xmldata, "to", roomid); |
1170 xmlnode_put_attrib(iqn->xmldata, "to", roomid); |
1171 xmlnode_put_attrib(iqn->xmldata, "type", "set"); |
1171 xmlnode_put_attrib(iqn->xmldata, "type", "set"); |
1172 y = xmlnode_get_tag(iqn->xmldata, "query"); |
1172 y = xmlnode_get_tag(iqn->xmldata, "query"); |
1173 z = xmlnode_insert_tag(y, "item"); |
1173 z = xmlnode_insert_tag(y, "item"); |
1174 |
1174 |
1175 if (jid) { |
1175 if (fjid) { |
1176 xmlnode_put_attrib(z, "jid", jid); |
1176 xmlnode_put_attrib(z, "jid", fjid); |
1177 } else { // nickname |
1177 } else { // nickname |
1178 xmlnode_put_attrib(z, "nick", nick); |
1178 xmlnode_put_attrib(z, "nick", nick); |
1179 } |
1179 } |
1180 |
1180 |
1181 if (ra.type == type_affil) |
1181 if (ra.type == type_affil) |
1196 } |
1196 } |
1197 |
1197 |
1198 // Invite a user to a MUC room |
1198 // Invite a user to a MUC room |
1199 // room syntax: "room@server" |
1199 // room syntax: "room@server" |
1200 // reason can be null. |
1200 // reason can be null. |
1201 void jb_room_invite(const char *room, const char *jid, const char *reason) |
1201 void jb_room_invite(const char *room, const char *fjid, const char *reason) |
1202 { |
1202 { |
1203 xmlnode x, y, z; |
1203 xmlnode x, y, z; |
1204 |
1204 |
1205 if (!online || !room || !jid) return; |
1205 if (!online || !room || !fjid) return; |
1206 |
1206 |
1207 x = jutil_msgnew(NULL, (char*)room, NULL, NULL); |
1207 x = jutil_msgnew(NULL, (char*)room, NULL, NULL); |
1208 |
1208 |
1209 y = xmlnode_insert_tag(x, "x"); |
1209 y = xmlnode_insert_tag(x, "x"); |
1210 xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); |
1210 xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc#user"); |
1211 |
1211 |
1212 z = xmlnode_insert_tag(y, "invite"); |
1212 z = xmlnode_insert_tag(y, "invite"); |
1213 xmlnode_put_attrib(z, "to", jid); |
1213 xmlnode_put_attrib(z, "to", fjid); |
1214 |
1214 |
1215 if (reason) { |
1215 if (reason) { |
1216 y = xmlnode_insert_tag(z, "reason"); |
1216 y = xmlnode_insert_tag(z, "reason"); |
1217 xmlnode_insert_cdata(y, reason, (unsigned) -1); |
1217 xmlnode_insert_cdata(y, reason, (unsigned) -1); |
1218 } |
1218 } |
1242 } |
1242 } |
1243 |
1243 |
1244 // Walk through the storage tags |
1244 // Walk through the storage tags |
1245 x = xmlnode_get_firstchild(bookmarks); |
1245 x = xmlnode_get_firstchild(bookmarks); |
1246 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1246 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1247 const char *jid; |
1247 const char *fjid; |
1248 const char *p; |
1248 const char *p; |
1249 p = xmlnode_get_name(x); |
1249 p = xmlnode_get_name(x); |
1250 // If the current node is a conference item, see if we have to replace it. |
1250 // If the current node is a conference item, see if we have to replace it. |
1251 if (p && !strcmp(p, "conference")) { |
1251 if (p && !strcmp(p, "conference")) { |
1252 jid = xmlnode_get_attrib(x, "jid"); |
1252 fjid = xmlnode_get_attrib(x, "jid"); |
1253 if (!jid) |
1253 if (!fjid) |
1254 continue; |
1254 continue; |
1255 if (!strcmp(jid, roomid)) { |
1255 if (!strcmp(fjid, roomid)) { |
1256 // We've found a bookmark for this room. Let's hide it and we'll |
1256 // We've found a bookmark for this room. Let's hide it and we'll |
1257 // create a new one. |
1257 // create a new one. |
1258 xmlnode_hide(x); |
1258 xmlnode_hide(x); |
1259 changed = TRUE; |
1259 changed = TRUE; |
1260 break; |
1260 break; |
1352 } |
1352 } |
1353 |
1353 |
1354 // Walk through the storage rosternotes tags |
1354 // Walk through the storage rosternotes tags |
1355 x = xmlnode_get_firstchild(rosternotes); |
1355 x = xmlnode_get_firstchild(rosternotes); |
1356 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1356 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1357 const char *jid; |
1357 const char *fjid; |
1358 const char *p; |
1358 const char *p; |
1359 p = xmlnode_get_name(x); |
1359 p = xmlnode_get_name(x); |
1360 // We want a note item |
1360 // We want a note item |
1361 if (!p || strcmp(p, "note")) |
1361 if (!p || strcmp(p, "note")) |
1362 continue; |
1362 continue; |
1363 // Just in case, check the jid... |
1363 // Just in case, check the jid... |
1364 jid = xmlnode_get_attrib(x, "jid"); |
1364 fjid = xmlnode_get_attrib(x, "jid"); |
1365 if (jid && !strcmp(jid, barejid)) // We've found a note for this contact. |
1365 if (fjid && !strcmp(fjid, barejid)) // We've found a note for this contact. |
1366 return parse_storage_rosternote(x); |
1366 return parse_storage_rosternote(x); |
1367 } |
1367 } |
1368 return NULL; // No note found |
1368 return NULL; // No note found |
1369 } |
1369 } |
1370 |
1370 |
1388 } |
1388 } |
1389 |
1389 |
1390 // Walk through the storage tags |
1390 // Walk through the storage tags |
1391 x = xmlnode_get_firstchild(rosternotes); |
1391 x = xmlnode_get_firstchild(rosternotes); |
1392 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1392 for ( ; x; x = xmlnode_get_nextsibling(x)) { |
1393 const char *jid; |
1393 const char *fjid; |
1394 const char *p; |
1394 const char *p; |
1395 p = xmlnode_get_name(x); |
1395 p = xmlnode_get_name(x); |
1396 // If the current node is a conference item, see if we have to replace it. |
1396 // If the current node is a conference item, see if we have to replace it. |
1397 if (p && !strcmp(p, "note")) { |
1397 if (p && !strcmp(p, "note")) { |
1398 jid = xmlnode_get_attrib(x, "jid"); |
1398 fjid = xmlnode_get_attrib(x, "jid"); |
1399 if (!jid) |
1399 if (!fjid) |
1400 continue; |
1400 continue; |
1401 if (!strcmp(jid, barejid)) { |
1401 if (!strcmp(fjid, barejid)) { |
1402 // We've found a note for this jid. Let's hide it and we'll |
1402 // We've found a note for this jid. Let's hide it and we'll |
1403 // create a new one. |
1403 // create a new one. |
1404 cdate = xmlnode_get_attrib(x, "cdate"); |
1404 cdate = xmlnode_get_attrib(x, "cdate"); |
1405 xmlnode_hide(x); |
1405 xmlnode_hide(x); |
1406 changed = TRUE; |
1406 changed = TRUE; |
1490 |
1490 |
1491 static void gotmessage(char *type, const char *from, const char *body, |
1491 static void gotmessage(char *type, const char *from, const char *body, |
1492 const char *enc, time_t timestamp, |
1492 const char *enc, time_t timestamp, |
1493 xmlnode xmldata_signed) |
1493 xmlnode xmldata_signed) |
1494 { |
1494 { |
1495 char *jid; |
1495 char *bjid; |
1496 const char *rname, *s; |
1496 const char *rname, *s; |
1497 char *decrypted = NULL; |
1497 char *decrypted = NULL; |
1498 |
1498 |
1499 jid = jidtodisp(from); |
1499 bjid = jidtodisp(from); |
1500 |
1500 |
1501 rname = strchr(from, JID_RESOURCE_SEPARATOR); |
1501 rname = strchr(from, JID_RESOURCE_SEPARATOR); |
1502 if (rname) rname++; |
1502 if (rname) rname++; |
1503 |
1503 |
1504 #ifdef HAVE_GPGME |
1504 #ifdef HAVE_GPGME |
1508 body = decrypted; |
1508 body = decrypted; |
1509 } |
1509 } |
1510 } |
1510 } |
1511 // Check signature of an unencrypted message |
1511 // Check signature of an unencrypted message |
1512 if (xmldata_signed && gpg_enabled()) |
1512 if (xmldata_signed && gpg_enabled()) |
1513 check_signature(jid, rname, xmldata_signed, decrypted); |
1513 check_signature(bjid, rname, xmldata_signed, decrypted); |
1514 #endif |
1514 #endif |
1515 |
1515 |
1516 // Check for unexpected groupchat messages |
1516 // Check for unexpected groupchat messages |
1517 // If we receive a groupchat message from a room we're not a member of, |
1517 // If we receive a groupchat message from a room we're not a member of, |
1518 // this is probably a server issue and the best we can do is to send |
1518 // this is probably a server issue and the best we can do is to send |
1519 // a type unavailable. |
1519 // a type unavailable. |
1520 if (type && !strcmp(type, "groupchat") && !roster_getnickname(jid)) { |
1520 if (type && !strcmp(type, "groupchat") && !roster_getnickname(bjid)) { |
1521 // It shouldn't happen, probably a server issue |
1521 // It shouldn't happen, probably a server issue |
1522 GSList *room_elt; |
1522 GSList *room_elt; |
1523 char *mbuf; |
1523 char *mbuf; |
1524 |
1524 |
1525 mbuf = g_strdup_printf("Unexpected groupchat packet!"); |
1525 mbuf = g_strdup_printf("Unexpected groupchat packet!"); |
1526 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); |
1526 scr_LogPrint(LPRINT_LOGNORM, "%s", mbuf); |
1527 scr_WriteIncomingMessage(jid, mbuf, 0, HBB_PREFIX_INFO); |
1527 scr_WriteIncomingMessage(bjid, mbuf, 0, HBB_PREFIX_INFO); |
1528 g_free(mbuf); |
1528 g_free(mbuf); |
1529 |
1529 |
1530 // Send back an unavailable packet |
1530 // Send back an unavailable packet |
1531 jb_setstatus(offline, jid, "", TRUE); |
1531 jb_setstatus(offline, bjid, "", TRUE); |
1532 |
1532 |
1533 // MUC |
1533 // MUC |
1534 // Make sure this is a room (it can be a conversion user->room) |
1534 // Make sure this is a room (it can be a conversion user->room) |
1535 room_elt = roster_find(jid, jidsearch, 0); |
1535 room_elt = roster_find(bjid, jidsearch, 0); |
1536 if (!room_elt) { |
1536 if (!room_elt) { |
1537 room_elt = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_ROOM, sub_none); |
1537 room_elt = roster_add_user(bjid, NULL, NULL, ROSTER_TYPE_ROOM, sub_none); |
1538 } else { |
1538 } else { |
1539 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); |
1539 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); |
1540 } |
1540 } |
1541 |
1541 |
1542 g_free(jid); |
1542 g_free(bjid); |
1543 g_free(decrypted); |
1543 g_free(decrypted); |
1544 |
1544 |
1545 buddylist_build(); |
1545 buddylist_build(); |
1546 scr_DrawRoster(); |
1546 scr_DrawRoster(); |
1547 return; |
1547 return; |
1549 |
1549 |
1550 // We don't call the message_in hook if 'block_unsubscribed' is true and |
1550 // We don't call the message_in hook if 'block_unsubscribed' is true and |
1551 // this is a regular message from an unsubscribed user. |
1551 // this is a regular message from an unsubscribed user. |
1552 // System messages (from our server) are allowed. |
1552 // System messages (from our server) are allowed. |
1553 if (!settings_opt_get_int("block_unsubscribed") || |
1553 if (!settings_opt_get_int("block_unsubscribed") || |
1554 (roster_getsubscription(jid) & sub_from) || |
1554 (roster_getsubscription(bjid) & sub_from) || |
1555 (type && strcmp(type, "chat")) || |
1555 (type && strcmp(type, "chat")) || |
1556 ((s = settings_opt_get("server")) != NULL && !strcasecmp(jid, s))) { |
1556 ((s = settings_opt_get("server")) != NULL && !strcasecmp(bjid, s))) { |
1557 hk_message_in(jid, rname, timestamp, body, type, |
1557 hk_message_in(bjid, rname, timestamp, body, type, |
1558 (decrypted ? TRUE : FALSE)); |
1558 (decrypted ? TRUE : FALSE)); |
1559 } else { |
1559 } else { |
1560 scr_LogPrint(LPRINT_LOGNORM, "Blocked a message from <%s>", jid); |
1560 scr_LogPrint(LPRINT_LOGNORM, "Blocked a message from <%s>", bjid); |
1561 } |
1561 } |
1562 g_free(jid); |
1562 g_free(bjid); |
1563 g_free(decrypted); |
1563 g_free(decrypted); |
1564 } |
1564 } |
1565 |
1565 |
1566 static const char *defaulterrormsg(int code) |
1566 static const char *defaulterrormsg(int code) |
1567 { |
1567 { |
2161 JEP_85, |
2161 JEP_85, |
2162 JEP_22 |
2162 JEP_22 |
2163 } which_jep = JEP_none; |
2163 } which_jep = JEP_none; |
2164 |
2164 |
2165 rname = strchr(from, JID_RESOURCE_SEPARATOR); |
2165 rname = strchr(from, JID_RESOURCE_SEPARATOR); |
2166 jid = jidtodisp(from); |
2166 bjid = jidtodisp(from); |
2167 sl_buddy = roster_find(jid, jidsearch, ROSTER_TYPE_USER); |
2167 sl_buddy = roster_find(bjid, jidsearch, ROSTER_TYPE_USER); |
|
2168 g_free(bjid); |
2168 |
2169 |
2169 /* XXX Actually that's wrong, since it filters out server "offline" |
2170 /* XXX Actually that's wrong, since it filters out server "offline" |
2170 messages (for JEP-0022). This JEP is (almost) deprecated so |
2171 messages (for JEP-0022). This JEP is (almost) deprecated so |
2171 we don't really care. */ |
2172 we don't really care. */ |
2172 if (!sl_buddy || !rname++) { |
2173 if (!sl_buddy || !rname++) { |
2173 g_free(jid); |
|
2174 return; |
2174 return; |
2175 } |
2175 } |
2176 |
2176 |
2177 /* Let's see chich JEP the contact uses. If possible, we'll use |
2177 /* Let's see chich JEP the contact uses. If possible, we'll use |
2178 JEP-85, if not we'll look for JEP-22 support. */ |
2178 JEP-85, if not we'll look for JEP-22 support. */ |