Mercurial > pidgin
comparison src/protocols/zephyr/zephyr.c @ 9478:0efa260e384f
[gaim-migrate @ 10303]
" This patch adds the following features for zephyr, in order
of usefulness :-)
Protocol action (Retrieve subscriptions from server) to
list user's subscriptions (chats) in a popup window.
Typing notification - (both sending and receiving --
using zephyrs with opcode ping).
Correct interpretation of %host% and %canon% entries in
.zephyr.subs . These are often used to subscribe to
system messages concerning a specific machine (by
hostname and canonical hostname, respectively).
An updated .todo list." --Arun A Tharuvai
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Wed, 07 Jul 2004 21:56:57 +0000 |
parents | 7a65fdba750f |
children | 8b2451878e26 |
comparison
equal
deleted
inserted
replaced
9477:2c7dcb5851f4 | 9478:0efa260e384f |
---|---|
33 #include "server.h" | 33 #include "server.h" |
34 #include "util.h" | 34 #include "util.h" |
35 #include "cmds.h" | 35 #include "cmds.h" |
36 | 36 |
37 #include "zephyr/zephyr.h" | 37 #include "zephyr/zephyr.h" |
38 #include "internal.h" | |
38 | 39 |
39 #include <strings.h> | 40 #include <strings.h> |
40 | 41 |
41 #define ZEPHYR_FALLBACK_CHARSET "ISO-8859-1" | 42 #define ZEPHYR_FALLBACK_CHARSET "ISO-8859-1" |
43 | |
44 /* these are deliberately high, since most people don't send multiple "PING"s */ | |
45 #define ZEPHYR_TYPING_SEND_TIMEOUT 15 | |
46 #define ZEPHYR_TYPING_RECV_TIMEOUT 10 | |
42 | 47 |
43 extern Code_t ZGetLocations(ZLocations_t *, int *); | 48 extern Code_t ZGetLocations(ZLocations_t *, int *); |
44 extern Code_t ZSetLocation(char *); | 49 extern Code_t ZSetLocation(char *); |
45 extern Code_t ZUnsetLocation(); | 50 extern Code_t ZUnsetLocation(); |
51 extern Code_t ZGetSubscriptions(ZSubscription_t *, int*); | |
46 | 52 |
47 typedef struct _zframe zframe; | 53 typedef struct _zframe zframe; |
48 typedef struct _zephyr_triple zephyr_triple; | 54 typedef struct _zephyr_triple zephyr_triple; |
55 | |
56 char ourhost[MAXHOSTNAMELEN]; | |
57 char ourhostcanon[MAXHOSTNAMELEN]; | |
49 | 58 |
50 /* struct I need for zephyr_to_html */ | 59 /* struct I need for zephyr_to_html */ |
51 struct _zframe { | 60 struct _zframe { |
52 /* true for everything but @color, since inside the parens of that one is | 61 /* true for everything but @color, since inside the parens of that one is |
53 * the color. */ | 62 * the color. */ |
112 static guint32 loctimer = 0; | 121 static guint32 loctimer = 0; |
113 GaimConnection *zgc = NULL; | 122 GaimConnection *zgc = NULL; |
114 static GList *pending_zloc_names = NULL; | 123 static GList *pending_zloc_names = NULL; |
115 static GSList *subscrips = NULL; | 124 static GSList *subscrips = NULL; |
116 static int last_id = 0; | 125 static int last_id = 0; |
117 | 126 unsigned short zephyr_port; |
118 /* just for debugging */ | 127 /* just for debugging */ |
119 static void handle_unknown(ZNotice_t notice) | 128 static void handle_unknown(ZNotice_t notice) |
120 { | 129 { |
121 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_packet: %s\n", notice.z_packet); | 130 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_packet: %s\n", notice.z_packet); |
122 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_version: %s\n", notice.z_version); | 131 gaim_debug(GAIM_DEBUG_MISC, "zephyr","z_version: %s\n", notice.z_version); |
152 g_free(zt->recipient); | 161 g_free(zt->recipient); |
153 g_free(zt->name); | 162 g_free(zt->name); |
154 g_free(zt); | 163 g_free(zt); |
155 } | 164 } |
156 | 165 |
157 static const char *gaim_zephyr_get_sender() | 166 static gchar *gaim_zephyr_get_sender() |
158 { | 167 { |
159 /* will be useful once this plugin can use a backend other | 168 /* will be useful once this plugin can use a backend other |
160 than libzephyr */ | 169 than libzephyr */ |
161 return ZGetSender(); | 170 /* XXX add zephyr error reporting */ |
171 gchar *sender; | |
172 sender = ZGetSender(); | |
173 if (!sender || !g_ascii_strcasecmp(sender,"")) { | |
174 sender = ""; | |
175 } | |
176 return sender; | |
162 } | 177 } |
163 | 178 |
164 static const char *gaim_zephyr_get_realm() | 179 static const char *gaim_zephyr_get_realm() |
165 { | 180 { |
166 /* will be useful once this plugin can use a backend other | 181 /* will be useful once this plugin can use a backend other |
167 than libzephyr */ | 182 than libzephyr */ |
168 return ZGetRealm(); | 183 gchar *realm=NULL; |
184 /* XXX add zephyr error reporting */ | |
185 realm= ZGetRealm(); | |
186 return realm; | |
169 } | 187 } |
170 | 188 |
171 /* returns true if zt1 is a subset of zt2. This function is used to | 189 /* returns true if zt1 is a subset of zt2. This function is used to |
172 determine whether a zephyr sent to zt1 should be placed in the chat | 190 determine whether a zephyr sent to zt1 should be placed in the chat |
173 with triple zt2 | 191 with triple zt2 |
263 { | 281 { |
264 int len, cnt, retcount; | 282 int len, cnt, retcount; |
265 char *ret; | 283 char *ret; |
266 | 284 |
267 len = strlen(message); | 285 len = strlen(message); |
286 if (!len) | |
287 return g_strdup(""); | |
288 | |
268 ret = g_new0(char, len * 3); | 289 ret = g_new0(char, len * 3); |
269 | 290 |
270 bzero(ret, len * 3); | 291 bzero(ret, len * 3); |
271 retcount = 0; | 292 retcount = 0; |
272 cnt = 0; | 293 cnt = 0; |
581 if (!g_ascii_strcasecmp(notice.z_opcode, LOCATE_LOCATE)) { | 602 if (!g_ascii_strcasecmp(notice.z_opcode, LOCATE_LOCATE)) { |
582 int nlocs; | 603 int nlocs; |
583 char *user; | 604 char *user; |
584 GaimBuddy *b; | 605 GaimBuddy *b; |
585 | 606 |
607 /* XXX add real error reporting */ | |
586 if (ZParseLocations(¬ice, NULL, &nlocs, &user) != ZERR_NONE) | 608 if (ZParseLocations(¬ice, NULL, &nlocs, &user) != ZERR_NONE) |
587 return; | 609 return; |
588 | 610 |
589 if ((b = gaim_find_buddy(zgc->account, user)) == NULL) { | 611 if ((b = gaim_find_buddy(zgc->account, user)) == NULL) { |
590 char *e = strchr(user, '@'); | 612 char *e = strchr(user, '@'); |
604 g_string_append_printf(str, _("<b>Alias:</b> %s<br>"), b->alias); | 626 g_string_append_printf(str, _("<b>Alias:</b> %s<br>"), b->alias); |
605 if (!nlocs) { | 627 if (!nlocs) { |
606 g_string_append_printf(str, _("<br>Hidden or not logged-in")); | 628 g_string_append_printf(str, _("<br>Hidden or not logged-in")); |
607 } | 629 } |
608 for (; nlocs > 0; nlocs--) { | 630 for (; nlocs > 0; nlocs--) { |
631 /* XXX add real error reporting */ | |
609 ZGetLocations(&locs, &one); | 632 ZGetLocations(&locs, &one); |
610 g_string_append_printf(str, _("<br>At %s since %s"), locs.host, locs.time); | 633 g_string_append_printf(str, _("<br>At %s since %s"), locs.host, locs.time); |
611 } | 634 } |
612 gaim_notify_formatted(zgc, NULL, _("Buddy Information"), NULL, str->str, NULL, NULL); | 635 gaim_notify_formatted(zgc, NULL, _("Buddy Information"), NULL, str->str, NULL, NULL); |
613 g_string_free(str, TRUE); | 636 g_string_free(str, TRUE); |
620 char *buf, *buf2, *buf3; | 643 char *buf, *buf2, *buf3; |
621 char *send_inst; | 644 char *send_inst; |
622 GaimConversation *gconv1; | 645 GaimConversation *gconv1; |
623 GaimConvChat *gcc; | 646 GaimConvChat *gcc; |
624 char *ptr = notice.z_message + strlen(notice.z_message) + 1; | 647 char *ptr = notice.z_message + strlen(notice.z_message) + 1; |
625 int len = notice.z_message_len - (strlen(notice.z_message) +1); | 648 int len; |
626 char *sendertmp = g_strdup_printf("%s", gaim_zephyr_get_sender()); | 649 char *sendertmp = g_strdup_printf("%s", gaim_zephyr_get_sender()); |
650 int signature_length = strlen(notice.z_message); | |
651 int message_has_no_body = 0; | |
627 GaimConvImFlags flags = 0; | 652 GaimConvImFlags flags = 0; |
628 | |
629 if (len > 0) { | |
630 gchar *tmpescape; | 653 gchar *tmpescape; |
631 | 654 |
655 /* Need to deal with 0 length messages to handle typing notification (OPCODE) ping messages */ | |
656 /* One field zephyrs would have caused gaim to crash */ | |
657 if ( (notice.z_message_len == 0) || (signature_length >= notice.z_message_len - 1)) { | |
658 message_has_no_body = 1; | |
659 len = 0; | |
660 gaim_debug_info("zephyr","message_size %d %d %d\n",len,notice.z_message_len,signature_length); | |
661 buf3 = g_strdup(""); | |
662 | |
663 } else { | |
664 len = notice.z_message_len - ( signature_length +1); | |
665 gaim_debug_info("zephyr","message_size %d %d %d\n",len,notice.z_message_len,signature_length); | |
632 buf = g_malloc(len + 1); | 666 buf = g_malloc(len + 1); |
633 g_snprintf(buf, len + 1, "%s", ptr); | 667 g_snprintf(buf, len + 1, "%s", ptr); |
634 g_strchomp(buf); | 668 g_strchomp(buf); |
635 tmpescape = gaim_escape_html(buf); | 669 tmpescape = gaim_escape_html(buf); |
670 g_free(buf); | |
636 buf2 = zephyr_to_html(tmpescape); | 671 buf2 = zephyr_to_html(tmpescape); |
637 buf3 = zephyr_recv_convert(buf2, strlen(buf2)); | 672 buf3 = zephyr_recv_convert(buf2, strlen(buf2)); |
638 g_free(buf2); | 673 g_free(buf2); |
639 g_free(buf); | |
640 g_free(tmpescape); | 674 g_free(tmpescape); |
675 } | |
641 | 676 |
642 if (!g_ascii_strcasecmp(notice.z_class, "MESSAGE") && !g_ascii_strcasecmp(notice.z_class_inst, "PERSONAL") | 677 if (!g_ascii_strcasecmp(notice.z_class, "MESSAGE") && !g_ascii_strcasecmp(notice.z_class_inst, "PERSONAL") |
643 && !g_ascii_strcasecmp(notice.z_recipient,gaim_zephyr_get_sender())) { | 678 && !g_ascii_strcasecmp(notice.z_recipient,gaim_zephyr_get_sender())) { |
644 gchar* stripped_sender; | 679 gchar* stripped_sender; |
645 if (!g_ascii_strcasecmp(notice.z_message, "Automated reply:")) | 680 if (!g_ascii_strcasecmp(notice.z_message, "Automated reply:")) |
646 flags |= GAIM_CONV_IM_AUTO_RESP; | 681 flags |= GAIM_CONV_IM_AUTO_RESP; |
647 stripped_sender = zephyr_strip_foreign_realm(notice.z_sender); | 682 stripped_sender = zephyr_strip_foreign_realm(notice.z_sender); |
683 | |
684 if (!g_ascii_strcasecmp(notice.z_opcode,"PING")) | |
685 serv_got_typing(zgc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, GAIM_TYPING); | |
686 else | |
648 serv_got_im(zgc, stripped_sender, buf3, flags, time(NULL)); | 687 serv_got_im(zgc, stripped_sender, buf3, flags, time(NULL)); |
688 | |
649 g_free(stripped_sender); | 689 g_free(stripped_sender); |
650 } else { | 690 } else { |
651 zephyr_triple *zt1, *zt2; | 691 zephyr_triple *zt1, *zt2; |
652 GList *gltmp; | 692 GList *gltmp; |
653 int found = 0; | 693 int found = 0; |
671 Realm from the sender field */ | 711 Realm from the sender field */ |
672 sendertmp = zephyr_strip_foreign_realm(notice.z_sender); | 712 sendertmp = zephyr_strip_foreign_realm(notice.z_sender); |
673 send_inst = g_strdup_printf("%s %s",sendertmp,notice.z_class_inst); | 713 send_inst = g_strdup_printf("%s %s",sendertmp,notice.z_class_inst); |
674 send_inst_utf8 = zephyr_recv_convert(send_inst, strlen(send_inst)); | 714 send_inst_utf8 = zephyr_recv_convert(send_inst, strlen(send_inst)); |
675 if (!send_inst_utf8) { | 715 if (!send_inst_utf8) { |
676 fprintf(stderr, "zephyr: send_inst %s became null\n",send_inst); | |
677 gaim_debug(GAIM_DEBUG_ERROR, "zephyr","send_inst %s became null\n", send_inst); | 716 gaim_debug(GAIM_DEBUG_ERROR, "zephyr","send_inst %s became null\n", send_inst); |
678 send_inst_utf8 = "malformed instance"; | 717 send_inst_utf8 = "malformed instance"; |
679 } | 718 } |
680 | 719 |
681 serv_got_chat_in(zgc, zt2->id, send_inst_utf8, FALSE, buf3, time(NULL)); | 720 serv_got_chat_in(zgc, zt2->id, send_inst_utf8, FALSE, buf3, time(NULL)); |
702 g_free(send_inst_utf8); | 741 g_free(send_inst_utf8); |
703 | 742 |
704 free_triple(zt1); | 743 free_triple(zt1); |
705 } | 744 } |
706 g_free(buf3); | 745 g_free(buf3); |
707 } | 746 |
708 } | 747 } |
709 } | 748 } |
710 | 749 |
711 static gint check_notify(gpointer data) | 750 static gint check_notify(gpointer data) |
712 { | 751 { |
752 /* XXX add real error reporting */ | |
753 | |
713 while (ZPending()) { | 754 while (ZPending()) { |
714 ZNotice_t notice; | 755 ZNotice_t notice; |
715 struct sockaddr_in from; | 756 struct sockaddr_in from; |
757 /* XXX add real error reporting */ | |
716 | 758 |
717 z_call_r(ZReceiveNotice(¬ice, &from)); | 759 z_call_r(ZReceiveNotice(¬ice, &from)); |
718 | 760 |
719 switch (notice.z_kind) { | 761 switch (notice.z_kind) { |
720 case UNSAFE: | 762 case UNSAFE: |
726 if (!(g_ascii_strcasecmp(notice.z_message, ZSRVACK_NOTSENT))) { | 768 if (!(g_ascii_strcasecmp(notice.z_message, ZSRVACK_NOTSENT))) { |
727 message_failed(notice, from); | 769 message_failed(notice, from); |
728 } | 770 } |
729 break; | 771 break; |
730 case CLIENTACK: | 772 case CLIENTACK: |
731 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "Client ack received\n"); | 773 gaim_debug_error("zephyr", "Client ack received\n"); |
732 default: | 774 default: |
733 /* we'll just ignore things for now */ | 775 /* we'll just ignore things for now */ |
734 handle_unknown(notice); | 776 handle_unknown(notice); |
735 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "Unhandled notice.\n"); | 777 gaim_debug_error("zephyr", "Unhandled notice.\n"); |
736 break; | 778 break; |
737 } | 779 } |
738 | 780 /* XXX add real error reporting */ |
739 ZFreeNotice(¬ice); | 781 ZFreeNotice(¬ice); |
740 } | 782 } |
741 | 783 |
742 return TRUE; | 784 return TRUE; |
743 } | 785 } |
764 continue; | 806 continue; |
765 if (b->account->gc == zgc) { | 807 if (b->account->gc == zgc) { |
766 const char *chk; | 808 const char *chk; |
767 | 809 |
768 chk = local_zephyr_normalize(b->name); | 810 chk = local_zephyr_normalize(b->name); |
811 /* XXX add real error reporting */ | |
769 /* doesn't matter if this fails or not; we'll just move on to the next one */ | 812 /* doesn't matter if this fails or not; we'll just move on to the next one */ |
770 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); | 813 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); |
771 g_free(ald.user); | 814 g_free(ald.user); |
772 g_free(ald.version); | 815 g_free(ald.version); |
773 } | 816 } |
778 return TRUE; | 821 return TRUE; |
779 } | 822 } |
780 | 823 |
781 static char *get_exposure_level() | 824 static char *get_exposure_level() |
782 { | 825 { |
826 /* XXX add real error reporting */ | |
783 char *exposure = ZGetVariable("exposure"); | 827 char *exposure = ZGetVariable("exposure"); |
784 | 828 |
785 if (!exposure) | 829 if (!exposure) |
786 return EXPOSE_REALMVIS; | 830 return EXPOSE_REALMVIS; |
787 if (!g_ascii_strcasecmp(exposure, EXPOSE_NONE)) | 831 if (!g_ascii_strcasecmp(exposure, EXPOSE_NONE)) |
805 *tmp = '\0'; | 849 *tmp = '\0'; |
806 g_strchug(str); | 850 g_strchug(str); |
807 g_strchomp(str); | 851 g_strchomp(str); |
808 } | 852 } |
809 | 853 |
854 static void zephyr_inithosts() | |
855 { | |
856 /* XXX This code may not be Win32 clean */ | |
857 struct hostent *hent; | |
858 | |
859 if (gethostname(ourhost, sizeof(ourhost)-1) == -1) { | |
860 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "unable to retrieve hostname, %%host%% and %%canon%% will be wrong in subscriptions and have been set to unknown\n"); | |
861 g_stpcpy(ourhost,"unknown"); | |
862 g_stpcpy(ourhostcanon,"unknown"); | |
863 return; | |
864 } | |
865 | |
866 if (!(hent = gethostbyname(ourhost))) { | |
867 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "unable to resolve hostname, %%canon%% will be wrong in subscriptions.and has been set to the value of %%host%%, %s\n",ourhost); | |
868 g_stpcpy(ourhostcanon,ourhost); | |
869 return; | |
870 } | |
871 g_stpcpy(ourhostcanon,hent->h_name); | |
872 return; | |
873 } | |
874 | |
810 static void process_zsubs() | 875 static void process_zsubs() |
811 { | 876 { |
812 /* Loads zephyr chats "(subscriptions) from ~/.zephyr.subs, and | 877 /* Loads zephyr chats "(subscriptions) from ~/.zephyr.subs, and |
813 registers (subscribes to) them on the server */ | 878 registers (subscribes to) them on the server */ |
814 | 879 |
815 /* XXX write subscriptions into the buddy list somehow "a Zephyr Chats group?"*/ | |
816 /* XXX deal with unsubscriptions */ | 880 /* XXX deal with unsubscriptions */ |
817 /* XXX deal with punts */ | 881 /* XXX deal with punts */ |
818 | 882 |
819 FILE *f; | 883 FILE *f; |
820 gchar *fname; | 884 gchar *fname; |
821 gchar buff[BUFSIZ]; | 885 gchar buff[BUFSIZ]; |
822 | 886 |
887 zephyr_inithosts(); | |
823 fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir()); | 888 fname = g_strdup_printf("%s/.zephyr.subs", gaim_home_dir()); |
824 f = fopen(fname, "r"); | 889 f = fopen(fname, "r"); |
825 if (f) { | 890 if (f) { |
826 char **triple; | 891 char **triple; |
827 ZSubscription_t sub; | 892 ZSubscription_t sub; |
828 char *recip; | 893 char *recip; |
894 char *z_class; | |
895 char *z_instance; | |
829 | 896 |
830 while (fgets(buff, BUFSIZ, f)) { | 897 while (fgets(buff, BUFSIZ, f)) { |
831 strip_comments(buff); | 898 strip_comments(buff); |
832 if (buff[0]) { | 899 if (buff[0]) { |
833 triple = g_strsplit(buff, ",", 3); | 900 triple = g_strsplit(buff, ",", 3); |
865 } else { | 932 } else { |
866 recip = g_strdup(triple[2]); | 933 recip = g_strdup(triple[2]); |
867 } | 934 } |
868 g_free(tmp); | 935 g_free(tmp); |
869 sub.zsub_recipient = recip; | 936 sub.zsub_recipient = recip; |
937 | |
938 if (!g_ascii_strcasecmp(triple[0],"%host%")) { | |
939 z_class = g_strdup(ourhost); | |
940 } else if (!g_ascii_strcasecmp(triple[0],"%canon%")) { | |
941 z_class = g_strdup(ourhostcanon); | |
942 } else { | |
943 z_class = g_strdup(triple[0]); | |
944 } | |
945 sub.zsub_class = z_class; | |
946 | |
947 if (!g_ascii_strcasecmp(triple[1],"%host%")) { | |
948 z_instance = g_strdup(ourhost); | |
949 } else if (!g_ascii_strcasecmp(triple[1],"%canon%")) { | |
950 z_instance = g_strdup(ourhostcanon); | |
951 } else { | |
952 z_instance = g_strdup(triple[1]); | |
953 } | |
954 sub.zsub_classinst = z_instance; | |
955 | |
956 /* There should be some sort of error report listing classes that couldn't be subbed to. | |
957 Not important right now though */ | |
958 | |
870 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { | 959 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { |
960 | |
871 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "Couldn't subscribe to %s, %s, %s\n", sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient); | 961 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "Couldn't subscribe to %s, %s, %s\n", sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient); |
872 } | 962 } |
873 subscrips = g_slist_append(subscrips, new_triple(triple[0], triple[1], recip)); | 963 |
964 subscrips = g_slist_append(subscrips, new_triple(sub.zsub_class,sub.zsub_classinst,sub.zsub_recipient)); | |
965 /* g_hash_table_destroy(sub_hash_table); */ | |
966 g_free(z_instance); | |
967 g_free(z_class); | |
874 g_free(recip); | 968 g_free(recip); |
875 } | 969 } |
876 g_strfreev(triple); | 970 g_strfreev(triple); |
877 } | 971 } |
878 } | 972 } |
909 | 1003 |
910 static void zephyr_login(GaimAccount * account) | 1004 static void zephyr_login(GaimAccount * account) |
911 { | 1005 { |
912 ZSubscription_t sub; | 1006 ZSubscription_t sub; |
913 | 1007 |
1008 /* This needs to fixed to deal with multiple accounts somehow */ | |
914 if (zgc) { | 1009 if (zgc) { |
915 gaim_notify_error(account->gc, NULL, | 1010 gaim_notify_error(account->gc, NULL, |
916 _("Already logged in with Zephyr"), _("Because Zephyr uses your system username, you " "are unable to have multiple accounts on it " "when logged in as the same user.")); | 1011 _("Already logged in with Zephyr"), _("Because Zephyr uses your system username, you " "are unable to have multiple accounts on it " "when logged in as the same user.")); |
917 return; | 1012 return; |
918 } | 1013 } |
919 | 1014 |
920 zgc = gaim_account_get_connection(account); | 1015 zgc = gaim_account_get_connection(account); |
921 zgc->flags |= GAIM_CONNECTION_HTML; | 1016 zgc->flags |= GAIM_CONNECTION_HTML | GAIM_CONNECTION_NO_BGCOLOR | GAIM_CONNECTION_NO_URLDESC; |
922 gaim_connection_update_progress(zgc, _("Connecting"), 0, 2); | 1017 gaim_connection_update_progress(zgc, _("Connecting"), 0, 8); |
1018 | |
1019 /* XXX z_call_s should actually try to report the com_err determined error */ | |
923 | 1020 |
924 z_call_s(ZInitialize(), "Couldn't initialize zephyr"); | 1021 z_call_s(ZInitialize(), "Couldn't initialize zephyr"); |
925 z_call_s(ZOpenPort(NULL), "Couldn't open port"); | 1022 z_call_s(ZOpenPort(&zephyr_port), "Couldn't open port"); |
926 z_call_s(ZSetLocation((char *) | 1023 z_call_s(ZSetLocation((char *) |
927 gaim_account_get_string(zgc->account, "exposure_level", EXPOSE_REALMVIS)), "Couldn't set location"); | 1024 gaim_account_get_string(zgc->account, "exposure_level", EXPOSE_REALMVIS)), "Couldn't set location"); |
928 | 1025 |
929 sub.zsub_class = "MESSAGE"; | 1026 sub.zsub_class = "MESSAGE"; |
930 sub.zsub_classinst = "PERSONAL"; | 1027 sub.zsub_classinst = "PERSONAL"; |
931 sub.zsub_recipient = (char *)gaim_zephyr_get_sender(); | 1028 sub.zsub_recipient = (char *)gaim_zephyr_get_sender(); |
932 | 1029 |
933 /* we don't care if this fails. i'm lying right now. */ | |
934 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { | 1030 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { |
935 gaim_debug(GAIM_DEBUG_ERROR, "zephyr", "Couldn't subscribe to messages!\n"); | 1031 /* XXX don't translate this yet. It could be written better */ |
1032 /* XXX error messages could be handled with more detail */ | |
1033 gaim_notify_error(account->gc, NULL, | |
1034 "Unable to subscribe to messages", "Unable to subscribe to initial messages"); | |
1035 return; | |
936 } | 1036 } |
937 | 1037 |
938 gaim_connection_set_state(zgc, GAIM_CONNECTED); | 1038 gaim_connection_set_state(zgc, GAIM_CONNECTED); |
939 serv_finish_login(zgc); | 1039 serv_finish_login(zgc); |
940 | 1040 |
966 g_free(fname); | 1066 g_free(fname); |
967 return; | 1067 return; |
968 } | 1068 } |
969 | 1069 |
970 while (s) { | 1070 while (s) { |
1071 char *zclass, *zinst, *zrecip; | |
971 zt = s->data; | 1072 zt = s->data; |
972 triple = g_strsplit(zt->name, ",", 3); | 1073 triple = g_strsplit(zt->name, ",", 3); |
973 if (triple[2] != NULL) { | 1074 |
974 if (!g_ascii_strcasecmp(triple[2], "")) { | 1075 /* deal with classes */ |
975 fprintf(fd, "%s,%s,*\n", triple[0], triple[1]); | 1076 if (!g_ascii_strcasecmp(triple[0],ourhost)) { |
976 } else if (!g_ascii_strcasecmp(triple[2], gaim_zephyr_get_sender())) { | 1077 zclass = g_strdup("%host%");; |
977 fprintf(fd, "%s,%s,%%me%%\n", triple[0], triple[1]); | 1078 } else if (!g_ascii_strcasecmp(triple[0],ourhostcanon)) { |
1079 zclass = g_strdup("%canon%");; | |
1080 } else { | |
1081 zclass = g_strdup(triple[0]); | |
1082 } | |
1083 | |
1084 /* deal with instances */ | |
1085 | |
1086 if (!g_ascii_strcasecmp(triple[1],ourhost)) { | |
1087 zinst = g_strdup("%host%");; | |
1088 } else if (!g_ascii_strcasecmp(triple[1],ourhostcanon)) { | |
1089 zinst = g_strdup("%canon%");; | |
978 } else { | 1090 } else { |
979 fprintf(fd, "%s\n", zt->name); | 1091 zinst = g_strdup(triple[1]); |
980 } | 1092 } |
1093 | |
1094 /* deal with recipients */ | |
1095 if (triple[2] == NULL) { | |
1096 zrecip = g_strdup("*"); | |
1097 } else if (!g_ascii_strcasecmp(triple[2],"")){ | |
1098 zrecip = g_strdup("*"); | |
1099 } else if (!g_ascii_strcasecmp(triple[2], gaim_zephyr_get_sender())) { | |
1100 zrecip = g_strdup("%me%"); | |
981 } else { | 1101 } else { |
982 fprintf(fd, "%s,%s,*\n", triple[0], triple[1]); | 1102 zrecip = g_strdup(triple[2]); |
983 } | 1103 } |
1104 | |
1105 fprintf(fd, "%s,%s,%s\n",zclass,zinst,zrecip); | |
1106 | |
1107 g_free(zclass); | |
1108 g_free(zinst); | |
1109 g_free(zrecip); | |
984 g_free(triple); | 1110 g_free(triple); |
985 s = s->next; | 1111 s = s->next; |
986 } | 1112 } |
987 g_free(fname); | 1113 g_free(fname); |
988 fclose(fd); | 1114 fclose(fd); |
1070 z_call(ZUnsetLocation()); | 1196 z_call(ZUnsetLocation()); |
1071 z_call(ZClosePort()); | 1197 z_call(ZClosePort()); |
1072 } | 1198 } |
1073 | 1199 |
1074 static int zephyr_send_message(char* zclass, char* instance, char* recipient, const char *im, | 1200 static int zephyr_send_message(char* zclass, char* instance, char* recipient, const char *im, |
1075 const char *sig) ; | 1201 const char *sig, char *opcode) ; |
1076 | 1202 |
1077 const char * zephyr_get_signature() | 1203 const char * zephyr_get_signature() |
1078 { | 1204 { |
1079 const char * sig; | 1205 /* XXX add zephyr error reporting */ |
1080 sig = ZGetVariable("zwrite-signature"); | 1206 const char * sig =ZGetVariable("zwrite-signature"); |
1081 if (!sig) { | 1207 if (!sig) { |
1082 sig = g_get_real_name(); | 1208 sig = g_get_real_name(); |
1083 } | 1209 } |
1084 return sig; | 1210 return sig; |
1085 } | 1211 } |
1109 if (!g_ascii_strcasecmp(zt->recipient, "*")) | 1235 if (!g_ascii_strcasecmp(zt->recipient, "*")) |
1110 recipient = local_zephyr_normalize(""); | 1236 recipient = local_zephyr_normalize(""); |
1111 else | 1237 else |
1112 recipient = local_zephyr_normalize(zt->recipient); | 1238 recipient = local_zephyr_normalize(zt->recipient); |
1113 | 1239 |
1114 zephyr_send_message(zt->class,inst,recipient,im,sig); | 1240 zephyr_send_message(zt->class,inst,recipient,im,sig,""); |
1115 /* g_free(inst); */ | 1241 /* g_free(inst); */ |
1116 /* g_free(recipient); */ | 1242 /* g_free(recipient); */ |
1117 return 0; | 1243 return 0; |
1118 } | 1244 } |
1119 | 1245 |
1125 if (flags & GAIM_CONV_IM_AUTO_RESP) | 1251 if (flags & GAIM_CONV_IM_AUTO_RESP) |
1126 sig = "Automated reply:"; | 1252 sig = "Automated reply:"; |
1127 else { | 1253 else { |
1128 sig = zephyr_get_signature(); | 1254 sig = zephyr_get_signature(); |
1129 } | 1255 } |
1130 zephyr_send_message("MESSAGE","PERSONAL",local_zephyr_normalize(who),im,sig); | 1256 zephyr_send_message("MESSAGE","PERSONAL",local_zephyr_normalize(who),im,sig,""); |
1131 | 1257 |
1132 return 1; | 1258 return 1; |
1133 } | 1259 } |
1134 | 1260 |
1135 static int zephyr_send_message(char* zclass, char* instance, char* recipient, const char *im, | 1261 static int zephyr_send_message(char* zclass, char* instance, char* recipient, const char *im, |
1136 const char *sig) | 1262 const char *sig, char *opcode) |
1137 { | 1263 { |
1138 char *html_buf; | 1264 char *html_buf; |
1139 char *html_buf2; | 1265 char *html_buf2; |
1140 char *buf; | 1266 char *buf; |
1141 ZNotice_t notice; | 1267 ZNotice_t notice; |
1154 notice.z_recipient = recipient; | 1280 notice.z_recipient = recipient; |
1155 notice.z_sender = 0; | 1281 notice.z_sender = 0; |
1156 notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2"; | 1282 notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2"; |
1157 notice.z_message_len = strlen(html_buf2) + strlen(sig) + 2; | 1283 notice.z_message_len = strlen(html_buf2) + strlen(sig) + 2; |
1158 notice.z_message = buf; | 1284 notice.z_message = buf; |
1285 notice.z_opcode = g_strdup(opcode); | |
1286 gaim_debug_info("zephyr","About to send notice"); | |
1287 if (! ZSendNotice(¬ice, ZAUTH) == ZERR_NONE) { | |
1288 /* XXX handle errors here */ | |
1289 return 0; | |
1290 } | |
1291 gaim_debug_info("zephyr","notice sent"); | |
1292 g_free(buf); | |
1293 | |
1159 g_free(html_buf2); | 1294 g_free(html_buf2); |
1160 g_free(html_buf); | 1295 g_free(html_buf); |
1161 | 1296 |
1162 ZSendNotice(¬ice, ZAUTH); | |
1163 g_free(buf); | |
1164 return 1; | 1297 return 1; |
1165 } | 1298 } |
1166 | 1299 |
1167 static const char *zephyr_normalize(const GaimAccount * account, const char *orig) | 1300 static const char *zephyr_normalize(const GaimAccount * account, const char *orig) |
1168 { | 1301 { |
1205 gchar* normalized_who = local_zephyr_normalize(who); | 1338 gchar* normalized_who = local_zephyr_normalize(who); |
1206 | 1339 |
1207 if (ZRequestLocations(normalized_who, &ald, UNACKED, ZAUTH) == ZERR_NONE) { | 1340 if (ZRequestLocations(normalized_who, &ald, UNACKED, ZAUTH) == ZERR_NONE) { |
1208 pending_zloc_names = g_list_append(pending_zloc_names, | 1341 pending_zloc_names = g_list_append(pending_zloc_names, |
1209 g_strdup(normalized_who)); | 1342 g_strdup(normalized_who)); |
1343 } else { | |
1344 /* XXX deal with errors somehow */ | |
1210 } | 1345 } |
1211 } | 1346 } |
1212 | 1347 |
1213 static void zephyr_set_away(GaimConnection * gc, const char *state, const char *msg) | 1348 static void zephyr_set_away(GaimConnection * gc, const char *state, const char *msg) |
1214 { | 1349 { |
1216 g_free(gc->away); | 1351 g_free(gc->away); |
1217 gc->away = NULL; | 1352 gc->away = NULL; |
1218 } | 1353 } |
1219 | 1354 |
1220 if (!g_ascii_strcasecmp(state, _("Hidden"))) { | 1355 if (!g_ascii_strcasecmp(state, _("Hidden"))) { |
1356 /* XXX handle errors */ | |
1221 ZSetLocation(EXPOSE_OPSTAFF); | 1357 ZSetLocation(EXPOSE_OPSTAFF); |
1222 gc->away = g_strdup(""); | 1358 gc->away = g_strdup(""); |
1223 } else if (!g_ascii_strcasecmp(state, _("Online"))) | 1359 } |
1360 else if (!g_ascii_strcasecmp(state, _("Online"))) { | |
1361 /* XXX handle errors */ | |
1224 ZSetLocation(get_exposure_level()); | 1362 ZSetLocation(get_exposure_level()); |
1363 } | |
1225 else /* state is GAIM_AWAY_CUSTOM */ if (msg) | 1364 else /* state is GAIM_AWAY_CUSTOM */ if (msg) |
1226 gc->away = g_strdup(msg); | 1365 gc->away = g_strdup(msg); |
1227 } | 1366 } |
1228 | 1367 |
1229 static GList *zephyr_away_states(GaimConnection * gc) | 1368 static GList *zephyr_away_states(GaimConnection * gc) |
1259 pce->label = _("_Recipient:"); | 1398 pce->label = _("_Recipient:"); |
1260 pce->identifier = "recipient"; | 1399 pce->identifier = "recipient"; |
1261 m = g_list_append(m, pce); | 1400 m = g_list_append(m, pce); |
1262 | 1401 |
1263 return m; | 1402 return m; |
1403 } | |
1404 | |
1405 /* Called when the server notifies us a message couldn't get sent */ | |
1406 | |
1407 static void zephyr_subscribe_failed(ZSubscription_t *sub) | |
1408 { | |
1409 gchar* subscribe_failed = g_strdup_printf(_("Attempt to subscribe to %s,%s,%s failed"), sub->zsub_class, sub->zsub_classinst,sub->zsub_recipient); | |
1410 gaim_notify_error(zgc,"", subscribe_failed, NULL); | |
1411 g_free(subscribe_failed); | |
1264 } | 1412 } |
1265 | 1413 |
1266 static void zephyr_join_chat(GaimConnection * gc, GHashTable * data) | 1414 static void zephyr_join_chat(GaimConnection * gc, GHashTable * data) |
1267 { | 1415 { |
1268 ZSubscription_t sub; | 1416 ZSubscription_t sub; |
1273 | 1421 |
1274 classname = g_hash_table_lookup(data, "class"); | 1422 classname = g_hash_table_lookup(data, "class"); |
1275 instname = g_hash_table_lookup(data, "instance"); | 1423 instname = g_hash_table_lookup(data, "instance"); |
1276 recip = g_hash_table_lookup(data, "recipient"); | 1424 recip = g_hash_table_lookup(data, "recipient"); |
1277 | 1425 |
1426 | |
1278 if (!classname) | 1427 if (!classname) |
1279 return; | 1428 return; |
1429 | |
1430 if (!g_ascii_strcasecmp(classname,"%host%")) | |
1431 classname = g_strdup(ourhost); | |
1432 if (!g_ascii_strcasecmp(classname,"%canon%")) | |
1433 classname = g_strdup(ourhostcanon); | |
1434 | |
1280 if (!instname || !strlen(instname)) | 1435 if (!instname || !strlen(instname)) |
1281 instname = "*"; | 1436 instname = "*"; |
1437 | |
1438 if (!g_ascii_strcasecmp(instname,"%host%")) | |
1439 instname = g_strdup(ourhost); | |
1440 if (!g_ascii_strcasecmp(instname,"%canon%")) | |
1441 instname = g_strdup(ourhostcanon); | |
1442 | |
1282 if (!recip || (*recip == '*')) | 1443 if (!recip || (*recip == '*')) |
1283 recip = ""; | 1444 recip = ""; |
1284 if (!g_ascii_strcasecmp(recip, "%me%")) | 1445 if (!g_ascii_strcasecmp(recip, "%me%")) |
1285 recip = gaim_zephyr_get_sender(); | 1446 recip = gaim_zephyr_get_sender(); |
1286 | 1447 |
1301 sub.zsub_class = zt1->class; | 1462 sub.zsub_class = zt1->class; |
1302 sub.zsub_classinst = zt1->instance; | 1463 sub.zsub_classinst = zt1->instance; |
1303 sub.zsub_recipient = zt1->recipient; | 1464 sub.zsub_recipient = zt1->recipient; |
1304 | 1465 |
1305 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { | 1466 if (ZSubscribeTo(&sub, 1, 0) != ZERR_NONE) { |
1467 /* XXX output better subscription information */ | |
1468 zephyr_subscribe_failed(&sub); | |
1306 free_triple(zt1); | 1469 free_triple(zt1); |
1307 return; | 1470 return; |
1308 } | 1471 } |
1309 | 1472 |
1310 subscrips = g_slist_append(subscrips, zt1); | 1473 subscrips = g_slist_append(subscrips, zt1); |
1324 zt->open = FALSE; | 1487 zt->open = FALSE; |
1325 zt->id = ++last_id; | 1488 zt->id = ++last_id; |
1326 } | 1489 } |
1327 } | 1490 } |
1328 | 1491 |
1492 static GaimChat *zephyr_find_blist_chat(GaimAccount *account, const char *name) | |
1493 { | |
1494 GaimBlistNode *gnode, *cnode; | |
1495 | |
1496 /* XXX needs to be %host%,%canon%, and %me% clean */ | |
1497 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { | |
1498 for(cnode = gnode->child; cnode; cnode = cnode->next) { | |
1499 GaimChat *chat = (GaimChat*)cnode; | |
1500 char *zclass, *inst, *recip; | |
1501 char** triple; | |
1502 if(!GAIM_BLIST_NODE_IS_CHAT(cnode)) | |
1503 continue; | |
1504 if(chat->account !=account) | |
1505 continue; | |
1506 if(!(zclass = g_hash_table_lookup(chat->components, "class"))) | |
1507 continue; | |
1508 if(!(inst = g_hash_table_lookup(chat->components, "instance"))) | |
1509 inst = g_strdup(""); | |
1510 if(!(recip = g_hash_table_lookup(chat->components, "recipient"))) | |
1511 recip = g_strdup(""); | |
1512 triple = g_strsplit(name,",",3); | |
1513 if (!g_ascii_strcasecmp(triple[0],zclass) && !g_ascii_strcasecmp(triple[1],inst) && !g_ascii_strcasecmp(triple[2],recip)) | |
1514 return chat; | |
1515 | |
1516 } | |
1517 } | |
1518 return NULL; | |
1519 } | |
1329 static const char *zephyr_list_icon(GaimAccount * a, GaimBuddy * b) | 1520 static const char *zephyr_list_icon(GaimAccount * a, GaimBuddy * b) |
1330 { | 1521 { |
1331 return "zephyr"; | 1522 return "zephyr"; |
1332 } | 1523 } |
1333 | 1524 |
1525 static int zephyr_send_typing(GaimConnection *gc, const char *who, int typing) { | |
1526 gchar *recipient; | |
1527 if (!typing) | |
1528 return 0; | |
1529 /* XXX We probably should care if this fails. Or maybe we don't want to */ | |
1530 if (!who) { | |
1531 gaim_debug_info("zephyr", "who is null\n"); | |
1532 recipient = local_zephyr_normalize(""); | |
1533 } else { | |
1534 recipient = local_zephyr_normalize(who); | |
1535 } | |
1536 | |
1537 gaim_debug_info("zephyr","about to send typing notification to %s",recipient); | |
1538 zephyr_send_message("MESSAGE","PERSONAL",recipient,"","","PING"); | |
1539 gaim_debug_info("zephyr","sent typing notification"); | |
1540 return ZEPHYR_TYPING_SEND_TIMEOUT; | |
1541 } | |
1334 | 1542 |
1335 | 1543 |
1336 | 1544 |
1337 static void zephyr_chat_set_topic(GaimConnection * gc, int id, const char *topic) | 1545 static void zephyr_chat_set_topic(GaimConnection * gc, int id, const char *topic) |
1338 { | 1546 { |
1356 | 1564 |
1357 static GaimCmdRet zephyr_gaim_cmd_msg(GaimConversation *conv, | 1565 static GaimCmdRet zephyr_gaim_cmd_msg(GaimConversation *conv, |
1358 const char *cmd, char **args, char **error) | 1566 const char *cmd, char **args, char **error) |
1359 { | 1567 { |
1360 char *recipient; | 1568 char *recipient; |
1569 | |
1361 if (!g_ascii_strcasecmp(args[0],"*")) | 1570 if (!g_ascii_strcasecmp(args[0],"*")) |
1362 recipient = local_zephyr_normalize(""); | 1571 return GAIM_CMD_RET_FAILED; /* "*" is not a valid argument */ |
1363 else | 1572 else |
1364 recipient = local_zephyr_normalize(args[0]); | 1573 recipient = local_zephyr_normalize(args[0]); |
1365 | 1574 |
1366 if (zephyr_send_message("MESSAGE","PERSONAL",recipient,args[1],zephyr_get_signature())) | 1575 if (strlen(recipient) < 1) |
1576 return GAIM_CMD_RET_FAILED; /* a null recipient is a chat message, not an IM */ | |
1577 | |
1578 if (zephyr_send_message("MESSAGE","PERSONAL",recipient,args[1],zephyr_get_signature(),"")) | |
1367 return GAIM_CMD_RET_OK; | 1579 return GAIM_CMD_RET_OK; |
1368 else | 1580 else |
1369 return GAIM_CMD_RET_FAILED; | 1581 return GAIM_CMD_RET_FAILED; |
1370 } | 1582 } |
1371 | 1583 |
1404 | 1616 |
1405 static GaimCmdRet zephyr_gaim_cmd_zi(GaimConversation *conv, | 1617 static GaimCmdRet zephyr_gaim_cmd_zi(GaimConversation *conv, |
1406 const char *cmd, char **args, char **error) | 1618 const char *cmd, char **args, char **error) |
1407 { | 1619 { |
1408 /* args = instance, message */ | 1620 /* args = instance, message */ |
1409 if (zephyr_send_message("message",args[0],"",args[1],zephyr_get_signature())) | 1621 if ( zephyr_send_message("message",args[0],"",args[1],zephyr_get_signature(),"")) |
1410 return GAIM_CMD_RET_OK; | 1622 return GAIM_CMD_RET_OK; |
1411 else | 1623 else |
1412 return GAIM_CMD_RET_FAILED; | 1624 return GAIM_CMD_RET_FAILED; |
1413 } | 1625 } |
1414 | 1626 |
1415 static GaimCmdRet zephyr_gaim_cmd_zci(GaimConversation *conv, | 1627 static GaimCmdRet zephyr_gaim_cmd_zci(GaimConversation *conv, |
1416 const char *cmd, char **args, char **error) | 1628 const char *cmd, char **args, char **error) |
1417 { | 1629 { |
1418 /* args = class, instance, message */ | 1630 /* args = class, instance, message */ |
1419 if ( zephyr_send_message(args[0],args[1],"",args[2],zephyr_get_signature())) | 1631 if ( zephyr_send_message(args[0],args[1],"",args[2],zephyr_get_signature(),"")) |
1420 return GAIM_CMD_RET_OK; | 1632 return GAIM_CMD_RET_OK; |
1421 else | 1633 else |
1422 return GAIM_CMD_RET_FAILED; | 1634 return GAIM_CMD_RET_FAILED; |
1423 } | 1635 } |
1424 | 1636 |
1425 static GaimCmdRet zephyr_gaim_cmd_zcir(GaimConversation *conv, | 1637 static GaimCmdRet zephyr_gaim_cmd_zcir(GaimConversation *conv, |
1426 const char *cmd, char **args, char **error) | 1638 const char *cmd, char **args, char **error) |
1427 { | 1639 { |
1428 /* args = class, instance, recipient, message */ | 1640 /* args = class, instance, recipient, message */ |
1429 if ( zephyr_send_message(args[0],args[1],args[2],args[3],zephyr_get_signature())) | 1641 if ( zephyr_send_message(args[0],args[1],args[2],args[3],zephyr_get_signature(),"")) |
1430 return GAIM_CMD_RET_OK; | 1642 return GAIM_CMD_RET_OK; |
1431 else | 1643 else |
1432 return GAIM_CMD_RET_FAILED; | 1644 return GAIM_CMD_RET_FAILED; |
1433 } | 1645 } |
1434 | 1646 |
1435 static GaimCmdRet zephyr_gaim_cmd_zir(GaimConversation *conv, | 1647 static GaimCmdRet zephyr_gaim_cmd_zir(GaimConversation *conv, |
1436 const char *cmd, char **args, char **error) | 1648 const char *cmd, char **args, char **error) |
1437 { | 1649 { |
1438 /* args = instance, recipient, message */ | 1650 /* args = instance, recipient, message */ |
1439 if ( zephyr_send_message("message",args[0],args[1],args[2],zephyr_get_signature())) | 1651 if ( zephyr_send_message("message",args[0],args[1],args[2],zephyr_get_signature(),"")) |
1440 return GAIM_CMD_RET_OK; | 1652 return GAIM_CMD_RET_OK; |
1441 else | 1653 else |
1442 return GAIM_CMD_RET_FAILED; | 1654 return GAIM_CMD_RET_FAILED; |
1443 } | 1655 } |
1444 | 1656 |
1445 static GaimCmdRet zephyr_gaim_cmd_zc(GaimConversation *conv, | 1657 static GaimCmdRet zephyr_gaim_cmd_zc(GaimConversation *conv, |
1446 const char *cmd, char **args, char **error) | 1658 const char *cmd, char **args, char **error) |
1447 { | 1659 { |
1448 /* args = class, message */ | 1660 /* args = class, message */ |
1449 if ( zephyr_send_message(args[0],"PERSONAL","",args[1],zephyr_get_signature())) | 1661 if ( zephyr_send_message(args[0],"PERSONAL","",args[1],zephyr_get_signature(),"")) |
1450 return GAIM_CMD_RET_OK; | 1662 return GAIM_CMD_RET_OK; |
1451 else | 1663 else |
1452 return GAIM_CMD_RET_FAILED; | 1664 return GAIM_CMD_RET_FAILED; |
1453 } | 1665 } |
1454 | 1666 |
1528 while (s) { | 1740 while (s) { |
1529 zt = s->data; | 1741 zt = s->data; |
1530 zst.zsub_class = zt->class; | 1742 zst.zsub_class = zt->class; |
1531 zst.zsub_classinst = zt->instance; | 1743 zst.zsub_classinst = zt->instance; |
1532 zst.zsub_recipient = zt->recipient; | 1744 zst.zsub_recipient = zt->recipient; |
1533 ZSubscribeTo(&zst, 1, 0); | |
1534 /* XXX We really should care if this fails */ | 1745 /* XXX We really should care if this fails */ |
1746 ZSubscribeTo(&zst, 1, 0); | |
1535 s = s->next; | 1747 s = s->next; |
1536 } | 1748 } |
1537 /* XXX handle unsubscriptions */ | 1749 /* XXX handle unsubscriptions */ |
1538 return 1; | 1750 return 1; |
1539 } | 1751 } |
1545 GaimConnection *gc = (GaimConnection *) action->context; | 1757 GaimConnection *gc = (GaimConnection *) action->context; |
1546 zephyr_resubscribe(gc); | 1758 zephyr_resubscribe(gc); |
1547 } | 1759 } |
1548 | 1760 |
1549 | 1761 |
1762 static void zephyr_action_get_subs_from_server(GaimPluginAction *action) | |
1763 { | |
1764 GaimConnection *gc = (GaimConnection *) action->context; | |
1765 gchar *title; | |
1766 int retval, nsubs, one,i; | |
1767 ZSubscription_t subs; | |
1768 GString* subout = g_string_new("Subscription list<br>"); | |
1769 | |
1770 title = g_strdup_printf("Server subscriptions for %s", gaim_zephyr_get_sender()); | |
1771 | |
1772 if (zephyr_port == 0) { | |
1773 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving port"); | |
1774 return; | |
1775 } | |
1776 if ((retval = ZRetrieveSubscriptions(zephyr_port,&nsubs)) != ZERR_NONE) { | |
1777 /* XXX better error handling */ | |
1778 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving subscriptions from server"); | |
1779 return; | |
1780 } | |
1781 g_string_append_printf(subout,"Subscription list <br>"); | |
1782 for(i=0;i<nsubs;i++) { | |
1783 one = 1; | |
1784 if ((retval = ZGetSubscriptions(&subs,&one)) != ZERR_NONE) { | |
1785 /* XXX better error handling */ | |
1786 gaim_debug(GAIM_DEBUG_ERROR,"zephyr", "error while retrieving individual subscription"); | |
1787 return; | |
1788 } | |
1789 g_string_append_printf(subout, "Class %s Instance %s Recipient %s<br>", | |
1790 subs.zsub_class, subs.zsub_classinst, | |
1791 subs.zsub_recipient); | |
1792 } | |
1793 gaim_notify_formatted(gc, title, title, NULL, subout->str, NULL, NULL); | |
1794 } | |
1795 | |
1796 | |
1550 static GList *zephyr_actions(GaimPlugin *plugin, gpointer context) | 1797 static GList *zephyr_actions(GaimPlugin *plugin, gpointer context) |
1551 { | 1798 { |
1552 GList *list = NULL; | 1799 GList *list = NULL; |
1553 GaimPluginAction *act = NULL; | 1800 GaimPluginAction *act = NULL; |
1554 | 1801 |
1555 act = gaim_plugin_action_new(_("Resubscribe"), zephyr_action_resubscribe); | 1802 act = gaim_plugin_action_new(_("Resubscribe"), zephyr_action_resubscribe); |
1556 list = g_list_append(list, act); | 1803 list = g_list_append(list, act); |
1804 | |
1805 act = gaim_plugin_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server); | |
1806 list = g_list_append(list,act); | |
1557 | 1807 |
1558 return list; | 1808 return list; |
1559 } | 1809 } |
1560 | 1810 |
1561 static GaimPlugin *my_protocol = NULL; | 1811 static GaimPlugin *my_protocol = NULL; |
1562 | 1812 |
1563 static GaimPluginProtocolInfo prpl_info = { | 1813 static GaimPluginProtocolInfo prpl_info = { |
1564 GAIM_PRPL_API_VERSION, | 1814 GAIM_PRPL_API_VERSION, |
1565 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD, | 1815 OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD, |
1566 NULL, /* user_splits */ | 1816 NULL, /* ??? user_splits */ |
1567 NULL, /* protocol_options */ | 1817 NULL, /* ??? protocol_options */ |
1568 NO_BUDDY_ICONS, /* icon_spec */ | 1818 NO_BUDDY_ICONS, |
1569 zephyr_list_icon, /* list_icon */ | 1819 zephyr_list_icon, |
1570 NULL, /* list_emblems */ | 1820 NULL, /* ??? list_emblems */ |
1571 NULL, /* status_text */ | 1821 NULL, /* ??? status_text */ |
1572 NULL, /* tooltip_text */ | 1822 NULL, /* ??? tooltip_text */ |
1573 zephyr_away_states, /* away_states */ | 1823 zephyr_away_states, /* away_states */ |
1574 NULL, /* blist_node_menu */ | 1824 NULL, /* ??? blist_node_menu - probably all useful actions are already handled*/ |
1575 zephyr_chat_info, /* chat_info */ | 1825 zephyr_chat_info, /* chat_info */ |
1576 zephyr_login, /* login */ | 1826 zephyr_login, /* login */ |
1577 zephyr_close, /* close */ | 1827 zephyr_close, /* close */ |
1578 zephyr_send_im, /* send_im */ | 1828 zephyr_send_im, /* send_im */ |
1579 NULL, /* set_info */ | 1829 NULL, /* XXX set info (Location?) */ |
1580 NULL, /* send_typing */ | 1830 zephyr_send_typing, /* send_typing */ |
1581 zephyr_zloc, /* get_info */ | 1831 zephyr_zloc, /* get_info */ |
1582 zephyr_set_away, /* set_away */ | 1832 zephyr_set_away, /* XXX set_away need to fix */ |
1583 NULL, /* set_idle */ | 1833 NULL, /* ??? set idle */ |
1584 NULL, /* change_passwd */ | 1834 NULL, /* change password */ |
1585 NULL, /* add_buddy */ | 1835 NULL, /* add_buddy */ |
1586 NULL, /* add_buddies */ | 1836 NULL, /* add_buddies */ |
1587 NULL, /* remove_buddy */ | 1837 NULL, /* remove_buddy */ |
1588 NULL, /* remove_buddies */ | 1838 NULL, /* remove_buddies */ |
1589 NULL, /* add_permit */ | 1839 NULL, /* add_permit -- not useful, since anyone can zephyr you by default*/ |
1590 NULL, /* add_deny */ | 1840 NULL, /* XXX add deny -- maybe put an auto "I'm ignoring your zephyrs*/ |
1591 NULL, /* rem_permit */ | 1841 NULL, /* remove_permit -- not useful, see add permit */ |
1592 NULL, /* rem_deny */ | 1842 NULL, /* XXX remove deny -- remove above deny, */ |
1593 NULL, /* set_permit_deny */ | 1843 NULL, /* ??? set permit deny */ |
1594 NULL, /* warn */ | 1844 NULL, /* --- warn */ |
1595 zephyr_join_chat, /* join_chat */ | 1845 zephyr_join_chat, /* join_chat */ |
1596 NULL, /* reject_chat */ | 1846 NULL, /* reject_chat */ |
1597 NULL, /* chat_invite */ | 1847 NULL, /* chat_invite */ |
1598 zephyr_chat_leave, /* chat_leave */ | 1848 zephyr_chat_leave, /* chat_leave */ |
1599 NULL, /* chat_whisper */ | 1849 NULL, /* chat_whisper */ |
1600 zephyr_chat_send, /* chat_send */ | 1850 zephyr_chat_send, /* chat_send */ |
1601 NULL, /* keepalive */ | 1851 NULL, /* keepalive */ |
1602 NULL, /* register_user */ | 1852 NULL, /* register_user */ |
1603 NULL, /* get_cb_info */ | 1853 NULL, /* XXX get_cb_info get chat buddy info */ |
1604 NULL, /* get_cb_away */ | 1854 NULL, /* get_cb_away */ |
1605 NULL, /* alias_buddy */ | 1855 NULL, /* alias_buddy */ |
1606 NULL, /* group_buddy */ | 1856 NULL, /* group_buddy */ |
1607 NULL, /* rename_group */ | 1857 NULL, /* rename_group */ |
1608 NULL, /* buddy_free */ | 1858 NULL, /* ??? buddy_free */ |
1609 NULL, /* convo_closed */ | 1859 NULL, /* convo_closed */ |
1610 zephyr_normalize, /* normalize */ | 1860 zephyr_normalize, /* normalize */ |
1611 NULL, /* set_buddy_icon */ | 1861 NULL, /* XXX set_buddy_icon */ |
1612 NULL, /* remove_group */ | 1862 NULL, /* remove_group */ |
1613 NULL, /* get_cb_real_name */ | 1863 NULL, /* XXX get_cb_real_name */ |
1614 zephyr_chat_set_topic, /* set_chat_topic */ | 1864 zephyr_chat_set_topic, /* set_chat_topic */ |
1615 NULL, /* find_blist_chat */ | 1865 zephyr_find_blist_chat, /* find_blist_chat */ |
1616 NULL, /* roomlist_get_list */ | 1866 NULL, /* roomlist_get_list */ |
1617 NULL, /* roomlist_cancel */ | 1867 NULL, /* roomlist_cancel */ |
1618 NULL, /* roomlist_expand_category */ | 1868 NULL, /* roomlist_expand_category */ |
1619 NULL, /* can_receive_file */ | 1869 NULL, /* can_receive_file */ |
1620 NULL /* send_file */ | 1870 NULL /* send_file */ |
1621 }; | 1871 }; |
1622 | 1872 |
1623 static GaimPluginInfo info = { | 1873 static GaimPluginInfo info = { |